1 19 20 package org.netbeans.modules.j2ee.clientproject.ui.customizer; 21 22 import java.awt.Component ; 23 import java.awt.Dialog ; 24 import java.awt.event.ActionEvent ; 25 import java.awt.event.ActionListener ; 26 import java.beans.BeanInfo ; 27 import java.io.File ; 28 import java.text.MessageFormat ; 29 import java.util.Arrays ; 30 import java.util.Collection ; 31 import java.util.HashMap ; 32 import java.util.HashSet ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import java.util.regex.Matcher ; 36 import java.util.regex.Pattern ; 37 import javax.swing.ButtonModel ; 38 import javax.swing.DefaultListCellRenderer ; 39 import javax.swing.DefaultListModel ; 40 import javax.swing.Icon ; 41 import javax.swing.ImageIcon ; 42 import javax.swing.JButton ; 43 import javax.swing.JFileChooser ; 44 import javax.swing.JList ; 45 import javax.swing.JTable ; 46 import javax.swing.ListSelectionModel ; 47 import javax.swing.SwingUtilities ; 48 import javax.swing.event.ListSelectionEvent ; 49 import javax.swing.event.ListSelectionListener ; 50 import javax.swing.filechooser.FileFilter ; 51 import javax.swing.table.DefaultTableCellRenderer ; 52 import javax.swing.table.TableCellRenderer ; 53 import org.netbeans.api.java.project.JavaProjectConstants; 54 import org.netbeans.api.project.Project; 55 import org.netbeans.api.project.ProjectInformation; 56 import org.netbeans.api.project.ProjectUtils; 57 import org.netbeans.api.project.libraries.Library; 58 import org.netbeans.modules.j2ee.clientproject.classpath.ClassPathSupport; 59 import org.netbeans.modules.j2ee.clientproject.ui.FoldersListSettings; 60 import org.netbeans.spi.project.support.ant.PropertyEvaluator; 61 import org.openide.DialogDescriptor; 62 import org.openide.DialogDisplayer; 63 import org.openide.filesystems.FileObject; 64 import org.openide.filesystems.FileUtil; 65 import org.openide.filesystems.Repository; 66 import org.openide.loaders.DataFolder; 67 import org.openide.util.NbBundle; 68 import org.openide.util.Utilities; 69 70 74 public class AppClientClassPathUi { 75 76 private AppClientClassPathUi() {} 77 78 80 82 public static class ClassPathListCellRenderer extends DefaultListCellRenderer { 83 84 private static final Pattern FOREIGN_PLAIN_FILE_REFERENCE = Pattern.compile("\\$\\{file\\.reference\\.([^${}]+)\\}"); private static final Pattern UNKNOWN_FILE_REFERENCE = Pattern.compile("\\$\\{([^${}]+)\\}"); 87 private static String RESOURCE_ICON_JAR = "org/netbeans/modules/j2ee/clientproject/ui/resources/jar.gif"; private static String RESOURCE_ICON_LIBRARY = "org/netbeans/modules/j2ee/clientproject/ui/resources/libraries.gif"; private static String RESOURCE_ICON_ARTIFACT = "org/netbeans/modules/j2ee/clientproject/ui/resources/projectDependencies.gif"; private static String RESOURCE_ICON_CLASSPATH = "org/netbeans/modules/j2ee/clientproject/ui/resources/referencedClasspath.gif"; private static String RESOURCE_ICON_BROKEN_BADGE = "org/netbeans/modules/j2ee/clientproject/ui/resources/brokenProjectBadge.gif"; 93 94 private static ImageIcon ICON_JAR = new ImageIcon ( Utilities.loadImage( RESOURCE_ICON_JAR ) ); 95 private static ImageIcon ICON_FOLDER = null; 96 private static ImageIcon ICON_LIBRARY = new ImageIcon ( Utilities.loadImage( RESOURCE_ICON_LIBRARY ) ); 97 private static ImageIcon ICON_ARTIFACT = new ImageIcon ( Utilities.loadImage( RESOURCE_ICON_ARTIFACT ) ); 98 private static ImageIcon ICON_CLASSPATH = new ImageIcon ( Utilities.loadImage( RESOURCE_ICON_CLASSPATH ) ); 99 private static ImageIcon ICON_BROKEN_BADGE = new ImageIcon ( Utilities.loadImage( RESOURCE_ICON_BROKEN_BADGE ) ); 100 101 private static ImageIcon ICON_BROKEN_JAR; 102 private static ImageIcon ICON_BROKEN_LIBRARY; 103 private static ImageIcon ICON_BROKEN_ARTIFACT; 104 105 private PropertyEvaluator evaluator; 106 107 private static final Map <String , String > WELL_KNOWN_PATHS_NAMES = new HashMap <String , String >(); 109 static { 110 WELL_KNOWN_PATHS_NAMES.put( AppClientProjectProperties.JAVAC_CLASSPATH, NbBundle.getMessage( AppClientProjectProperties.class, "LBL_JavacClasspath_DisplayName" ) ); 111 WELL_KNOWN_PATHS_NAMES.put( AppClientProjectProperties.JAVAC_TEST_CLASSPATH, NbBundle.getMessage( AppClientProjectProperties.class,"LBL_JavacTestClasspath_DisplayName") ); 112 WELL_KNOWN_PATHS_NAMES.put( AppClientProjectProperties.RUN_CLASSPATH, NbBundle.getMessage( AppClientProjectProperties.class, "LBL_RunClasspath_DisplayName" ) ); 113 WELL_KNOWN_PATHS_NAMES.put( AppClientProjectProperties.RUN_TEST_CLASSPATH, NbBundle.getMessage( AppClientProjectProperties.class, "LBL_RunTestClasspath_DisplayName" ) ); 114 WELL_KNOWN_PATHS_NAMES.put( AppClientProjectProperties.BUILD_CLASSES_DIR, NbBundle.getMessage( AppClientProjectProperties.class, "LBL_BuildClassesDir_DisplayName" ) ); 115 WELL_KNOWN_PATHS_NAMES.put( AppClientProjectProperties.BUILD_TEST_CLASSES_DIR, NbBundle.getMessage (AppClientProjectProperties.class,"LBL_BuildTestClassesDir_DisplayName") ); 116 }; 117 118 public ClassPathListCellRenderer( PropertyEvaluator evaluator ) { 119 super(); 120 this.evaluator = evaluator; 121 } 122 123 public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 124 125 ClassPathSupport.Item item = (ClassPathSupport.Item)value; 126 127 super.getListCellRendererComponent( list, getDisplayName( item ), index, isSelected, cellHasFocus ); 128 setIcon( getIcon( item ) ); 129 setToolTipText( getToolTipText( item ) ); 130 131 return this; 132 } 133 134 135 private String getDisplayName( ClassPathSupport.Item item ) { 136 137 switch ( item.getType() ) { 138 139 case ClassPathSupport.Item.TYPE_LIBRARY: 140 if ( item.isBroken() ) { 141 return NbBundle.getMessage( AppClientClassPathUi.class, "LBL_MISSING_LIBRARY", getLibraryName( item ) ); 142 } 143 else { 144 return item.getLibrary().getDisplayName(); 145 } 146 case ClassPathSupport.Item.TYPE_CLASSPATH: 147 String name = (String )WELL_KNOWN_PATHS_NAMES.get( ClassPathSupport.getAntPropertyName( item.getReference() ) ); 148 return name == null ? item.getReference() : name; 149 case ClassPathSupport.Item.TYPE_ARTIFACT: 150 if ( item.isBroken() ) { 151 return NbBundle.getMessage( AppClientClassPathUi.class, "LBL_MISSING_PROJECT", getProjectName( item ) ); 152 } 153 else { 154 Project p = item.getArtifact().getProject(); 155 ProjectInformation pi = ProjectUtils.getInformation(p); 156 String projectName = pi.getDisplayName(); 157 return MessageFormat.format (NbBundle.getMessage(AppClientClassPathUi.class,"MSG_ProjectArtifactFormat"), new Object [] { 158 projectName, 159 item.getArtifactURI().toString() 160 }); 161 } 162 case ClassPathSupport.Item.TYPE_JAR: 163 if ( item.isBroken() ) { 164 return NbBundle.getMessage( AppClientClassPathUi.class, "LBL_MISSING_FILE", getFileRefName( item ) ); 165 } 166 else { 167 return item.getFile().getPath(); 168 } 169 } 170 171 return item.getReference(); } 173 174 static Icon getIcon( ClassPathSupport.Item item ) { 175 176 switch ( item.getType() ) { 177 178 case ClassPathSupport.Item.TYPE_LIBRARY: 179 if ( item.isBroken() ) { 180 if ( ICON_BROKEN_LIBRARY == null ) { 181 ICON_BROKEN_LIBRARY = new ImageIcon ( Utilities.mergeImages( ICON_LIBRARY.getImage(), ICON_BROKEN_BADGE.getImage(), 7, 7 ) ); 182 } 183 return ICON_BROKEN_LIBRARY; 184 } 185 else { 186 return ICON_LIBRARY; 187 } 188 case ClassPathSupport.Item.TYPE_ARTIFACT: 189 if ( item.isBroken() ) { 190 if ( ICON_BROKEN_ARTIFACT == null ) { 191 ICON_BROKEN_ARTIFACT = new ImageIcon ( Utilities.mergeImages( ICON_ARTIFACT.getImage(), ICON_BROKEN_BADGE.getImage(), 7, 7 ) ); 192 } 193 return ICON_BROKEN_ARTIFACT; 194 } 195 else { 196 Project p = item.getArtifact().getProject(); 197 if (p != null) { 198 ProjectInformation pi = ProjectUtils.getInformation(p); 199 return pi.getIcon(); 200 } 201 return ICON_ARTIFACT; 202 } 203 case ClassPathSupport.Item.TYPE_JAR: 204 if ( item.isBroken() ) { 205 if ( ICON_BROKEN_JAR == null ) { 206 ICON_BROKEN_JAR = new ImageIcon ( Utilities.mergeImages( ICON_JAR.getImage(), ICON_BROKEN_BADGE.getImage(), 7, 7 ) ); 207 } 208 return ICON_BROKEN_JAR; 209 } 210 else { 211 File file = item.getFile(); 212 return file.isDirectory() ? getFolderIcon() : ICON_JAR; 213 } 214 case ClassPathSupport.Item.TYPE_CLASSPATH: 215 return ICON_CLASSPATH; 216 217 } 218 219 return null; } 221 222 private String getToolTipText( ClassPathSupport.Item item ) { 223 if ( item.isBroken() && 224 ( item.getType() == ClassPathSupport.Item.TYPE_JAR || 225 item.getType() == ClassPathSupport.Item.TYPE_ARTIFACT ) ) { 226 return evaluator.evaluate( item.getReference() ); 227 } 228 229 return getDisplayName( item ); } 231 232 private static ImageIcon getFolderIcon() { 233 234 if ( ICON_FOLDER == null ) { 235 FileObject root = Repository.getDefault().getDefaultFileSystem().getRoot(); 236 DataFolder dataFolder = DataFolder.findFolder( root ); 237 ICON_FOLDER = new ImageIcon ( dataFolder.getNodeDelegate().getIcon( BeanInfo.ICON_COLOR_16x16 ) ); 238 } 239 240 return ICON_FOLDER; 241 } 242 243 private String getProjectName( ClassPathSupport.Item item ) { 244 String ID = item.getReference(); 245 return ID.substring(12, ID.indexOf(".", 12)); } 248 249 private String getLibraryName( ClassPathSupport.Item item ) { 250 String ID = item.getReference(); 251 return ID.substring(7, ID.indexOf(".classpath")); } 254 255 private String getFileRefName( ClassPathSupport.Item item ) { 256 String ID = item.getReference(); 257 Matcher m = FOREIGN_PLAIN_FILE_REFERENCE.matcher(ID); 259 if (m.matches()) { 260 return m.group(1); 261 } 262 m = UNKNOWN_FILE_REFERENCE.matcher(ID); 263 if (m.matches()) { 264 return m.group(1); 265 } 266 return ID; 267 } 268 269 270 271 } 272 273 274 public static class EditMediator implements ActionListener , ListSelectionListener { 275 276 private final Project project; 277 private final ListComponent list; 278 private final DefaultListModel listModel; 279 private final ListSelectionModel selectionModel; 280 private final ButtonModel addJar; 281 private final ButtonModel addLibrary; 282 private final ButtonModel addAntArtifact; 283 private final ButtonModel remove; 284 private final ButtonModel moveUp; 285 private final ButtonModel moveDown; 286 private final boolean includeNewFilesInDeployment; 287 288 public EditMediator( Project project, 289 ListComponent list, 290 ButtonModel addJar, 291 ButtonModel addLibrary, 292 ButtonModel addAntArtifact, 293 ButtonModel remove, 294 ButtonModel moveUp, 295 ButtonModel moveDown, 296 boolean includeNewFilesInDeployment) { 297 298 300 this.list = list; 301 302 if ( !( list.getModel() instanceof DefaultListModel ) ) { 303 throw new IllegalArgumentException ( "The list's model has to be of class DefaultListModel" ); } 305 306 this.listModel = (DefaultListModel )list.getModel(); 307 this.selectionModel = list.getSelectionModel(); 308 309 this.addJar = addJar; 310 this.addLibrary = addLibrary; 311 this.addAntArtifact = addAntArtifact; 312 this.remove = remove; 313 this.moveUp = moveUp; 314 this.moveDown = moveDown; 315 316 this.project = project; 317 this.includeNewFilesInDeployment = includeNewFilesInDeployment; 318 } 319 320 public static void register(Project project, 321 ListComponent list, 322 ButtonModel addJar, 323 ButtonModel addLibrary, 324 ButtonModel addAntArtifact, 325 ButtonModel remove, 326 ButtonModel moveUp, 327 ButtonModel moveDown, 328 boolean includeNewFilesInDeployment) { 329 330 EditMediator em = new EditMediator( project, 331 list, 332 addJar, 333 addLibrary, 334 addAntArtifact, 335 remove, 336 moveUp, 337 moveDown, 338 includeNewFilesInDeployment ); 339 340 addJar.addActionListener( em ); 342 addLibrary.addActionListener( em ); 343 addAntArtifact.addActionListener( em ); 344 remove.addActionListener( em ); 345 moveUp.addActionListener( em ); 346 moveDown.addActionListener( em ); 347 em.selectionModel.addListSelectionListener( em ); 349 em.valueChanged( null ); 351 } 352 353 355 357 public void actionPerformed( ActionEvent e ) { 358 359 Object source = e.getSource(); 360 361 if ( source == addJar ) { 362 JFileChooser chooser = new JFileChooser (); 364 FileUtil.preventFileChooserSymlinkTraversal(chooser, null); 365 chooser.setFileSelectionMode( JFileChooser.FILES_AND_DIRECTORIES ); 366 chooser.setMultiSelectionEnabled( true ); 367 chooser.setDialogTitle( NbBundle.getMessage( AppClientClassPathUi.class, "LBL_AddJar_DialogTitle" ) ); chooser.setAcceptAllFileFilterUsed( false ); 370 chooser.setFileFilter( new SimpleFileFilter( 371 NbBundle.getMessage( AppClientClassPathUi.class, "LBL_ZipJarFolderFilter" ), new String [] {"ZIP","JAR"} ) ); File curDir = FoldersListSettings.getDefault().getLastUsedClassPathFolder(); 374 chooser.setCurrentDirectory (curDir); 375 int option = chooser.showOpenDialog( SwingUtilities.getWindowAncestor( list.getComponent() ) ); 377 if ( option == JFileChooser.APPROVE_OPTION ) { 378 379 File files[] = chooser.getSelectedFiles(); 380 int[] newSelection = ClassPathUiSupport.addJarFiles( listModel, list.getSelectedIndices(), files, includeNewFilesInDeployment ); 381 list.setSelectedIndices( newSelection ); 382 curDir = FileUtil.normalizeFile(chooser.getCurrentDirectory()); 383 FoldersListSettings.getDefault().setLastUsedClassPathFolder(curDir); 384 } 385 } 386 else if ( source == addLibrary ) { 387 Set <Library> includedLibraries = new HashSet <Library>(); 388 for (int i=0; i< listModel.getSize(); i++) { 389 ClassPathSupport.Item item = (ClassPathSupport.Item) listModel.get(i); 390 if (item.getType() == ClassPathSupport.Item.TYPE_LIBRARY && !item.isBroken() ) { 391 includedLibraries.add( item.getLibrary() ); 392 } 393 } 394 Object [] options = new Object [] { 395 new JButton (NbBundle.getMessage (AppClientClassPathUi.class,"LBL_AddLibrary")), 396 DialogDescriptor.CANCEL_OPTION 397 }; 398 ((JButton )options[0]).setEnabled(false); 399 ((JButton )options[0]).getAccessibleContext().setAccessibleDescription (NbBundle.getMessage (AppClientClassPathUi.class,"AD_AddLibrary")); 400 LibrariesChooser panel = new LibrariesChooser ((JButton )options[0], includedLibraries); 401 DialogDescriptor desc = new DialogDescriptor(panel,NbBundle.getMessage( AppClientClassPathUi.class, "LBL_CustomizeCompile_Classpath_AddLibrary" ), 402 true, options, options[0], DialogDescriptor.DEFAULT_ALIGN,null,null); 403 Dialog dlg = DialogDisplayer.getDefault().createDialog(desc); 404 dlg.setVisible(true); 405 if (desc.getValue() == options[0]) { 406 int[] newSelection = ClassPathUiSupport.addLibraries( listModel, list.getSelectedIndices(), panel.getSelectedLibraries(), includedLibraries, includeNewFilesInDeployment ); 407 list.setSelectedIndices( newSelection ); 408 } 409 dlg.dispose(); 410 } 411 else if ( source == addAntArtifact ) { 412 AntArtifactChooser.ArtifactItem artifactItems[] = AntArtifactChooser.showDialog(JavaProjectConstants.ARTIFACT_TYPE_JAR, project, list.getComponent().getParent()); 413 if (artifactItems != null) { 414 int[] newSelection = ClassPathUiSupport.addArtifacts( listModel, list.getSelectedIndices(), artifactItems, includeNewFilesInDeployment ); 415 list.setSelectedIndices( newSelection ); 416 } 417 } 418 else if ( source == remove ) { 419 int[] newSelection = ClassPathUiSupport.remove( listModel, list.getSelectedIndices() ); 420 list.setSelectedIndices( newSelection ); 421 } 422 else if ( source == moveUp ) { 423 int[] newSelection = ClassPathUiSupport.moveUp( listModel, list.getSelectedIndices() ); 424 list.setSelectedIndices( newSelection ); 425 } 426 else if ( source == moveDown ) { 427 int[] newSelection = ClassPathUiSupport.moveDown( listModel, list.getSelectedIndices() ); 428 list.setSelectedIndices( newSelection ); 429 } 430 } 431 432 433 435 public void valueChanged( ListSelectionEvent e ) { 436 437 boolean canRemove = false; 439 if ( selectionModel.getMinSelectionIndex() != -1 ) { 441 canRemove = true; 442 int iMin = selectionModel.getMinSelectionIndex(); 443 int iMax = selectionModel.getMinSelectionIndex(); 444 for ( int i = iMin; i <= iMax; i++ ) { 445 446 if ( selectionModel.isSelectedIndex( i ) ) { 447 ClassPathSupport.Item item = (ClassPathSupport.Item)listModel.get( i ); 448 if ( item.getType() == ClassPathSupport.Item.TYPE_CLASSPATH ) { 449 canRemove = false; 450 break; 451 } 452 } 453 } 454 } 455 456 remove.setEnabled( canRemove ); 461 moveUp.setEnabled( ClassPathUiSupport.canMoveUp( selectionModel ) ); 462 moveDown.setEnabled( ClassPathUiSupport.canMoveDown( selectionModel, listModel.getSize() ) ); 463 464 } 465 466 public interface ListComponent { 467 public Component getComponent(); 468 public int[] getSelectedIndices(); 469 public void setSelectedIndices(int[] indices); 470 public DefaultListModel getModel(); 471 public ListSelectionModel getSelectionModel(); 472 } 473 474 private static final class JListListComponent implements ListComponent { 475 private JList list; 476 private DefaultListModel model; 477 478 public JListListComponent(JList list) { 479 this.list = list; 480 this.model = model; 481 } 482 483 public Component getComponent() { 484 return list; 485 } 486 487 public int[] getSelectedIndices() { 488 return list.getSelectedIndices(); 489 } 490 491 public void setSelectedIndices(int[] indices) { 492 list.setSelectedIndices(indices); 493 } 494 495 public DefaultListModel getModel() { 496 return (DefaultListModel )list.getModel(); 497 } 498 499 public ListSelectionModel getSelectionModel() { 500 return list.getSelectionModel(); 501 } 502 } 503 504 private static final class JTableListComponent implements ListComponent { 505 private JTable table; 506 private DefaultListModel model; 507 508 public JTableListComponent(JTable table, DefaultListModel model) { 509 this.table = table; 510 this.model = model; 511 } 512 513 public Component getComponent() { 514 return table; 515 } 516 517 public int[] getSelectedIndices() { 518 return table.getSelectedRows(); 519 } 520 521 public void setSelectedIndices(int[] indices) { 522 table.clearSelection(); 523 for (int i = 0; i < indices.length; i++) { 524 table.addRowSelectionInterval(indices[i], indices[i]); 525 } 526 } 527 528 public DefaultListModel getModel() { 529 return model; 530 } 531 532 public ListSelectionModel getSelectionModel() { 533 return table.getSelectionModel(); 534 } 535 } 536 537 public static ListComponent createListComponent(JList list) { 538 return new JListListComponent(list); 539 } 540 541 public static ListComponent createListComponent(JTable table, DefaultListModel model) { 542 return new JTableListComponent(table, model); 543 } 544 } 545 546 private static class SimpleFileFilter extends FileFilter { 547 548 private String description; 549 private Collection extensions; 550 551 552 public SimpleFileFilter (String description, String [] extensions) { 553 this.description = description; 554 this.extensions = Arrays.asList(extensions); 555 } 556 557 public boolean accept(File f) { 558 if (f.isDirectory()) 559 return true; 560 String name = f.getName(); 561 int index = name.lastIndexOf('.'); if (index <= 0 || index==name.length()-1) 563 return false; 564 String extension = name.substring (index+1).toUpperCase(); 565 return this.extensions.contains(extension); 566 } 567 568 public String getDescription() { 569 return this.description; 570 } 571 } 572 573 public static class ClassPathTableCellItemRenderer extends DefaultTableCellRenderer { 574 575 private ClassPathListCellRenderer renderer; 576 private TableCellRenderer booleanRenderer; 577 578 public ClassPathTableCellItemRenderer(PropertyEvaluator evaluator) { 579 renderer = new ClassPathListCellRenderer(evaluator); 580 } 581 582 public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column ) { 583 584 if (value instanceof ClassPathSupport.Item) { 585 ClassPathSupport.Item item = (ClassPathSupport.Item)value; 586 setIcon( renderer.getIcon( item ) ); 587 setToolTipText( renderer.getToolTipText( item ) ); 588 return super.getTableCellRendererComponent(table, renderer.getDisplayName( item ), isSelected, false, row, column); 589 } else { 590 if (value instanceof Boolean && booleanRenderer != null) 591 return booleanRenderer.getTableCellRendererComponent( table, value, isSelected, false, row, column ); 592 else { 593 setIcon( null ); 594 return super.getTableCellRendererComponent( table, value, isSelected, false, row, column ); 595 } 596 } 597 } 598 599 public void setBooleanRenderer(TableCellRenderer booleanRenderer) { 600 this.booleanRenderer = booleanRenderer; 601 } 602 } 603 604 } 605 | Popular Tags |