KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > apisupport > project > ui > LibrariesNode


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.apisupport.project.ui;
21
22 import java.awt.Dialog JavaDoc;
23 import java.awt.Image JavaDoc;
24 import java.awt.event.ActionEvent JavaDoc;
25 import java.awt.event.ActionListener JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Arrays JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.SortedSet JavaDoc;
34 import java.util.TreeSet JavaDoc;
35 import javax.swing.AbstractAction JavaDoc;
36 import javax.swing.Action JavaDoc;
37 import javax.swing.Icon JavaDoc;
38 import javax.swing.ImageIcon JavaDoc;
39 import org.netbeans.api.project.Project;
40 import org.netbeans.api.project.ProjectManager;
41 import org.netbeans.api.project.ui.OpenProjects;
42 import org.netbeans.modules.apisupport.project.NbModuleProject;
43 import org.netbeans.modules.apisupport.project.spi.NbModuleProvider;
44 import org.netbeans.modules.apisupport.project.ProjectXMLManager;
45 import org.netbeans.modules.apisupport.project.Util;
46 import org.netbeans.modules.apisupport.project.ui.ModulesNodeFactory.AddNewLibraryWrapperAction;
47 import org.netbeans.modules.apisupport.project.ui.customizer.AddModulePanel;
48 import org.netbeans.modules.apisupport.project.ui.customizer.EditDependencyPanel;
49 import org.netbeans.modules.apisupport.project.ui.customizer.ModuleDependency;
50 import org.netbeans.modules.apisupport.project.ui.customizer.SingleModuleProperties;
51 import org.netbeans.modules.apisupport.project.universe.ModuleEntry;
52 import org.netbeans.modules.apisupport.project.universe.NbPlatform;
53 import org.netbeans.modules.apisupport.project.universe.TestModuleDependency;
54 import org.netbeans.spi.java.project.support.ui.PackageView;
55 import org.netbeans.spi.project.support.ant.AntProjectEvent;
56 import org.netbeans.spi.project.support.ant.AntProjectHelper;
57 import org.netbeans.spi.project.support.ant.AntProjectListener;
58 import org.openide.DialogDescriptor;
59 import org.openide.DialogDisplayer;
60 import org.openide.ErrorManager;
61 import org.openide.actions.DeleteAction;
62 import org.openide.actions.FindAction;
63 import org.openide.awt.HtmlBrowser;
64 import org.openide.awt.StatusDisplayer;
65 import org.openide.filesystems.FileObject;
66 import org.openide.filesystems.FileUtil;
67 import org.openide.filesystems.URLMapper;
68 import org.openide.nodes.AbstractNode;
69 import org.openide.nodes.Children;
70 import org.openide.nodes.FilterNode;
71 import org.openide.nodes.Node;
72 import org.openide.util.HelpCtx;
73 import org.openide.util.Mutex;
74 import org.openide.util.MutexException;
75 import org.openide.util.NbBundle;
76 import org.openide.util.RequestProcessor;
77 import org.openide.util.Utilities;
78 import org.openide.util.actions.CookieAction;
79 import org.openide.util.actions.SystemAction;
80 import org.openide.util.lookup.Lookups;
81 import org.openide.util.lookup.ProxyLookup;
82
83 /**
84  * @author Martin Krauskopf
85  */

