1 19 20 package org.netbeans.modules.apisupport.project.ui; 21 22 import java.awt.Dialog ; 23 import java.awt.Image ; 24 import java.awt.event.ActionEvent ; 25 import java.awt.event.ActionListener ; 26 import java.io.File ; 27 import java.io.IOException ; 28 import java.net.URL ; 29 import java.util.ArrayList ; 30 import java.util.Arrays ; 31 import java.util.Collections ; 32 import java.util.HashMap ; 33 import java.util.HashSet ; 34 import java.util.Iterator ; 35 import java.util.LinkedHashSet ; 36 import java.util.List ; 37 import java.util.Map ; 38 import java.util.Set ; 39 import java.util.SortedSet ; 40 import java.util.TreeSet ; 41 import javax.swing.AbstractAction ; 42 import javax.swing.Action ; 43 import javax.swing.Icon ; 44 import javax.swing.ImageIcon ; 45 import org.netbeans.api.project.ProjectManager; 46 import org.netbeans.modules.apisupport.project.NbModuleProject; 47 import org.netbeans.modules.apisupport.project.ProjectXMLManager; 48 import org.netbeans.modules.apisupport.project.Util; 49 import org.netbeans.modules.apisupport.project.ui.customizer.AddModulePanel; 50 import org.netbeans.modules.apisupport.project.ui.customizer.EditTestDependencyPanel; 51 import org.netbeans.modules.apisupport.project.ui.customizer.ModuleDependency; 52 import org.netbeans.modules.apisupport.project.ui.customizer.SingleModuleProperties; 53 import org.netbeans.modules.apisupport.project.universe.ModuleEntry; 54 import org.netbeans.modules.apisupport.project.universe.TestModuleDependency; 55 import org.netbeans.spi.java.project.support.ui.PackageView; 56 import org.netbeans.spi.project.support.ant.AntProjectEvent; 57 import org.netbeans.spi.project.support.ant.AntProjectHelper; 58 import org.netbeans.spi.project.support.ant.AntProjectListener; 59 import org.openide.DialogDescriptor; 60 import org.openide.DialogDisplayer; 61 import org.openide.ErrorManager; 62 import org.openide.actions.FindAction; 63 import org.openide.filesystems.FileObject; 64 import org.openide.filesystems.URLMapper; 65 import org.openide.nodes.AbstractNode; 66 import org.openide.nodes.Children; 67 import org.openide.nodes.FilterNode; 68 import org.openide.nodes.Node; 69 import org.openide.util.HelpCtx; 70 import org.openide.util.Lookup; 71 import org.openide.util.Mutex; 72 import org.openide.util.MutexException; 73 import org.openide.util.NbBundle; 74 import org.openide.util.Utilities; 75 import org.openide.util.actions.CookieAction; 76 import org.openide.util.actions.SystemAction; 77 import org.openide.util.lookup.Lookups; 78 import org.openide.util.lookup.ProxyLookup; 79 80 83 final class UnitTestLibrariesNode extends AbstractNode { 84 85 static final String UNIT_TEST_LIBRARIES_NAME = "unit libraries"; 87 private static final String DISPLAY_NAME = getMessage("LBL_unit_test_libraries"); 88 89 private final Action [] actions; 90 91 public UnitTestLibrariesNode(final NbModuleProject project) { 92 super(new LibrariesChildren(project)); 93 setName(UNIT_TEST_LIBRARIES_NAME); 94 setDisplayName(DISPLAY_NAME); 95 actions = new Action [] { 96 new AddUnitTestDependencyAction(project) 97 }; 98 } 99 100 public Image getIcon(int type) { 101 return getIcon(false); 102 } 103 104 public Image getOpenedIcon(int type) { 105 return getIcon(true); 106 } 107 108 private Image getIcon(boolean opened) { 109 Image badge = Utilities.loadImage("org/netbeans/modules/apisupport/project/ui/resources/libraries-badge.png", true); 110 return Utilities.mergeImages(UIUtil.getTreeFolderIcon(opened), badge, 8, 8); 111 } 112 113 public Action [] getActions(boolean context) { 114 return actions; 115 } 116 117 private static String createHtmlDescription(final TestModuleDependency dep) { 118 StringBuffer shortDesc = new StringBuffer ("<html><u>" + dep.getModule().getCodeNameBase() + "</u><br>"); if (dep.isTest()) { 120 shortDesc.append("<br>" + getMessage("CTL_test")); 121 } 122 if (dep.isCompile()) { 123 shortDesc.append("<br>").append(getMessage("CTL_compile")); 124 } 125 if (dep.isRecursive()) { 126 shortDesc.append("<br>").append(getMessage("CTL_recursive")); 127 } 128 shortDesc.append("</html>"); return shortDesc.toString(); 130 } 131 132 private static String getMessage(String bundleKey) { 133 return NbBundle.getMessage(UnitTestLibrariesNode.class, bundleKey); 134 } 135 136 137 private static final class LibrariesChildren extends Children.Keys implements AntProjectListener { 138 139 private static final String JUNIT = "junit"; 141 private static final String JUNIT_CNB = "org.netbeans.modules.junit"; 142 143 private static final String NBJUNIT = "nbjunit"; 145 private static final String NBJUNIT_CNB = "org.netbeans.modules.nbjunit"; 146 147 private static final String LIBRARIES_ICON = 148 "org/netbeans/modules/apisupport/project/ui/resources/libraries.gif"; 150 static final Action REMOVE_DEPENDENCY_ACTION = new RemoveDependencyAction(); 151 152 private final NbModuleProject project; 153 154 private ImageIcon librariesIcon; 155 156 LibrariesChildren(final NbModuleProject project) { 157 this.project = project; 158 } 159 160 protected void addNotify() { 161 super.addNotify(); 162 project.getHelper().addAntProjectListener(this); 163 refreshKeys(); 164 } 165 166 protected void removeNotify() { 167 setKeys(Collections.EMPTY_SET); 168 project.getHelper().removeAntProjectListener(this); 169 super.removeNotify(); 170 } 171 172 private void refreshKeys() { 173 try { 174 ProjectManager.mutex().readAccess(new Mutex.ExceptionAction() { 175 public Object run() throws Exception { 176 ProjectXMLManager pxm = new ProjectXMLManager(project); 177 List keys = new ArrayList (); 178 if(isModuleInModuleList(JUNIT_CNB)) { 179 keys.add(JUNIT); 180 } 181 if(isModuleInModuleList(NBJUNIT_CNB)) { 182 keys.add(NBJUNIT); 183 } 184 SortedSet <TestModuleDependency> deps = new TreeSet <TestModuleDependency>(TestModuleDependency.CNB_COMPARATOR); 185 Set <TestModuleDependency> d = pxm.getTestDependencies( 186 project.getModuleList()).get(TestModuleDependency.UNIT); 187 if(d != null){ 189 for (TestModuleDependency tmd : d) { 190 if(tmd.isCompile()) { 191 deps.add(tmd); 192 }; 193 } 194 keys.addAll(deps); 195 } 196 setKeys(Collections.unmodifiableList(keys)); 197 return null; 198 } 199 }); 200 } catch (MutexException e) { 201 assert false : e.getException(); 202 } 203 } 204 205 private boolean isModuleInModuleList(String cnb){ 206 ModuleEntry me = null; 207 boolean result = false; 208 try { 209 me = project.getModuleList().getEntry(cnb); 210 if(me != null) { 211 File moduleJar = me.getJarLocation(); 212 result = moduleJar.exists(); 213 214 } 215 } catch (IOException ex) { 216 java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, 217 ex.getMessage(), 218 ex); 219 }; 220 return result; 221 } 222 223 224 protected Node[] createNodes(Object key) { 225 Node node = null; 226 if (JUNIT.equals(key) || NBJUNIT.equals(key)) { 228 String cnb = null; 229 if (JUNIT.equals(key)) { 230 cnb = JUNIT_CNB; 231 } else { 232 cnb = NBJUNIT_CNB; 233 } 234 try { 235 ModuleEntry me = project.getModuleList().getEntry(cnb); 236 Icon icon = getLibrariesIcon(); File junitJar = me.getJarLocation(); 238 URL junitURL = Util.urlForJar(junitJar); 239 assert junitURL != null; 240 FileObject junitFO = URLMapper.findFileObject(junitURL); 241 String name = me.getLocalizedName(); 242 node = ActionFilterNode.create( 243 PackageView.createPackageView(new LibrariesSourceGroup(junitFO, name, icon, icon))); 244 node.setName(name); } catch (IOException ex) { 246 ex.printStackTrace(); 247 } 248 } else { 249 TestModuleDependency dep = (TestModuleDependency) key; 250 File srcF = dep.getModule().getSourceLocation(); 251 if (srcF == null) { 252 File jarF = dep.getModule().getJarLocation(); 253 URL jarRootURL = Util.urlForJar(jarF); 254 assert jarRootURL != null; 255 FileObject root = URLMapper.findFileObject(jarRootURL); 256 ModuleEntry me = dep.getModule(); 257 String name = me.getLocalizedName() + " - " + me.getCodeNameBase(); Icon icon = getLibrariesIcon(); 259 Node pvNode = ActionFilterNode.create( 260 PackageView.createPackageView(new LibrariesSourceGroup(root, name, icon, icon))); 261 node = new LibraryDependencyNode(dep, project, pvNode); 262 node.setName(me.getLocalizedName()); 263 } else { 264 node = new ProjectDependencyNode(dep, project); 265 node.setName(dep.getModule().getLocalizedName()); 266 } 267 268 } 269 270 assert node != null; 271 return new Node[] { node }; 272 } 273 274 public void configurationXmlChanged(AntProjectEvent ev) { 275 if (project.getHelper().resolveFileObject(AntProjectHelper.PROJECT_XML_PATH) != null) { 278 refreshKeys(); 279 } 280 } 281 282 public void propertiesChanged(AntProjectEvent ev) { 283 } 285 286 287 private Icon getLibrariesIcon() { 288 if (librariesIcon == null) { 289 librariesIcon = new ImageIcon (Utilities.loadImage(LIBRARIES_ICON, true)); 290 } 291 return librariesIcon; 292 } 293 294 } 295 296 private static final class ProjectDependencyNode extends AbstractNode { 297 298 private final TestModuleDependency dep; 299 private final NbModuleProject project; 300 private Action [] actions; 301 302 ProjectDependencyNode(final TestModuleDependency dep, final NbModuleProject project) { 303 super(Children.LEAF, Lookups.fixed(new Object [] { dep, project, dep.getModule()})); 304 this.dep = dep; 305 this.project = project; 306 ModuleEntry me = dep.getModule(); 307 setIconBaseWithExtension(NbModuleProject.NB_PROJECT_ICON_PATH); 308 setDisplayName(me.getLocalizedName()); 309 setShortDescription(UnitTestLibrariesNode.createHtmlDescription(dep)); 310 } 311 312 public Action [] getActions(boolean context) { 313 314 if (actions == null) { 315 Set result = new LinkedHashSet (); 316 result.add(SystemAction.get(LibrariesNode.OpenProjectAction.class)); 318 result.add(new EditTestDependencyAction(dep, project)); 320 result.add(LibrariesChildren.REMOVE_DEPENDENCY_ACTION); 322 actions = (Action []) result.toArray(new Action [result.size()]); 323 } 324 return actions; 325 } 326 327 public Action getPreferredAction() { 328 return getActions(false)[0]; } 330 331 } 332 333 private static final class LibraryDependencyNode extends FilterNode { 334 335 private final TestModuleDependency dep; 336 private final NbModuleProject project; 337 private Action [] actions; 338 339 LibraryDependencyNode(final TestModuleDependency dep, 340 final NbModuleProject project, final Node original) { 341 super(original, null, new ProxyLookup(new Lookup[] { 342 original.getLookup(), 343 Lookups.fixed(new Object [] { dep, project }) 344 })); 345 this.dep = dep; 346 this.project = project; 347 setShortDescription(UnitTestLibrariesNode.createHtmlDescription(dep)); 348 } 349 350 public Action [] getActions(boolean context) { 351 if (actions == null) { 352 Set result = new LinkedHashSet (); 353 result.add(new EditTestDependencyAction(dep, project)); 354 Action [] superActions = super.getActions(false); 355 for (int i = 0; i < superActions.length; i++) { 356 if (superActions[i] instanceof FindAction) { 357 result.add(superActions[i]); 358 } 359 } 360 result.add(LibrariesChildren.REMOVE_DEPENDENCY_ACTION); 361 actions = (Action []) result.toArray(new Action [result.size()]); 362 } 363 return actions; 364 } 365 366 public Action getPreferredAction() { 367 return getActions(false)[0]; 368 } 369 370 } 371 372 static final class AddUnitTestDependencyAction extends AbstractAction { 373 374 private final NbModuleProject project; 375 376 AddUnitTestDependencyAction(final NbModuleProject project) { 377 super(getMessage("CTL_AddTestDependency")); 378 this.project = project; 379 } 380 381 public void actionPerformed(ActionEvent ev) { 383 SingleModuleProperties props = SingleModuleProperties.getInstance(project); 384 final AddModulePanel addPanel = new AddModulePanel(props); 385 final DialogDescriptor descriptor = new DialogDescriptor(addPanel, 386 getMessage("CTL_AddTestDependency")); 387 descriptor.setHelpCtx(new HelpCtx(AddModulePanel.class)); 388 descriptor.setClosingOptions(new Object [0]); 389 final Dialog d = DialogDisplayer.getDefault().createDialog(descriptor); 390 descriptor.setButtonListener(new ActionListener () { 391 public void actionPerformed(ActionEvent e) { 392 if (DialogDescriptor.OK_OPTION.equals(e.getSource()) && 393 addPanel.getSelectedDependencies().length == 0) { 394 return; 395 } 396 d.setVisible(false); 397 d.dispose(); 398 } 399 }); 400 d.setVisible(true); 401 if (descriptor.getValue().equals(DialogDescriptor.OK_OPTION)) { 402 ModuleDependency[] newDeps = addPanel.getSelectedDependencies(); 404 ProjectXMLManager pxm = new ProjectXMLManager(project); 405 try { 406 for (int i = 0; i < newDeps.length; i++) { 407 pxm.addTestDependency(TestModuleDependency.UNIT 409 ,new TestModuleDependency(newDeps[i].getModuleEntry(), false, false, true)); 410 ProjectManager.getDefault().saveProject(project); 411 } 412 } catch (Exception e) { 413 ErrorManager.getDefault().annotate(e, "Cannot add dependencies, probably IO error: " + Arrays.asList(newDeps)); ErrorManager.getDefault().notify(e); 416 } 417 } 418 d.dispose(); 419 } 420 421 422 423 } 424 425 426 427 static final class RemoveDependencyAction extends CookieAction { 428 429 protected void performAction(Node[] activatedNodes) { 430 Map map = new HashMap (); 431 for (int i = 0; i < activatedNodes.length; i++) { 432 TestModuleDependency dep = (TestModuleDependency) activatedNodes[i].getLookup().lookup(TestModuleDependency.class); 433 assert dep != null; 434 NbModuleProject project = (NbModuleProject) activatedNodes[i].getLookup().lookup(NbModuleProject.class); 435 assert project != null; 436 Set deps = (Set ) map.get(project); 437 if (deps == null) { 438 deps = new HashSet (); 439 map.put(project, deps); 440 } 441 deps.add(dep); 442 } 443 for (Iterator it = map.entrySet().iterator(); it.hasNext();) { 444 Map.Entry me = (Map.Entry ) it.next(); 445 NbModuleProject project = (NbModuleProject) me.getKey(); 446 Set deps = (Set ) me.getValue(); 447 ProjectXMLManager pxm = new ProjectXMLManager(project); 448 for (Iterator it2 = deps.iterator(); it2.hasNext();) { 450 TestModuleDependency rem = (TestModuleDependency) it2.next(); 451 pxm.removeTestDependency(TestModuleDependency.UNIT, rem.getModule().getCodeNameBase()); 452 } 453 try { 454 ProjectManager.getDefault().saveProject(project); 455 } catch (IOException e) { 456 ErrorManager.getDefault().annotate(e, "Problem during test dependencies removing"); ErrorManager.getDefault().notify(e); 458 } 459 } 460 461 } 462 463 public String getName() { 464 return getMessage("CTL_RemoveDependency"); 465 } 466 467 public HelpCtx getHelpCtx() { 468 return HelpCtx.DEFAULT_HELP; 469 } 470 471 protected boolean asynchronous() { 472 return false; 473 } 474 475 protected int mode() { 476 return CookieAction.MODE_ALL; 477 } 478 479 protected Class [] cookieClasses() { 480 return new Class [] {TestModuleDependency.class, NbModuleProject.class }; 481 } 482 483 484 } 485 486 487 static final class EditTestDependencyAction extends AbstractAction { 488 489 private final TestModuleDependency testDep; 490 private final NbModuleProject project; 491 492 EditTestDependencyAction(final TestModuleDependency testDep, final NbModuleProject project) { 493 super(getMessage("CTL_EditDependency")); 494 this.testDep = testDep; 495 this.project = project; 496 } 497 498 499 public void actionPerformed(ActionEvent ev) { 500 final EditTestDependencyPanel editTestPanel = new EditTestDependencyPanel(testDep); 501 DialogDescriptor descriptor = new DialogDescriptor(editTestPanel, 502 NbBundle.getMessage(LibrariesNode.class, "CTL_EditModuleDependencyTitle", 503 testDep.getModule().getLocalizedName())); 504 descriptor.setHelpCtx(new HelpCtx(EditTestDependencyPanel.class)); 505 Dialog d = DialogDisplayer.getDefault().createDialog(descriptor); 506 d.setVisible(true); 507 if (descriptor.getValue().equals(DialogDescriptor.OK_OPTION)) { 508 TestModuleDependency editedDep = editTestPanel.getEditedDependency(); 509 try { 510 ProjectXMLManager pxm = new ProjectXMLManager(project); 511 final String UNIT = TestModuleDependency.UNIT; 512 pxm.removeTestDependency(UNIT, testDep.getModule().getCodeNameBase()); 513 pxm.addTestDependency(UNIT, editedDep); 514 ProjectManager.getDefault().saveProject(project); 515 516 517 } catch (IOException e) { 518 ErrorManager.getDefault().annotate(e, "Cannot store dependency: " + editedDep); ErrorManager.getDefault().notify(e); 520 } 521 522 523 } 524 d.dispose(); 525 } 526 } 527 528 } 529 530 | Popular Tags |