1 19 20 package org.netbeans.modules.tomcat5.customizer; 21 22 import java.awt.Component ; 23 import java.awt.GridBagConstraints ; 24 import java.awt.GridBagLayout ; 25 import java.awt.Insets ; 26 import java.awt.event.ActionEvent ; 27 import java.awt.event.ActionListener ; 28 import java.io.File ; 29 import java.net.MalformedURLException ; 30 import java.net.URI ; 31 import java.net.URL ; 32 import java.util.ArrayList ; 33 import java.util.Arrays ; 34 import java.util.Collection ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.StringTokenizer ; 38 import javax.swing.AbstractListModel ; 39 import javax.swing.JButton ; 40 import javax.swing.JFileChooser ; 41 import javax.swing.JLabel ; 42 import javax.swing.JList ; 43 import javax.swing.JPanel ; 44 import javax.swing.JScrollPane ; 45 import javax.swing.event.ListSelectionEvent ; 46 import javax.swing.event.ListSelectionListener ; 47 import javax.swing.filechooser.FileFilter ; 48 import org.netbeans.modules.j2ee.deployment.common.api.J2eeLibraryTypeProvider; 49 import org.openide.ErrorManager; 50 import org.openide.NotifyDescriptor; 51 import org.openide.filesystems.FileUtil; 52 import org.openide.util.NbBundle; 53 54 62 public final class CustomizerSupport { 63 64 private static final String CLASSPATH = J2eeLibraryTypeProvider.VOLUME_TYPE_CLASSPATH; 65 private static final String SOURCES = J2eeLibraryTypeProvider.VOLUME_TYPE_SRC; 66 private static final String JAVADOC = J2eeLibraryTypeProvider.VOLUME_TYPE_JAVADOC; 67 68 69 private CustomizerSupport() { 70 } 71 72 81 public static Component createClassesCustomizer(PathModel model) { 82 if (model == null) { 83 throw new NullPointerException (); 84 } 85 return new PathView(model, CLASSPATH, null); 86 } 87 88 99 public static Component createSourcesCustomizer(PathModel model, File currentDir) { 100 if (model == null) { 101 throw new NullPointerException (); 102 } 103 return new PathView(model, SOURCES, currentDir); 104 } 105 106 117 public static Component createJavadocCustomizer(PathModel model, File currentDir) { 118 if (model == null) { 119 throw new NullPointerException (); 120 } 121 return new PathView(model, JAVADOC, currentDir); 122 } 123 124 131 public static String buildPath(List <URL > path) { 132 String PATH_SEPARATOR = System.getProperty("path.separator"); StringBuffer sb = new StringBuffer (path.size() * 16); 134 for (Iterator <URL > i = path.iterator(); i.hasNext(); ) { 135 sb.append(urlToString(i.next())); 136 if (i.hasNext()) { 137 sb.append(PATH_SEPARATOR); 138 } 139 } 140 return sb.toString(); 141 } 142 143 152 public static List <URL > tokenizePath(String path) { 153 try { 154 List <URL > l = new ArrayList (); 155 StringTokenizer tok = new StringTokenizer (path, ":;", true); char dosHack = '\0'; 157 char lastDelim = '\0'; 158 int delimCount = 0; 159 while (tok.hasMoreTokens()) { 160 String s = tok.nextToken(); 161 if (s.length() == 0) { 162 continue; 164 } 165 if (s.length() == 1) { 166 char c = s.charAt(0); 167 if (c == ':' || c == ';') { 168 lastDelim = c; 170 delimCount++; 171 continue; 172 } 173 } 174 if (dosHack != '\0') { 175 if (lastDelim == ':' && delimCount == 1 && (s.charAt(0) == '\\' || s.charAt(0) == '/')) { 177 s = "" + dosHack + ':' + s; 179 } else { 181 l.add(fileToUrl(new File (Character.toString(dosHack)))); 183 } 185 dosHack = '\0'; 186 } 187 delimCount = 0; 189 if (s.length() == 1) { 190 char c = s.charAt(0); 191 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 192 dosHack = c; 194 continue; 195 } 196 } 197 l.add(fileToUrl(new File (s))); 198 } 199 if (dosHack != '\0') { 200 l.add(fileToUrl(new File (Character.toString(dosHack)))); 204 } 205 return l; 206 } catch (MalformedURLException e) { 207 ErrorManager.getDefault().notify(e); 208 return new ArrayList (); 209 } 210 } 211 212 213 private static URL fileToUrl(File file) throws MalformedURLException { 214 URL url = file.toURI().toURL(); 215 if (FileUtil.isArchiveFile(url)) { 216 url = FileUtil.getArchiveRoot(url); 217 } 218 return url; 219 } 220 221 222 private static String urlToString(URL url) { 223 if ("jar".equals(url.getProtocol())) { URL fileURL = FileUtil.getArchiveFile(url); 225 if (FileUtil.getArchiveRoot(fileURL).equals(url)) { 226 url = fileURL; 228 } else { 229 return url.toExternalForm(); 231 } 232 } 233 if ("file".equals(url.getProtocol())) { File f = new File (URI.create(url.toExternalForm())); 235 return f.getAbsolutePath(); 236 } 237 else { 238 return url.toExternalForm(); 239 } 240 } 241 242 245 public static final class PathModel extends AbstractListModel { 246 247 private final List <URL > data; 248 249 256 public PathModel(List <URL > data) { 257 if (data == null) { 258 throw new NullPointerException ("The data attribute must not be null."); } 260 this.data = data; 261 } 262 263 268 public int getSize() { 269 return data.size(); 270 } 271 272 279 public Object getElementAt(int index) { 280 URL url = data.get(index); 281 if ("jar".equals(url.getProtocol())) { URL fileURL = FileUtil.getArchiveFile(url); 283 if (FileUtil.getArchiveRoot(fileURL).equals(url)) { 284 url = fileURL; 286 } else { 287 return url.toExternalForm(); 289 } 290 } 291 if ("file".equals(url.getProtocol())) { File f = new File (URI.create(url.toExternalForm())); 293 return f.getAbsolutePath(); 294 } 295 else { 296 return url.toExternalForm(); 297 } 298 } 299 300 303 public void removePath(int[] indices) { 304 for (int i = indices.length - 1; i >= 0; i--) { 305 data.remove(indices[i]); 306 } 307 fireIntervalRemoved(this, indices[0], indices[indices.length - 1]); 308 } 309 310 313 public void moveUpPath(int[] indices) { 314 for (int i = 0; i < indices.length; i++) { 315 URL p2 = data.get(indices[i]); 316 URL p1 = data.set(indices[i] - 1, p2); 317 data.set(indices[i], p1); 318 } 319 fireContentsChanged(this, indices[0] - 1, indices[indices.length - 1]); 320 } 321 322 325 public void moveDownPath(int[] indices) { 326 for (int i = indices.length - 1; i >= 0; i--) { 327 URL p1 = data.get(indices[i]); 328 URL p2 = data.set(indices[i] + 1, p1); 329 data.set(indices[i], p2); 330 } 331 fireContentsChanged(this, indices[0], indices[indices.length - 1] + 1); 332 } 333 334 339 public boolean addPath(File f) { 340 try { 341 URL url = f.toURI().toURL(); 342 return this.addPath(url); 343 } catch (MalformedURLException mue) { 344 return false; 345 } 346 } 347 348 353 public boolean addPath(URL url) { 354 if (FileUtil.isArchiveFile(url)) { 355 url = FileUtil.getArchiveRoot(url); 356 } else if (!url.toExternalForm().endsWith("/")) { try { 358 url = new URL (url.toExternalForm() + "/"); } catch (MalformedURLException mue) { 360 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, mue); 361 } 362 } 363 int oldSize = data.size(); 364 data.add(url); 365 fireIntervalAdded(this, oldSize, oldSize); 366 return true; 367 } 368 369 373 public List <URL > getData() { 374 return data; 375 } 376 } 377 378 380 private static class PathView extends JPanel { 381 382 private JList resources; 383 private JButton addButton; 384 private JButton addURLButton; 385 private JButton removeButton; 386 private JButton moveUpButton; 387 private JButton moveDownButton; 388 private File currentDir; 389 private String type; 390 391 public PathView (PathModel model, String type, File currentDir) { 392 this.type = type; 393 this.currentDir = currentDir; 394 initComponents(model); 395 } 396 397 private void initComponents(PathModel model) { 398 setLayout(new GridBagLayout ()); 399 JLabel label = new JLabel (); 400 String key = null; 401 String mneKey = null; 402 String ad = null; 403 if (type.equals(CLASSPATH)) { 404 key = "TXT_Classes"; mneKey = "MNE_Classes"; ad = "AD_Classes"; } else if (type.equals(SOURCES)) { 408 key = "TXT_Sources"; mneKey = "MNE_Sources"; ad = "AD_Sources"; } else if (type.equals(JAVADOC)) { 412 key = "TXT_Javadoc"; mneKey = "MNE_Javadoc"; ad = "AD_Javadoc"; } else { 416 assert false : "Illegal type of panel"; return; 418 } 419 label.setText(NbBundle.getMessage(CustomizerSupport.class,key)); 420 label.setDisplayedMnemonic(NbBundle.getMessage(CustomizerSupport.class,mneKey).charAt(0)); 421 GridBagConstraints c = new GridBagConstraints (); 422 c.gridx = GridBagConstraints.RELATIVE; 423 c.gridy = GridBagConstraints.RELATIVE; 424 c.gridwidth = GridBagConstraints.REMAINDER; 425 c.insets = new Insets (6,12,2,0); 426 c.fill = GridBagConstraints.HORIZONTAL; 427 c.weightx = 1.0; 428 ((GridBagLayout )getLayout()).setConstraints(label,c); 429 add(label); 430 resources = new JList (model); 431 label.setLabelFor(resources); 432 resources.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CustomizerSupport.class,ad)); 433 resources.addListSelectionListener(new ListSelectionListener () { 434 public void valueChanged(ListSelectionEvent e) { 435 selectionChanged (); 436 } 437 }); 438 JScrollPane spane = new JScrollPane (this.resources); 439 spane.setPreferredSize(new java.awt.Dimension (200, 100)); 442 c = new GridBagConstraints (); 443 c.gridx = GridBagConstraints.RELATIVE; 444 c.gridy = GridBagConstraints.RELATIVE; 445 c.gridwidth = 1; 446 c.gridheight = 5; 447 c.insets = new Insets (0,12,12,6); 448 c.fill = GridBagConstraints.BOTH; 449 c.weightx = 1.0; 450 c.weighty = 1.0; 451 ((GridBagLayout )this.getLayout()).setConstraints(spane,c); 452 add(spane); 453 if (type == SOURCES || type == JAVADOC) { 454 this.addButton = new JButton (); 455 String text; 456 char mne; 457 if (type == SOURCES) { 458 text = NbBundle.getMessage(CustomizerSupport.class, "CTL_Add"); 459 mne = NbBundle.getMessage(CustomizerSupport.class, "MNE_Add").charAt(0); 460 ad = NbBundle.getMessage(CustomizerSupport.class, "AD_Add"); 461 } 462 else { 463 text = NbBundle.getMessage(CustomizerSupport.class, "CTL_AddZip"); 464 mne = NbBundle.getMessage(CustomizerSupport.class, "MNE_AddZip").charAt(0); 465 ad = NbBundle.getMessage(CustomizerSupport.class, "AD_AddZip"); 466 } 467 this.addButton.setText(text); 468 this.addButton.setMnemonic(mne); 469 this.addButton.getAccessibleContext().setAccessibleDescription (ad); 470 addButton.addActionListener( new ActionListener () { 471 public void actionPerformed(ActionEvent e) { 472 addPathElement (); 473 } 474 }); 475 c = new GridBagConstraints (); 476 c.gridx = 1; 477 c.gridy = 1; 478 c.gridwidth = GridBagConstraints.REMAINDER; 479 c.fill = GridBagConstraints.HORIZONTAL; 480 c.anchor = GridBagConstraints.NORTHWEST; 481 c.insets = new Insets (0,6,0,6); 482 ((GridBagLayout )this.getLayout()).setConstraints(addButton,c); 483 this.add (addButton); 484 removeButton = new JButton (NbBundle.getMessage(CustomizerSupport.class, "CTL_Remove")); 503 removeButton.setMnemonic(NbBundle.getMessage(CustomizerSupport.class, "MNE_Remove").charAt(0)); 504 removeButton.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(CustomizerSupport.class,"AD_Remove")); 505 removeButton.addActionListener( new ActionListener () { 506 public void actionPerformed(ActionEvent e) { 507 removePathElement (); 508 } 509 }); 510 removeButton.setEnabled(false); 511 c = new GridBagConstraints (); 512 c.gridx = 1; 513 c.gridy = 3; 514 c.gridwidth = GridBagConstraints.REMAINDER; 515 c.fill = GridBagConstraints.HORIZONTAL; 516 c.anchor = GridBagConstraints.NORTHWEST; 517 c.insets = new Insets (12,6,0,6); 518 ((GridBagLayout )this.getLayout()).setConstraints(removeButton,c); 519 this.add (removeButton); 520 moveUpButton = new JButton (NbBundle.getMessage(CustomizerSupport.class, "CTL_Up")); 521 moveUpButton.setMnemonic(NbBundle.getMessage(CustomizerSupport.class, "MNE_Up").charAt(0)); 522 moveUpButton.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(CustomizerSupport.class,"AD_Up")); 523 moveUpButton.addActionListener( new ActionListener () { 524 public void actionPerformed(ActionEvent e) { 525 moveUpPathElement (); 526 } 527 }); 528 moveUpButton.setEnabled(false); 529 c = new GridBagConstraints (); 530 c.gridx = 1; 531 c.gridy = 4; 532 c.gridwidth = GridBagConstraints.REMAINDER; 533 c.fill = GridBagConstraints.HORIZONTAL; 534 c.anchor = GridBagConstraints.NORTHWEST; 535 c.insets = new Insets (12,6,0,6); 536 ((GridBagLayout )this.getLayout()).setConstraints(moveUpButton,c); 537 this.add (moveUpButton); 538 moveDownButton = new JButton (NbBundle.getMessage(CustomizerSupport.class, "CTL_Down")); 539 moveDownButton.setMnemonic (NbBundle.getMessage(CustomizerSupport.class, "MNE_Down").charAt(0)); 540 moveDownButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CustomizerSupport.class,"AD_Down")); 541 moveDownButton.addActionListener( new ActionListener () { 542 public void actionPerformed(ActionEvent e) { 543 moveDownPathElement (); 544 } 545 }); 546 moveDownButton.setEnabled(false); 547 c = new GridBagConstraints (); 548 c.gridx = 1; 549 c.gridy = 5; 550 c.gridwidth = GridBagConstraints.REMAINDER; 551 c.fill = GridBagConstraints.HORIZONTAL; 552 c.anchor = GridBagConstraints.NORTHWEST; 553 c.insets = new Insets (5,6,6,6); 554 ((GridBagLayout )this.getLayout()).setConstraints(moveDownButton,c); 555 this.add (moveDownButton); 556 } 557 } 558 559 609 private void addPathElement () { 610 JFileChooser chooser = new JFileChooser (); 611 FileUtil.preventFileChooserSymlinkTraversal(chooser, null); 612 chooser.setMultiSelectionEnabled (true); 613 String title = null; 614 String message = null; 615 String approveButtonName = null; 616 String approveButtonNameMne = null; 617 if (this.type == SOURCES) { 618 title = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenSources"); 619 message = NbBundle.getMessage (CustomizerSupport.class,"TXT_Sources"); 620 approveButtonName = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenSources"); 621 approveButtonNameMne = NbBundle.getMessage (CustomizerSupport.class,"MNE_OpenSources"); 622 } 623 else if (this.type == JAVADOC) { 624 title = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenJavadoc"); 625 message = NbBundle.getMessage (CustomizerSupport.class,"TXT_Javadoc"); 626 approveButtonName = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenJavadoc"); 627 approveButtonNameMne = NbBundle.getMessage (CustomizerSupport.class,"MNE_OpenJavadoc"); 628 } 629 chooser.setDialogTitle(title); 630 chooser.setApproveButtonText(approveButtonName); 631 chooser.setApproveButtonMnemonic (approveButtonNameMne.charAt(0)); 632 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 633 chooser.setAcceptAllFileFilterUsed( false ); 635 chooser.setFileFilter (new SimpleFileFilter(message,new String [] {"ZIP","JAR"})); if (this.currentDir != null && currentDir.exists()) { 637 chooser.setCurrentDirectory(this.currentDir); 638 } 639 if (chooser.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) { 640 File [] fs = chooser.getSelectedFiles(); 641 PathModel model = (PathModel) this.resources.getModel(); 642 boolean addingFailed = false; 643 int firstIndex = this.resources.getModel().getSize(); 644 for (int i = 0; i < fs.length; i++) { 645 File f = fs[i]; 646 if (!f.exists()) { 650 File parent = f.getParentFile(); 651 if (parent != null && f.getName().equals(parent.getName()) && parent.exists()) { 652 f = parent; 653 } 654 } 655 addingFailed|=!model.addPath (f); 656 } 657 if (addingFailed) { 658 new NotifyDescriptor.Message (NbBundle.getMessage(CustomizerSupport.class,"TXT_CanNotAddResolve"), 659 NotifyDescriptor.ERROR_MESSAGE); 660 } 661 int lastIndex = this.resources.getModel().getSize()-1; 662 if (firstIndex<=lastIndex) { 663 int[] toSelect = new int[lastIndex-firstIndex+1]; 664 for (int i = 0; i < toSelect.length; i++) { 665 toSelect[i] = firstIndex+i; 666 } 667 this.resources.setSelectedIndices(toSelect); 668 } 669 this.currentDir = FileUtil.normalizeFile(chooser.getCurrentDirectory()); 670 } 671 } 672 673 private void removePathElement () { 674 int[] indices = this.resources.getSelectedIndices(); 675 if (indices.length == 0) { 676 return; 677 } 678 PathModel model = (PathModel) this.resources.getModel(); 679 model.removePath (indices); 680 if ( indices[indices.length-1]-indices.length+1 < this.resources.getModel().getSize()) { 681 this.resources.setSelectedIndex (indices[indices.length-1]-indices.length+1); 682 } 683 else if (indices[0]>0) { 684 this.resources.setSelectedIndex (indices[0]-1); 685 } 686 } 687 688 private void moveDownPathElement () { 689 int[] indices = this.resources.getSelectedIndices(); 690 if (indices.length == 0) { 691 return; 692 } 693 PathModel model = (PathModel) this.resources.getModel(); 694 model.moveDownPath (indices); 695 for (int i=0; i< indices.length; i++) { 696 indices[i] = indices[i] + 1; 697 } 698 this.resources.setSelectedIndices (indices); 699 } 700 701 private void moveUpPathElement () { 702 int[] indices = this.resources.getSelectedIndices(); 703 if (indices.length == 0) { 704 return; 705 } 706 PathModel model = (PathModel) this.resources.getModel(); 707 model.moveUpPath (indices); 708 for (int i=0; i< indices.length; i++) { 709 indices[i] = indices[i] - 1; 710 } 711 this.resources.setSelectedIndices (indices); 712 } 713 714 private void selectionChanged () { 715 if (this.type == CLASSPATH) { 716 return; 717 } 718 int indices[] = this.resources.getSelectedIndices(); 719 this.removeButton.setEnabled (indices.length > 0); 720 this.moveUpButton.setEnabled (indices.length > 0 && indices[0]>0); 721 this.moveDownButton.setEnabled(indices.length > 0 && indices[indices.length-1]<this.resources.getModel().getSize()-1); 722 } 723 } 724 725 private static class SimpleFileFilter extends FileFilter { 726 727 private String description; 728 private Collection extensions; 729 730 731 public SimpleFileFilter (String description, String [] extensions) { 732 this.description = description; 733 this.extensions = Arrays.asList(extensions); 734 } 735 736 public boolean accept(File f) { 737 if (f.isDirectory()) 738 return true; 739 String name = f.getName(); 740 int index = name.lastIndexOf('.'); if (index <= 0 || index==name.length()-1) 742 return false; 743 String extension = name.substring (index+1).toUpperCase(); 744 return this.extensions.contains(extension); 745 } 746 747 public String getDescription() { 748 return this.description; 749 } 750 } 751 } 752 | Popular Tags |