86 final class LibrariesNode extends AbstractNode {
87     
88     static final String JavaDoc LIBRARIES_NAME = "libraries"; // NOI18N
89

90     private static final String JavaDoc DISPLAY_NAME = getMessage("LBL_libraries");
91     
92     /** Package private for unit tests only. */
93     static final RequestProcessor RP = new RequestProcessor();
94     
95     private final Action JavaDoc[] actions;
96     
97     public LibrariesNode(final NbModuleProject project) {
98         super(new LibrariesChildren(project));
99         setName(LIBRARIES_NAME);
100         setDisplayName(DISPLAY_NAME);
101         if (Util.getModuleType(project) == NbModuleProvider.SUITE_COMPONENT) {
102             actions = new Action JavaDoc[] {
103                 new AddModuleDependencyAction(project),
104                 new AddNewLibraryWrapperAction(project, project)
105             };
106         } else {
107             actions = new Action JavaDoc[] {
108                 new AddModuleDependencyAction(project),
109             };
110         }
111     }
112     
113     public Image JavaDoc getIcon(int type) {
114         return getIcon(false);
115     }
116     
117     public Image JavaDoc getOpenedIcon(int type) {
118         return getIcon(true);
119     }
120     
121     private Image JavaDoc getIcon(boolean opened) {
122         Image JavaDoc badge = Utilities.loadImage("org/netbeans/modules/apisupport/project/ui/resources/libraries-badge.png", true);
123         return Utilities.mergeImages(UIUtil.getTreeFolderIcon(opened), badge, 8, 8);
124     }
125     
126     public Action JavaDoc[] getActions(boolean context) {
127         return actions;
128     }
129     
130     private static String JavaDoc createHtmlDescription(final ModuleDependency dep) {
131         // assemble an html short description (tooltip actually)
132
StringBuffer JavaDoc shortDesc = new StringBuffer JavaDoc("<html><u>" + dep.getModuleEntry().getCodeNameBase() + "</u><br>"); // NOI18N
133
if (dep.hasImplementationDepedendency()) {
134             shortDesc.append("<br><font color=\"red\">" + getMessage("CTL_ImplementationDependency") + "</font>");
135         }
136         if (dep.hasCompileDependency()) {
137             shortDesc.append("<br>").append(getMessage("CTL_NeededToCompile"));
138         }
139         if (dep.getReleaseVersion() != null) {
140             shortDesc.append("<br>").append(NbBundle.getMessage(LibrariesNode.class, "CTL_MajorReleaseVersion",
141                     dep.getReleaseVersion()));
142         }
143         if (dep.getSpecificationVersion() != null) {
144             shortDesc.append("<br>").append(NbBundle.getMessage(LibrariesNode.class, "CTL_SpecificationVersion",
145                     dep.getSpecificationVersion()));
146         }
147         shortDesc.append("</html>"); // NOI18N
148
return shortDesc.toString();
149     }
150     
151     private static String JavaDoc getMessage(String JavaDoc bundleKey) {
152         return NbBundle.getMessage(LibrariesNode.class, bundleKey);
153     }
154     
155     private static final class LibrariesChildren extends Children.Keys<Object JavaDoc/*JDK_PLATFORM_NAME|ModuleDependency*/> implements AntProjectListener {
156         
157         private static final String JavaDoc JDK_PLATFORM_NAME = "jdkPlatform"; // NOI18N
158

159         private static final String JavaDoc LIBRARIES_ICON =
160                 "org/netbeans/modules/apisupport/project/ui/resources/libraries.gif"; // NOI18N
161

162         private final NbModuleProject project;
163         
164         private ImageIcon JavaDoc librariesIcon;
165         
166         LibrariesChildren(final NbModuleProject project) {
167             this.project = project;
168         }
169         
170         protected void addNotify() {
171             super.addNotify();
172             project.getHelper().addAntProjectListener(this);
173             refreshKeys();
174         }
175         
176         protected void removeNotify() {
177             setKeys(Collections.emptySet());
178             project.getHelper().removeAntProjectListener(this);
179             super.removeNotify();
180         }
181         
182         private void refreshKeys() {
183             // Since miscellaneous operations may be run upon the project.xml
184
// of individual projects we could be called from the same thread
185
// with already acquired ProjectManager.mutex. This could lead to
186
// refreshing during the misconfigurated suite/suite_component
187
// relationship.
188
RP.post(new Runnable JavaDoc() {
189                 public void run() {
190                     try {
191                         ProjectManager.mutex().readAccess(new Mutex.ExceptionAction<Void JavaDoc>() {
192                             public Void JavaDoc run() throws Exception JavaDoc {
193                                 ProjectXMLManager pxm = new ProjectXMLManager(project);
194                                 final List JavaDoc<Object JavaDoc> keys = new ArrayList JavaDoc<Object JavaDoc>();
195                                 keys.add(JDK_PLATFORM_NAME);
196                                 SortedSet JavaDoc<ModuleDependency> deps = new TreeSet JavaDoc<ModuleDependency>(ModuleDependency.LOCALIZED_NAME_COMPARATOR);
197                                 deps.addAll(pxm.getDirectDependencies());
198                                 keys.addAll(deps);
199                                 // XXX still not good when dependency was just edited, since Children use
200
// hashCode/equals (probably HashMap) to find lastly selected node (so neither
201
// SortedSet would help here). Use probably wrapper instead to keep selection.
202
RP.post(new Runnable JavaDoc() {
203                                     public void run() {
204                                         setKeys(Collections.unmodifiableList(keys));
205                                     }
206                                 });
207                                 return null;
208                             }
209                         });
210                     } catch (MutexException e) {
211                         assert false : e.getException();
212                     }
213                 }
214             });
215         }
216         
217         protected Node[] createNodes(Object JavaDoc key) {
218             Node node;
219             if (key == JDK_PLATFORM_NAME) {
220                 node = PlatformNode.create(project.evaluator(), "nbjdk.home"); // NOI18N
221
} else {
222                 ModuleDependency dep = (ModuleDependency) key;
223                 File JavaDoc srcF = dep.getModuleEntry().getSourceLocation();
224                 if (srcF == null) {
225                     File JavaDoc jarF = dep.getModuleEntry().getJarLocation();
226                     URL JavaDoc jarRootURL = Util.urlForJar(jarF);
227                     assert jarRootURL != null;
228                     FileObject root = URLMapper.findFileObject(jarRootURL);
229                     ModuleEntry me = dep.getModuleEntry();
230                     String JavaDoc name = me.getLocalizedName() + " - " + me.getCodeNameBase(); // NOI18N
231
Icon JavaDoc icon = getLibrariesIcon();
232                     Node pvNode = ActionFilterNode.create(
233                             PackageView.createPackageView(new LibrariesSourceGroup(root, name, icon, icon)));
234                     node = new LibraryDependencyNode(dep, project, pvNode);
235                 } else {
236                     node = new ProjectDependencyNode(dep, project);
237                 }
238             }
239             assert node != null;
240             return new Node[] { node };
241         }
242         
243         public void configurationXmlChanged(AntProjectEvent ev) {
244             // XXX this is a little strange but happens during project move. Bad ordering.
245
// Probably bug in moving implementation (our or in general Project API).
246
if (project.getHelper().resolveFileObject(AntProjectHelper.PROJECT_XML_PATH) != null) {
247                 refreshKeys();
248             }
249         }
250         
251         public void propertiesChanged(AntProjectEvent ev) {
252             // do not need
253
}
254         
255         /*
256         private Node getNodeDelegate(final File jarF) {
257             Node n = null;
258             assert jarF != null;
259             FileObject jar = FileUtil.toFileObject(jarF);
260             if (jarF != null) {
261                 DataObject dobj;
262                 try {
263                     dobj = DataObject.find(jar);
264                     if (dobj != null) {
265                         n = dobj.getNodeDelegate();
266                     }
267                 } catch (DataObjectNotFoundException e) {
268                     assert false : e;
269                 }
270             }
271             return n;
272         }
273          */

274         
275         private Icon JavaDoc getLibrariesIcon() {
276             if (librariesIcon == null) {
277                 librariesIcon = new ImageIcon JavaDoc(Utilities.loadImage(LIBRARIES_ICON, true));
278             }
279             return librariesIcon;
280         }
281         
282     }
283     
284     private static final class ProjectDependencyNode extends AbstractNode {
285         
286         private final ModuleDependency dep;
287         private final NbModuleProject project;
288         
289         ProjectDependencyNode(final ModuleDependency dep, final NbModuleProject project) {
290             super(Children.LEAF, Lookups.fixed(dep, project, dep.getModuleEntry()));
291             this.dep = dep;
292             this.project = project;
293             ModuleEntry me = dep.getModuleEntry();
294             setIconBaseWithExtension(NbModuleProject.NB_PROJECT_ICON_PATH);
295             setDisplayName(me.getLocalizedName());
296             setShortDescription(LibrariesNode.createHtmlDescription(dep));
297         }
298         
299         public Action JavaDoc[] getActions(boolean context) {
300             return new Action JavaDoc[] {
301                 SystemAction.get(OpenProjectAction.class),
302                 new EditDependencyAction(dep, project),
303                 new ShowJavadocAction(dep, project),
304                 SystemAction.get(RemoveAction.class),
305             };
306         }
307         
308         public Action JavaDoc getPreferredAction() {
309             return getActions(false)[0]; // open
310
}
311
312         public boolean canDestroy() {
313             return true;
314         }
315
316         public void destroy() throws IOException JavaDoc {
317             removeDependency(project, dep);
318         }
319         
320     }
321     
322     private static final class LibraryDependencyNode extends FilterNode {
323         
324         private final ModuleDependency dep;
325         private final NbModuleProject project;
326         
327         LibraryDependencyNode(final ModuleDependency dep,
328                 final NbModuleProject project, final Node original) {
329             super(original, null, new ProxyLookup(original.getLookup(), Lookups.fixed(dep, project)));
330             this.dep = dep;
331             this.project = project;
332             setShortDescription(LibrariesNode.createHtmlDescription(dep));
333         }
334         
335         public Action JavaDoc[] getActions(boolean context) {
336             return new Action JavaDoc[] {
337                 new EditDependencyAction(dep, project),
338                 SystemAction.get(FindAction.class),
339                 new ShowJavadocAction(dep, project),
340                 SystemAction.get(RemoveAction.class),
341             };
342         }
343         
344         public Action JavaDoc getPreferredAction() {
345             return new EditDependencyAction(dep, project);
346         }
347
348         public boolean canDestroy() {
349             return true;
350         }
351
352         public void destroy() throws IOException JavaDoc {
353             removeDependency(project, dep);
354         }
355         
356     }
357     
358     private static void removeDependency(NbModuleProject project, ModuleDependency dep) throws IOException JavaDoc {
359         new ProjectXMLManager(project).removeDependencies(Collections.singleton(dep));
360         ProjectManager.getDefault().saveProject(project);
361     }
362     
363     private static final class AddModuleDependencyAction extends AbstractAction JavaDoc {
364         
365         private final NbModuleProject project;
366         
367         AddModuleDependencyAction(final NbModuleProject project) {
368             super(getMessage("CTL_AddModuleDependency"));
369             this.project = project;
370         }
371         
372         public void actionPerformed(ActionEvent JavaDoc ev) {
373             // XXX duplicated from CustomizerLibraries --> Refactor
374
SingleModuleProperties props = SingleModuleProperties.getInstance(project);
375             final AddModulePanel addPanel = new AddModulePanel(props);
376             final DialogDescriptor descriptor = new DialogDescriptor(addPanel,
377                     getMessage("CTL_AddModuleDependencyTitle"));
378             descriptor.setHelpCtx(new HelpCtx(AddModulePanel.class));
379             descriptor.setClosingOptions(new Object JavaDoc[0]);
380             final Dialog JavaDoc d = DialogDisplayer.getDefault().createDialog(descriptor);
381             descriptor.setButtonListener(new ActionListener JavaDoc() {
382                 public void actionPerformed(ActionEvent JavaDoc e) {
383                     if (DialogDescriptor.OK_OPTION.equals(e.getSource()) &&
384                             addPanel.getSelectedDependencies().length == 0) {
385                         return;
386                     }
387                     d.setVisible(false);
388                     d.dispose();
389                 }
390             });
391             d.setVisible(true);
392             if (descriptor.getValue().equals(DialogDescriptor.OK_OPTION)) {
393                 ModuleDependency[] newDeps = addPanel.getSelectedDependencies();
394                 ProjectXMLManager pxm = new ProjectXMLManager(project);
395                 try {
396                     for (ModuleDependency dep : newDeps) {
397                         pxm.addDependency(dep);
398                     }
399                     ProjectManager.getDefault().saveProject(project);
400                 } catch (IOException JavaDoc e) {
401                     ErrorManager.getDefault().annotate(e, "Cannot add selected dependencies: " + Arrays.asList(newDeps)); // NOI18N
402
ErrorManager.getDefault().notify(e);
403                 }
404             }
405             d.dispose();
406         }
407         
408     }
409     
410     private static final class EditDependencyAction extends AbstractAction JavaDoc {
411         
412         private final ModuleDependency dep;
413         private final NbModuleProject project;
414         
415         EditDependencyAction(final ModuleDependency dep, final NbModuleProject project) {
416             super(getMessage("CTL_EditDependency"));
417             this.dep = dep;
418             this.project = project;
419         }
420         
421         public void actionPerformed(ActionEvent JavaDoc ev) {
422             // XXX duplicated from CustomizerLibraries --> Refactor
423
EditDependencyPanel editPanel = new EditDependencyPanel(dep,
424                     NbPlatform.getPlatformByDestDir(dep.getModuleEntry().getDestDir()));
425             DialogDescriptor descriptor = new DialogDescriptor(editPanel,
426                     NbBundle.getMessage(LibrariesNode.class, "CTL_EditModuleDependencyTitle",
427                     dep.getModuleEntry().getLocalizedName()));
428             descriptor.setHelpCtx(new HelpCtx(EditDependencyPanel.class));
429             Dialog JavaDoc d = DialogDisplayer.getDefault().createDialog(descriptor);
430             d.setVisible(true);
431             if (descriptor.getValue().equals(DialogDescriptor.OK_OPTION)) {
432                 ModuleDependency editedDep = editPanel.getEditedDependency();
433                 try {
434                     ProjectXMLManager pxm = new ProjectXMLManager(project);
435                     SortedSet JavaDoc<ModuleDependency> deps = new TreeSet JavaDoc<ModuleDependency>(pxm.getDirectDependencies());
436                     deps.remove(dep);
437                     deps.add(editedDep);
438                     pxm.replaceDependencies(deps);
439                     ProjectManager.getDefault().saveProject(project);
440                 } catch (IOException JavaDoc e) {
441                     ErrorManager.getDefault().annotate(e, "Cannot store dependency: " + editedDep); // NOI18N
442
ErrorManager.getDefault().notify(e);
443                 }
444             }
445             d.dispose();
446         }
447         
448     }
449     
450     private static final class ShowJavadocAction extends AbstractAction JavaDoc {
451         
452         private final ModuleDependency dep;
453         private final NbModuleProject project;
454         
455         private URL JavaDoc currectJavadoc;
456         
457         ShowJavadocAction(final ModuleDependency dep, final NbModuleProject project) {
458             super(getMessage("CTL_ShowJavadoc"));
459             this.dep = dep;
460             this.project = project;
461         }
462         
463         public void actionPerformed(ActionEvent JavaDoc ev) {
464             HtmlBrowser.URLDisplayer.getDefault().showURL(currectJavadoc);
465         }
466         
467         public boolean isEnabled() {
468             if (Util.getModuleType(project) == NbModuleProvider.NETBEANS_ORG) {
469                 currectJavadoc = Util.findJavadocForNetBeansOrgModules(dep);
470             } else {
471                 currectJavadoc = Util.findJavadoc(dep, project.getPlatform(true));
472             }
473             return currectJavadoc != null;
474         }
475         
476     }
477     
478     static final class OpenProjectAction extends CookieAction {
479         
480         protected void performAction(Node[] activatedNodes) {
481             try {
482                 final Project[] projects = new Project[activatedNodes.length];
483                 for (int i = 0; i < activatedNodes.length; i++) {
484                     ModuleEntry me = activatedNodes[i].getLookup().lookup(ModuleEntry.class);
485                     assert me != null;
486                     File JavaDoc prjDir = me.getSourceLocation();
487                     assert prjDir != null;
488                     Project project = ProjectManager.getDefault().findProject(FileUtil.toFileObject(prjDir));
489                     assert project != null;
490                     projects[i] = project;
491                 }
492                 RequestProcessor.getDefault().post(new Runnable JavaDoc() {
493                     public void run() {
494                         StatusDisplayer.getDefault().setStatusText(
495                                 getMessage("MSG_OpeningProjects"));
496                         OpenProjects.getDefault().open(projects, false);
497                     }
498                 });
499             } catch (IOException JavaDoc e) {
500                 assert false : e;
501             }
502         }
503         
504         public boolean isEnabled() {
505             return true;
506         }
507         
508         public String JavaDoc getName() {
509             return getMessage("CTL_Open");
510         }
511         
512         public HelpCtx getHelpCtx() {
513             return HelpCtx.DEFAULT_HELP;
514         }
515         
516         protected boolean asynchronous() {
517             return false;
518         }
519         
520         protected int mode() {
521             return CookieAction.MODE_ALL;
522         }
523         
524         protected Class JavaDoc[] cookieClasses() {
525             return new Class JavaDoc[] { ModuleDependency.class, TestModuleDependency.class };
526         }
527         
528     }
529     
530     private static final class RemoveAction extends DeleteAction {
531         
532         public String JavaDoc getName() {
533             return getMessage("CTL_RemoveDependency");
534         }
535
536         protected void initialize() {
537             super.initialize();
538             putValue(Action.ACCELERATOR_KEY, SystemAction.get(DeleteAction.class).getValue(Action.ACCELERATOR_KEY));
539         }
540         
541     }
542     
543 }
544
Popular Tags