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