1 19 20 package org.netbeans.modules.j2ee.oc4j.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.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties; 50 import org.openide.ErrorManager; 51 import org.openide.NotifyDescriptor; 52 import org.openide.filesystems.FileUtil; 53 import org.openide.util.NbBundle; 54 55 61 public final class OC4JCustomizerSupport { 62 63 private static final String CLASSPATH = J2eeLibraryTypeProvider.VOLUME_TYPE_CLASSPATH; 64 private static final String JAVADOC = J2eeLibraryTypeProvider.VOLUME_TYPE_JAVADOC; 65 66 67 private OC4JCustomizerSupport() { 68 } 69 70 79 public static Component createUserCustomizer(InstanceProperties ip) { 80 if (ip == null) { 81 throw new NullPointerException (); 82 } 83 84 return new OC4JCustomizerUserPanel(ip); 85 } 86 87 96 public static Component createClassesCustomizer(PathModel model) { 97 if (model == null) { 98 throw new NullPointerException (); 99 } 100 return new PathView(model, CLASSPATH, null); 101 } 102 103 114 public static Component createJavadocCustomizer(PathModel model, File currentDir) { 115 if (model == null) { 116 throw new NullPointerException (); 117 } 118 return new PathView(model, JAVADOC, currentDir); 119 } 120 121 128 public static String buildPath(List <URL > path) { 129 String PATH_SEPARATOR = System.getProperty("path.separator"); StringBuffer sb = new StringBuffer (path.size() * 16); 131 for (Iterator <URL > i = path.iterator(); i.hasNext(); ) { 132 sb.append(urlToString(i.next())); 133 if (i.hasNext()) { 134 sb.append(PATH_SEPARATOR); 135 } 136 } 137 return sb.toString(); 138 } 139 140 149 public static List <URL > tokenizePath(String path) { 150 try { 151 List <URL > l = new ArrayList (); 152 StringTokenizer tok = new StringTokenizer (path, ":;", true); char dosHack = '\0'; 154 char lastDelim = '\0'; 155 int delimCount = 0; 156 while (tok.hasMoreTokens()) { 157 String s = tok.nextToken(); 158 if (s.length() == 0) { 159 continue; 161 } 162 if (s.length() == 1) { 163 char c = s.charAt(0); 164 if (c == ':' || c == ';') { 165 lastDelim = c; 167 delimCount++; 168 continue; 169 } 170 } 171 if (dosHack != '\0') { 172 if (lastDelim == ':' && delimCount == 1 && (s.charAt(0) == '\\' || s.charAt(0) == '/')) { 174 s = "" + dosHack + ':' + s; 176 } else { 178 l.add(fileToUrl(new File (Character.toString(dosHack)))); 180 } 182 dosHack = '\0'; 183 } 184 delimCount = 0; 186 if (s.length() == 1) { 187 char c = s.charAt(0); 188 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 189 dosHack = c; 191 continue; 192 } 193 } 194 l.add(fileToUrl(new File (s))); 195 } 196 if (dosHack != '\0') { 197 l.add(fileToUrl(new File (Character.toString(dosHack)))); 201 } 202 return l; 203 } catch (MalformedURLException e) { 204 ErrorManager.getDefault().notify(e); 205 return new ArrayList (); 206 } 207 } 208 209 210 private static URL fileToUrl(File file) throws MalformedURLException { 211 URL url = file.toURI().toURL(); 212 if (FileUtil.isArchiveFile(url)) { 213 url = FileUtil.getArchiveRoot(url); 214 } 215 return url; 216 } 217 218 219 private static String urlToString(URL url) { 220 if ("jar".equals(url.getProtocol())) { URL fileURL = FileUtil.getArchiveFile(url); 222 if (FileUtil.getArchiveRoot(fileURL).equals(url)) { 223 url = fileURL; 225 } else { 226 return url.toExternalForm(); 228 } 229 } 230 if ("file".equals(url.getProtocol())) { File f = new File (URI.create(url.toExternalForm())); 232 return f.getAbsolutePath(); 233 } else { 234 return url.toExternalForm(); 235 } 236 } 237 238 241 public static final class PathModel extends AbstractListModel { 242 243 private final List <URL > data; 244 245 252 public PathModel(List <URL > data) { 253 if (data == null) { 254 throw new NullPointerException ("The data attribute must not be null."); } 256 this.data = data; 257 } 258 259 264 public int getSize() { 265 return data.size(); 266 } 267 268 275 public Object getElementAt(int index) { 276 URL url = data.get(index); 277 if ("jar".equals(url.getProtocol())) { URL fileURL = FileUtil.getArchiveFile(url); 279 if (FileUtil.getArchiveRoot(fileURL).equals(url)) { 280 url = fileURL; 282 } else { 283 return url.toExternalForm(); 285 } 286 } 287 if ("file".equals(url.getProtocol())) { File f = new File (URI.create(url.toExternalForm())); 289 return f.getAbsolutePath(); 290 } else { 291 return url.toExternalForm(); 292 } 293 } 294 295 298 public void removePath(int[] indices) { 299 for (int i = indices.length - 1; i >= 0; i--) { 300 data.remove(indices[i]); 301 } 302 fireIntervalRemoved(this, indices[0], indices[indices.length - 1]); 303 } 304 305 308 public void moveUpPath(int[] indices) { 309 for (int i = 0; i < indices.length; i++) { 310 URL p2 = data.get(indices[i]); 311 URL p1 = data.set(indices[i] - 1, p2); 312 data.set(indices[i], p1); 313 } 314 fireContentsChanged(this, indices[0] - 1, indices[indices.length - 1]); 315 } 316 317 320 public void moveDownPath(int[] indices) { 321 for (int i = indices.length - 1; i >= 0; i--) { 322 URL p1 = data.get(indices[i]); 323 URL p2 = data.set(indices[i] + 1, p1); 324 data.set(indices[i], p2); 325 } 326 fireContentsChanged(this, indices[0], indices[indices.length - 1] + 1); 327 } 328 329 334 public boolean addPath(File f) { 335 try { 336 URL url = f.toURI().toURL(); 337 return this.addPath(url); 338 } catch (MalformedURLException mue) { 339 return false; 340 } 341 } 342 343 348 public boolean addPath(URL url) { 349 if (FileUtil.isArchiveFile(url)) { 350 url = FileUtil.getArchiveRoot(url); 351 } else if (!url.toExternalForm().endsWith("/")) { try { 353 url = new URL (url.toExternalForm() + "/"); } catch (MalformedURLException mue) { 355 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, mue); 356 } 357 } 358 int oldSize = data.size(); 359 data.add(url); 360 fireIntervalAdded(this, oldSize, oldSize); 361 return true; 362 } 363 364 368 public List <URL > getData() { 369 return data; 370 } 371 } 372 373 private static class PathView extends JPanel { 374 375 private JList resources; 376 private JButton addButton; 377 private JButton addURLButton; 378 private JButton removeButton; 379 private JButton moveUpButton; 380 private JButton moveDownButton; 381 private File currentDir; 382 private String type; 383 384 public PathView(PathModel model, String type, File currentDir) { 385 this.type = type; 386 this.currentDir = currentDir; 387 initComponents(model); 388 } 389 390 private void initComponents(PathModel model) { 391 setLayout(new GridBagLayout ()); 392 JLabel label = new JLabel (); 393 String key = null; 394 String mneKey = null; 395 String ad = null; 396 if (type.equals(CLASSPATH)) { 397 key = "TXT_Classes"; mneKey = "MNE_Classes"; ad = "AD_Classes"; } else if (type.equals(JAVADOC)) { 401 key = "TXT_Javadoc"; mneKey = "MNE_Javadoc"; ad = "AD_Javadoc"; } else { 405 assert false : "Illegal type of panel"; return; 407 } 408 label.setText(NbBundle.getMessage(OC4JCustomizerSupport.class,key)); 409 label.setDisplayedMnemonic(NbBundle.getMessage(OC4JCustomizerSupport.class,mneKey).charAt(0)); 410 GridBagConstraints c = new GridBagConstraints (); 411 c.gridx = GridBagConstraints.RELATIVE; 412 c.gridy = GridBagConstraints.RELATIVE; 413 c.gridwidth = GridBagConstraints.REMAINDER; 414 c.insets = new Insets (6,12,2,0); 415 c.fill = GridBagConstraints.HORIZONTAL; 416 c.weightx = 1.0; 417 ((GridBagLayout )getLayout()).setConstraints(label,c); 418 add(label); 419 resources = new JList (model); 420 label.setLabelFor(resources); 421 resources.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(OC4JCustomizerSupport.class,ad)); 422 resources.addListSelectionListener(new ListSelectionListener () { 423 public void valueChanged(ListSelectionEvent e) { 424 selectionChanged(); 425 } 426 }); 427 JScrollPane spane = new JScrollPane (this.resources); 428 spane.setPreferredSize(new java.awt.Dimension (200, 100)); 431 c = new GridBagConstraints (); 432 c.gridx = GridBagConstraints.RELATIVE; 433 c.gridy = GridBagConstraints.RELATIVE; 434 c.gridwidth = 1; 435 c.gridheight = 5; 436 c.insets = new Insets (0,12,12,6); 437 c.fill = GridBagConstraints.BOTH; 438 c.weightx = 1.0; 439 c.weighty = 1.0; 440 ((GridBagLayout )this.getLayout()).setConstraints(spane,c); 441 add(spane); 442 if (type == JAVADOC) { 443 this.addButton = new JButton (); 444 String text = NbBundle.getMessage(OC4JCustomizerSupport.class, "CTL_AddZip"); 445 char mne = NbBundle.getMessage(OC4JCustomizerSupport.class, "MNE_AddZip").charAt(0); 446 ad = NbBundle.getMessage(OC4JCustomizerSupport.class, "AD_AddZip"); 447 this.addButton.setText(text); 448 this.addButton.setMnemonic(mne); 449 this.addButton.getAccessibleContext().setAccessibleDescription(ad); 450 addButton.addActionListener( new ActionListener () { 451 public void actionPerformed(ActionEvent e) { 452 addPathElement(); 453 } 454 }); 455 c = new GridBagConstraints (); 456 c.gridx = 1; 457 c.gridy = 1; 458 c.gridwidth = GridBagConstraints.REMAINDER; 459 c.fill = GridBagConstraints.HORIZONTAL; 460 c.anchor = GridBagConstraints.NORTHWEST; 461 c.insets = new Insets (0,6,0,6); 462 ((GridBagLayout )this.getLayout()).setConstraints(addButton,c); 463 this.add(addButton); 464 465 removeButton = new JButton (NbBundle.getMessage(OC4JCustomizerSupport.class, "CTL_Remove")); 466 removeButton.setMnemonic(NbBundle.getMessage(OC4JCustomizerSupport.class, "MNE_Remove").charAt(0)); 467 removeButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(OC4JCustomizerSupport.class,"AD_Remove")); 468 removeButton.addActionListener( new ActionListener () { 469 public void actionPerformed(ActionEvent e) { 470 removePathElement(); 471 } 472 }); 473 removeButton.setEnabled(false); 474 c = new GridBagConstraints (); 475 c.gridx = 1; 476 c.gridy = 3; 477 c.gridwidth = GridBagConstraints.REMAINDER; 478 c.fill = GridBagConstraints.HORIZONTAL; 479 c.anchor = GridBagConstraints.NORTHWEST; 480 c.insets = new Insets (12,6,0,6); 481 ((GridBagLayout )this.getLayout()).setConstraints(removeButton,c); 482 this.add(removeButton); 483 moveUpButton = new JButton (NbBundle.getMessage(OC4JCustomizerSupport.class, "CTL_Up")); 484 moveUpButton.setMnemonic(NbBundle.getMessage(OC4JCustomizerSupport.class, "MNE_Up").charAt(0)); 485 moveUpButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(OC4JCustomizerSupport.class,"AD_Up")); 486 moveUpButton.addActionListener( new ActionListener () { 487 public void actionPerformed(ActionEvent e) { 488 moveUpPathElement(); 489 } 490 }); 491 moveUpButton.setEnabled(false); 492 c = new GridBagConstraints (); 493 c.gridx = 1; 494 c.gridy = 4; 495 c.gridwidth = GridBagConstraints.REMAINDER; 496 c.fill = GridBagConstraints.HORIZONTAL; 497 c.anchor = GridBagConstraints.NORTHWEST; 498 c.insets = new Insets (12,6,0,6); 499 ((GridBagLayout )this.getLayout()).setConstraints(moveUpButton,c); 500 this.add(moveUpButton); 501 moveDownButton = new JButton (NbBundle.getMessage(OC4JCustomizerSupport.class, "CTL_Down")); 502 moveDownButton.setMnemonic(NbBundle.getMessage(OC4JCustomizerSupport.class, "MNE_Down").charAt(0)); 503 moveDownButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(OC4JCustomizerSupport.class,"AD_Down")); 504 moveDownButton.addActionListener( new ActionListener () { 505 public void actionPerformed(ActionEvent e) { 506 moveDownPathElement(); 507 } 508 }); 509 moveDownButton.setEnabled(false); 510 c = new GridBagConstraints (); 511 c.gridx = 1; 512 c.gridy = 5; 513 c.gridwidth = GridBagConstraints.REMAINDER; 514 c.fill = GridBagConstraints.HORIZONTAL; 515 c.anchor = GridBagConstraints.NORTHWEST; 516 c.insets = new Insets (5,6,6,6); 517 ((GridBagLayout )this.getLayout()).setConstraints(moveDownButton,c); 518 this.add(moveDownButton); 519 } 520 } 521 522 private void addPathElement() { 523 JFileChooser chooser = new JFileChooser (); 524 FileUtil.preventFileChooserSymlinkTraversal(chooser, null); 525 chooser.setMultiSelectionEnabled(true); 526 String title = null; 527 String message = null; 528 String approveButtonName = null; 529 String approveButtonNameMne = null; 530 if (this.type == JAVADOC) { 531 title = NbBundle.getMessage(OC4JCustomizerSupport.class,"TXT_OpenJavadoc"); 532 message = NbBundle.getMessage(OC4JCustomizerSupport.class,"TXT_Javadoc"); 533 approveButtonName = NbBundle.getMessage(OC4JCustomizerSupport.class,"TXT_OpenJavadoc"); 534 approveButtonNameMne = NbBundle.getMessage(OC4JCustomizerSupport.class,"MNE_OpenJavadoc"); 535 } 536 chooser.setDialogTitle(title); 537 chooser.setApproveButtonText(approveButtonName); 538 chooser.setApproveButtonMnemonic(approveButtonNameMne.charAt(0)); 539 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 540 chooser.setAcceptAllFileFilterUsed( false ); 542 chooser.setFileFilter(new SimpleFileFilter(message,new String [] {"ZIP","JAR"})); if (this.currentDir != null && currentDir.exists()) { 544 chooser.setCurrentDirectory(this.currentDir); 545 } 546 if (chooser.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) { 547 File [] fs = chooser.getSelectedFiles(); 548 PathModel model = (PathModel) this.resources.getModel(); 549 boolean addingFailed = false; 550 int firstIndex = this.resources.getModel().getSize(); 551 for (int i = 0; i < fs.length; i++) { 552 File f = fs[i]; 553 if (!f.exists()) { 557 File parent = f.getParentFile(); 558 if (parent != null && f.getName().equals(parent.getName()) && parent.exists()) { 559 f = parent; 560 } 561 } 562 addingFailed|=!model.addPath(f); 563 } 564 if (addingFailed) { 565 new NotifyDescriptor.Message(NbBundle.getMessage(OC4JCustomizerSupport.class,"TXT_CanNotAddResolve"), 566 NotifyDescriptor.ERROR_MESSAGE); 567 } 568 int lastIndex = this.resources.getModel().getSize()-1; 569 if (firstIndex<=lastIndex) { 570 int[] toSelect = new int[lastIndex-firstIndex+1]; 571 for (int i = 0; i < toSelect.length; i++) { 572 toSelect[i] = firstIndex+i; 573 } 574 this.resources.setSelectedIndices(toSelect); 575 } 576 this.currentDir = FileUtil.normalizeFile(chooser.getCurrentDirectory()); 577 } 578 } 579 580 private void removePathElement() { 581 int[] indices = this.resources.getSelectedIndices(); 582 if (indices.length == 0) { 583 return; 584 } 585 PathModel model = (PathModel) this.resources.getModel(); 586 model.removePath(indices); 587 if ( indices[indices.length-1]-indices.length+1 < this.resources.getModel().getSize()) { 588 this.resources.setSelectedIndex(indices[indices.length-1]-indices.length+1); 589 } else if (indices[0]>0) { 590 this.resources.setSelectedIndex(indices[0]-1); 591 } 592 } 593 594 private void moveDownPathElement() { 595 int[] indices = this.resources.getSelectedIndices(); 596 if (indices.length == 0) { 597 return; 598 } 599 PathModel model = (PathModel) this.resources.getModel(); 600 model.moveDownPath(indices); 601 for (int i=0; i< indices.length; i++) { 602 indices[i] = indices[i] + 1; 603 } 604 this.resources.setSelectedIndices(indices); 605 } 606 607 private void moveUpPathElement() { 608 int[] indices = this.resources.getSelectedIndices(); 609 if (indices.length == 0) { 610 return; 611 } 612 PathModel model = (PathModel) this.resources.getModel(); 613 model.moveUpPath(indices); 614 for (int i=0; i< indices.length; i++) { 615 indices[i] = indices[i] - 1; 616 } 617 this.resources.setSelectedIndices(indices); 618 } 619 620 private void selectionChanged() { 621 if (this.type == CLASSPATH) { 622 return; 623 } 624 int indices[] = this.resources.getSelectedIndices(); 625 this.removeButton.setEnabled(indices.length > 0); 626 this.moveUpButton.setEnabled(indices.length > 0 && indices[0]>0); 627 this.moveDownButton.setEnabled(indices.length > 0 && indices[indices.length-1]<this.resources.getModel().getSize()-1); 628 } 629 } 630 631 private static class SimpleFileFilter extends FileFilter { 632 633 private String description; 634 private Collection extensions; 635 636 637 public SimpleFileFilter(String description, String [] extensions) { 638 this.description = description; 639 this.extensions = Arrays.asList(extensions); 640 } 641 642 public boolean accept(File f) { 643 if (f.isDirectory()) 644 return true; 645 String name = f.getName(); 646 int index = name.lastIndexOf('.'); if (index <= 0 || index==name.length()-1) 648 return false; 649 String extension = name.substring(index+1).toUpperCase(); 650 return this.extensions.contains(extension); 651 } 652 653 public String getDescription() { 654 return this.description; 655 } 656 } 657 } | Popular Tags |