1 19 20 package org.netbeans.modules.j2ee.sun.ide.j2ee.ui; 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 ErrorManager.getDefault().log(ErrorManager.WARNING, f.getAbsolutePath()); 345 ErrorManager.getDefault().notify(ErrorManager.WARNING, mue); 346 return false; 347 } 348 } 349 350 355 public boolean addPath(URL url) { 356 if (FileUtil.isArchiveFile(url)) { 357 url = FileUtil.getArchiveRoot(url); 358 } else if (!url.toExternalForm().endsWith("/")) { try { 360 url = new URL (url.toExternalForm() + "/"); } catch (MalformedURLException mue) { 362 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, mue); 363 } 364 } 365 int oldSize = data.size(); 366 data.add(url); 367 fireIntervalAdded(this, oldSize, oldSize); 368 return true; 369 } 370 371 375 public List <URL > getData() { 376 return data; 377 } 378 } 379 380 382 private static class PathView extends JPanel { 383 384 private JList resources; 385 private JButton addButton; 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; 402 String mneKey; 403 String ad; 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 org.openide.awt.Mnemonics.setLocalizedText(label, org.openide.util.NbBundle.getBundle(CustomizerSupport.class).getString(key)); 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 (SOURCES.equals(type) || JAVADOC.equals(type)) { 454 this.addButton = new JButton (); 455 String text; 456 char mne; 457 if (SOURCES.equals(type)) { 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 org.openide.awt.Mnemonics.setLocalizedText(this.addButton, text); this.addButton.getAccessibleContext().setAccessibleDescription (ad); 469 addButton.addActionListener( new ActionListener () { 470 public void actionPerformed(ActionEvent e) { 471 addPathElement (); 472 } 473 }); 474 c = new GridBagConstraints (); 475 c.gridx = 1; 476 c.gridy = 1; 477 c.gridwidth = GridBagConstraints.REMAINDER; 478 c.fill = GridBagConstraints.HORIZONTAL; 479 c.anchor = GridBagConstraints.NORTHWEST; 480 c.insets = new Insets (0,6,0,6); 481 ((GridBagLayout )this.getLayout()).setConstraints(addButton,c); 482 this.add (addButton); 483 removeButton = new JButton (); 484 org.openide.awt.Mnemonics.setLocalizedText(this.removeButton, 485 NbBundle.getMessage(CustomizerSupport.class, "CTL_Remove")); removeButton.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(CustomizerSupport.class,"AD_Remove")); 487 removeButton.addActionListener( new ActionListener () { 488 public void actionPerformed(ActionEvent e) { 489 removePathElement (); 490 } 491 }); 492 removeButton.setEnabled(false); 493 c = new GridBagConstraints (); 494 c.gridx = 1; 495 c.gridy = 3; 496 c.gridwidth = GridBagConstraints.REMAINDER; 497 c.fill = GridBagConstraints.HORIZONTAL; 498 c.anchor = GridBagConstraints.NORTHWEST; 499 c.insets = new Insets (12,6,0,6); 500 ((GridBagLayout )this.getLayout()).setConstraints(removeButton,c); 501 this.add (removeButton); 502 moveUpButton = new JButton (); 503 org.openide.awt.Mnemonics.setLocalizedText(this.moveUpButton, 504 NbBundle.getMessage(CustomizerSupport.class, "CTL_Up")); moveUpButton.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(CustomizerSupport.class,"AD_Up")); 506 moveUpButton.addActionListener( new ActionListener () { 507 public void actionPerformed(ActionEvent e) { 508 moveUpPathElement (); 509 } 510 }); 511 moveUpButton.setEnabled(false); 512 c = new GridBagConstraints (); 513 c.gridx = 1; 514 c.gridy = 4; 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(moveUpButton,c); 520 this.add (moveUpButton); 521 moveDownButton = new JButton (); 522 org.openide.awt.Mnemonics.setLocalizedText(this.moveDownButton, 523 NbBundle.getMessage(CustomizerSupport.class, "CTL_Down")); moveDownButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CustomizerSupport.class,"AD_Down")); 525 moveDownButton.addActionListener( new ActionListener () { 526 public void actionPerformed(ActionEvent e) { 527 moveDownPathElement (); 528 } 529 }); 530 moveDownButton.setEnabled(false); 531 c = new GridBagConstraints (); 532 c.gridx = 1; 533 c.gridy = 5; 534 c.gridwidth = GridBagConstraints.REMAINDER; 535 c.fill = GridBagConstraints.HORIZONTAL; 536 c.anchor = GridBagConstraints.NORTHWEST; 537 c.insets = new Insets (5,6,6,6); 538 ((GridBagLayout )this.getLayout()).setConstraints(moveDownButton,c); 539 this.add (moveDownButton); 540 } 541 } 542 543 544 private void addPathElement () { 545 JFileChooser chooser = new JFileChooser (); 546 FileUtil.preventFileChooserSymlinkTraversal(chooser, null); 547 chooser.setMultiSelectionEnabled (true); 548 String title = null; 549 String message = null; 550 String approveButtonName = null; 551 String approveButtonNameMne = null; 552 if (SOURCES.equals(this.type)) { 553 title = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenSources"); 554 message = NbBundle.getMessage (CustomizerSupport.class,"TXT_Sources"); 555 approveButtonName = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenSources"); 556 approveButtonNameMne = NbBundle.getMessage (CustomizerSupport.class,"MNE_OpenSources"); 557 } 558 else if (JAVADOC.equals(this.type)) { 559 title = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenJavadoc"); 560 message = NbBundle.getMessage (CustomizerSupport.class,"TXT_Javadoc"); 561 approveButtonName = NbBundle.getMessage (CustomizerSupport.class,"TXT_OpenJavadoc"); 562 approveButtonNameMne = NbBundle.getMessage (CustomizerSupport.class,"MNE_OpenJavadoc"); 563 } 564 chooser.setDialogTitle(title); 565 chooser.setApproveButtonText(approveButtonName); 566 if (null != approveButtonNameMne) { 567 chooser.setApproveButtonMnemonic (approveButtonNameMne.charAt(0)); 568 } 569 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 570 chooser.setAcceptAllFileFilterUsed( false ); 572 chooser.setFileFilter (new SimpleFileFilter(message,new String [] {"ZIP","JAR"})); if (this.currentDir != null && currentDir.exists()) { 574 chooser.setCurrentDirectory(this.currentDir); 575 } 576 if (chooser.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) { 577 File [] fs = chooser.getSelectedFiles(); 578 PathModel model = (PathModel) this.resources.getModel(); 579 boolean addingFailed = false; 580 int firstIndex = this.resources.getModel().getSize(); 581 for (int i = 0; i < fs.length; i++) { 582 File f = fs[i]; 583 if (!f.exists()) { 587 File parent = f.getParentFile(); 588 if (parent != null && f.getName().equals(parent.getName()) && parent.exists()) { 589 f = parent; 590 } 591 } 592 addingFailed|=!model.addPath (f); 593 } 594 if (addingFailed) { 595 new NotifyDescriptor.Message (NbBundle.getMessage(CustomizerSupport.class,"TXT_CanNotAddResolve"), 596 NotifyDescriptor.ERROR_MESSAGE); 597 } 598 int lastIndex = this.resources.getModel().getSize()-1; 599 if (firstIndex<=lastIndex) { 600 int[] toSelect = new int[lastIndex-firstIndex+1]; 601 for (int i = 0; i < toSelect.length; i++) { 602 toSelect[i] = firstIndex+i; 603 } 604 this.resources.setSelectedIndices(toSelect); 605 } 606 this.currentDir = FileUtil.normalizeFile(chooser.getCurrentDirectory()); 607 } 608 } 609 610 private void removePathElement () { 611 int[] indices = this.resources.getSelectedIndices(); 612 if (indices.length == 0) { 613 return; 614 } 615 PathModel model = (PathModel) this.resources.getModel(); 616 model.removePath (indices); 617 if ( indices[indices.length-1]-indices.length+1 < this.resources.getModel().getSize()) { 618 this.resources.setSelectedIndex (indices[indices.length-1]-indices.length+1); 619 } 620 else if (indices[0]>0) { 621 this.resources.setSelectedIndex (indices[0]-1); 622 } 623 } 624 625 private void moveDownPathElement () { 626 int[] indices = this.resources.getSelectedIndices(); 627 if (indices.length == 0) { 628 return; 629 } 630 PathModel model = (PathModel) this.resources.getModel(); 631 model.moveDownPath (indices); 632 for (int i=0; i< indices.length; i++) { 633 indices[i] = indices[i] + 1; 634 } 635 this.resources.setSelectedIndices (indices); 636 } 637 638 private void moveUpPathElement () { 639 int[] indices = this.resources.getSelectedIndices(); 640 if (indices.length == 0) { 641 return; 642 } 643 PathModel model = (PathModel) this.resources.getModel(); 644 model.moveUpPath (indices); 645 for (int i=0; i< indices.length; i++) { 646 indices[i] = indices[i] - 1; 647 } 648 this.resources.setSelectedIndices (indices); 649 } 650 651 private void selectionChanged () { 652 if (CLASSPATH.equals(this.type)) { 653 return; 654 } 655 int indices[] = this.resources.getSelectedIndices(); 656 this.removeButton.setEnabled (indices.length > 0); 657 this.moveUpButton.setEnabled (indices.length > 0 && indices[0]>0); 658 this.moveDownButton.setEnabled(indices.length > 0 && indices[indices.length-1]<this.resources.getModel().getSize()-1); 659 } 660 } 661 662 private static class SimpleFileFilter extends FileFilter { 663 664 private String description; 665 private Collection extensions; 666 667 668 public SimpleFileFilter (String description, String [] extensions) { 669 this.description = description; 670 this.extensions = Arrays.asList(extensions); 671 } 672 673 public boolean accept(File f) { 674 if (f.isDirectory()) { 675 return true; 676 } 677 String name = f.getName(); 678 int index = name.lastIndexOf('.'); if (index <= 0 || index==name.length()-1) { 680 return false; 681 } 682 String extension = name.substring (index+1).toUpperCase(); 683 return this.extensions.contains(extension); 684 } 685 686 public String getDescription() { 687 return this.description; 688 } 689 } 690 } 691 | Popular Tags |