KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > web > project > ui > ConfFilesNodeFactory


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.web.project.ui;
21
22 import java.awt.Image JavaDoc;
23 import java.beans.PropertyChangeEvent JavaDoc;
24 import java.beans.PropertyChangeListener JavaDoc;
25 import java.io.File JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Arrays JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Set JavaDoc;
35 import javax.swing.SwingUtilities JavaDoc;
36 import javax.swing.event.ChangeEvent JavaDoc;
37 import javax.swing.event.ChangeListener JavaDoc;
38 import org.netbeans.api.project.Project;
39 import org.netbeans.api.project.ProjectUtils;
40 import org.netbeans.api.project.SourceGroup;
41 import org.netbeans.api.project.Sources;
42 import org.netbeans.api.queries.VisibilityQuery;
43 import org.netbeans.modules.j2ee.deployment.devmodules.spi.ConfigurationFilesListener;
44 import org.netbeans.modules.web.api.webmodule.WebFrameworkSupport;
45 import org.netbeans.modules.web.api.webmodule.WebModule;
46 import org.netbeans.modules.web.project.ProjectWebModule;
47 import org.netbeans.modules.web.project.WebProject;
48 import org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider;
49 import org.netbeans.spi.project.ui.support.NodeFactory;
50 import org.netbeans.spi.project.ui.support.NodeList;
51 import org.openide.ErrorManager;
52 import org.openide.actions.FindAction;
53 import org.openide.filesystems.FileChangeAdapter;
54 import org.openide.filesystems.FileChangeListener;
55 import org.openide.filesystems.FileEvent;
56 import org.openide.filesystems.FileObject;
57 import org.openide.filesystems.FileRenameEvent;
58 import org.openide.filesystems.FileStateInvalidException;
59 import org.openide.filesystems.FileStatusEvent;
60 import org.openide.filesystems.FileStatusListener;
61 import org.openide.filesystems.FileSystem;
62 import org.openide.filesystems.FileUtil;
63 import org.openide.loaders.DataFolder;
64 import org.openide.loaders.DataObject;
65 import org.openide.loaders.DataObjectNotFoundException;
66 import org.openide.nodes.Children;
67 import org.openide.nodes.Node;
68 import org.openide.util.HelpCtx;
69 import org.openide.util.Lookup;
70 import org.openide.util.NbBundle;
71 import org.openide.util.RequestProcessor;
72 import org.openide.util.Utilities;
73 import org.openide.util.WeakListeners;
74 import org.openide.util.actions.CookieAction;
75 import org.openide.util.actions.SystemAction;
76 import org.openide.util.lookup.Lookups;
77
78 /**
79  *
80  * @author mkleint
81  */

82 public final class ConfFilesNodeFactory implements NodeFactory {
83     
84     /** Creates a new instance of LibrariesNodeFactory */
85     public ConfFilesNodeFactory() {
86     }
87
88     public NodeList createNodes(Project p) {
89         WebProject project = (WebProject)p.getLookup().lookup(WebProject.class);
90         assert project != null;
91         return new ConfFilesNodeList(project);
92     }
93
94     private static class ConfFilesNodeList implements NodeList<String JavaDoc>, PropertyChangeListener JavaDoc {
95         private static final String JavaDoc CONF_FILES = "confFiles"; //NOI18N
96

97         private final WebProject project;
98         private final ArrayList JavaDoc<ChangeListener JavaDoc> listeners = new ArrayList JavaDoc<ChangeListener JavaDoc>();
99
100         ConfFilesNodeList(WebProject proj) {
101             project = proj;
102             WebLogicalViewProvider logView = (WebLogicalViewProvider) project.getLookup().lookup(WebLogicalViewProvider.class);
103             assert logView != null;
104         }
105         
106         public List JavaDoc<String JavaDoc> keys() {
107             List JavaDoc<String JavaDoc> result = new ArrayList JavaDoc<String JavaDoc>();
108             result.add(CONF_FILES);
109             return result;
110         }
111
112         public synchronized void addChangeListener(ChangeListener JavaDoc l) {
113             listeners.add(l);
114         }
115
116         public synchronized void removeChangeListener(ChangeListener JavaDoc l) {
117             listeners.remove(l);
118         }
119         
120         private void fireChange() {
121             ArrayList JavaDoc<ChangeListener JavaDoc> list = new ArrayList JavaDoc<ChangeListener JavaDoc>();
122             synchronized (this) {
123                 list.addAll(listeners);
124             }
125             Iterator JavaDoc<ChangeListener JavaDoc> it = list.iterator();
126             while (it.hasNext()) {
127                 ChangeListener JavaDoc elem = it.next();
128                 elem.stateChanged(new ChangeEvent JavaDoc( this ));
129             }
130         }
131
132         public Node node(String JavaDoc key) {
133             if (key == CONF_FILES) {
134                 return new ConfFilesNode(project);
135             }
136             assert false: "No node for key: " + key;
137             return null;
138         }
139
140         public void addNotify() {
141         }
142
143         public void removeNotify() {
144         }
145
146         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
147             // The caller holds ProjectManager.mutex() read lock
148
SwingUtilities.invokeLater(new Runnable JavaDoc() {
149                 public void run() {
150                     fireChange();
151                 }
152             });
153         }
154         
155     }
156     
157     private static Lookup createLookup(Project project) {
158         DataFolder rootFolder = DataFolder.findFolder(project.getProjectDirectory());
159         // XXX Remove root folder after FindAction rewrite
160
return Lookups.fixed(new Object JavaDoc[] {project, rootFolder});
161     }
162
163     private static final class ConfFilesNode extends org.openide.nodes.AbstractNode implements Runnable JavaDoc, FileStatusListener, ChangeListener JavaDoc, PropertyChangeListener JavaDoc {
164         private static final Image JavaDoc CONFIGURATION_FILES_BADGE = Utilities.loadImage( "org/netbeans/modules/web/project/ui/resources/config-badge.gif", true ); // NOI18N
165

166         private Node projectNode;
167         
168         // icon badging >>>
169
private Set JavaDoc files;
170         private Map JavaDoc fileSystemListeners;
171         private RequestProcessor.Task task;
172         private final Object JavaDoc privateLock = new Object JavaDoc();
173         private boolean iconChange;
174         private boolean nameChange;
175         private ChangeListener JavaDoc sourcesListener;
176         private Map JavaDoc groupsListeners;
177     private final Project project;
178         // icon badging <<<
179

180         public ConfFilesNode(Project prj) {
181             super(ConfFilesChildren.forProject(prj), createLookup(prj));
182         this.project = prj;
183             setName("configurationFiles"); // NOI18N
184

185             FileObject projectDir = prj.getProjectDirectory();
186             try {
187                 DataObject projectDo = DataObject.find(projectDir);
188                 if (projectDo != null)
189                     projectNode = projectDo.getNodeDelegate();
190             }
191             catch (DataObjectNotFoundException e) {}
192         }
193         
194         public Image JavaDoc getIcon(int type) {
195             Image JavaDoc img = computeIcon(false, type);
196             return (img != null) ? img: super.getIcon(type);
197         }
198         
199         public Image JavaDoc getOpenedIcon(int type) {
200             Image JavaDoc img = computeIcon(true, type);
201             return (img != null) ? img: super.getIcon(type);
202         }
203         
204         private Image JavaDoc computeIcon(boolean opened, int type) {
205             if (projectNode == null)
206                 return null;
207
208             Image JavaDoc image = opened ? projectNode.getOpenedIcon(type) : projectNode.getIcon(type);
209             image = Utilities.mergeImages(image, CONFIGURATION_FILES_BADGE, 7, 7);
210             return image;
211         }
212         
213         public String JavaDoc getDisplayName() {
214             return NbBundle.getMessage(ConfFilesNodeFactory.class, "LBL_Node_Config"); //NOI18N
215
}
216         
217         public javax.swing.Action JavaDoc[] getActions(boolean context) {
218             return new javax.swing.Action JavaDoc[] {
219                 SystemAction.get(FindAction.class),
220             };
221         }
222
223     public void run() {
224             boolean fireIcon;
225             boolean fireName;
226             synchronized (privateLock) {
227                 fireIcon = iconChange;
228                 fireName = nameChange;
229                 iconChange = false;
230                 nameChange = false;
231             }
232             if (fireIcon) {
233                 fireIconChange();
234                 fireOpenedIconChange();
235             }
236             if (fireName) {
237                 fireDisplayNameChange(null, null);
238             }
239     }
240
241     public void annotationChanged(FileStatusEvent event) {
242             if (task == null) {
243                 task = RequestProcessor.getDefault().create(this);
244             }
245
246             synchronized (privateLock) {
247                 if ((!iconChange && event.isIconChange()) || (!nameChange && event.isNameChange())) {
248                     Iterator JavaDoc it = files.iterator();
249                     while (it.hasNext()) {
250                         FileObject fo = (FileObject) it.next();
251                         if (event.hasChanged(fo)) {
252                             iconChange |= event.isIconChange();
253                             nameChange |= event.isNameChange();
254                         }
255                     }
256                 }
257             }
258
259             task.schedule(50); // batch by 50 ms
260
}
261
262     public void stateChanged(ChangeEvent JavaDoc e) {
263             setProjectFiles(project);
264     }
265
266     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
267             setProjectFiles(project);
268     }
269     
270         protected void setProjectFiles(Project project) {
271             Sources sources = ProjectUtils.getSources(project); // returns singleton
272
if (sourcesListener == null) {
273                 sourcesListener = WeakListeners.change(this, sources);
274                 sources.addChangeListener(sourcesListener);
275             }
276             setGroups(Arrays.asList(sources.getSourceGroups(Sources.TYPE_GENERIC)));
277         }
278
279         private void setGroups(Collection JavaDoc groups) {
280             if (groupsListeners != null) {
281                 Iterator JavaDoc it = groupsListeners.keySet().iterator();
282                 while (it.hasNext()) {
283                     SourceGroup group = (SourceGroup) it.next();
284                     PropertyChangeListener JavaDoc pcl = (PropertyChangeListener JavaDoc) groupsListeners.get(group);
285                     group.removePropertyChangeListener(pcl);
286                 }
287             }
288             groupsListeners = new HashMap JavaDoc();
289             Set JavaDoc roots = new HashSet JavaDoc();
290             Iterator JavaDoc it = groups.iterator();
291             while (it.hasNext()) {
292                 SourceGroup group = (SourceGroup) it.next();
293                 PropertyChangeListener JavaDoc pcl = WeakListeners.propertyChange(this, group);
294                 groupsListeners.put(group, pcl);
295                 group.addPropertyChangeListener(pcl);
296                 FileObject fo = group.getRootFolder();
297                 roots.add(fo);
298             }
299             setFiles(roots);
300         }
301
302         protected void setFiles(Set JavaDoc files) {
303             if (fileSystemListeners != null) {
304                 Iterator JavaDoc it = fileSystemListeners.keySet().iterator();
305                 while (it.hasNext()) {
306                     FileSystem fs = (FileSystem) it.next();
307                     FileStatusListener fsl = (FileStatusListener) fileSystemListeners.get(fs);
308                     fs.removeFileStatusListener(fsl);
309                 }
310             }
311                         
312             fileSystemListeners = new HashMap JavaDoc();
313             this.files = files;
314             if (files == null) return;
315
316             Iterator JavaDoc it = files.iterator();
317             Set JavaDoc hookedFileSystems = new HashSet JavaDoc();
318             while (it.hasNext()) {
319                 FileObject fo = (FileObject) it.next();
320                 try {
321                     FileSystem fs = fo.getFileSystem();
322                     if (hookedFileSystems.contains(fs)) {
323                         continue;
324                     }
325                     hookedFileSystems.add(fs);
326                     FileStatusListener fsl = FileUtil.weakFileStatusListener(this, fs);
327                     fs.addFileStatusListener(fsl);
328                     fileSystemListeners.put(fs, fsl);
329                 } catch (FileStateInvalidException e) {
330                     ErrorManager err = ErrorManager.getDefault();
331                     err.annotate(e, "Can not get " + fo + " filesystem, ignoring..."); // NO18N
332
err.notify(ErrorManager.INFORMATIONAL, e);
333                 }
334             }
335         }
336     }
337
338     private static final class ConfFilesChildren extends Children.Keys {
339         
340         private final static String JavaDoc[] wellKnownFiles = {
341             "web.xml",
342             "webservices.xml",
343             "struts-config.xml",
344             "faces-config.xml",
345             "portlet.xml",
346              // Creator-specific JSF config files
347
"navigator.xml",
348             "managed-beans.xml"
349         }; //NOI18N
350

351         private final ProjectWebModule pwm;
352         private final HashSet JavaDoc keys;
353         private final java.util.Comparator JavaDoc comparator = new NodeComparator();
354         
355         private final FileChangeListener webInfListener = new FileChangeAdapter() {
356             public void fileDataCreated(FileEvent fe) {
357                 if (isWellKnownFile(fe.getFile().getNameExt()))
358                     addKey(fe.getFile());
359             }
360
361             public void fileRenamed(FileRenameEvent fe) {
362                 // if the old file name was in keys, the new file name
363
// is now there (since it's the same FileObject)
364
if (keys.contains(fe.getFile())) {
365                     // so we need to remove it if it's not well-known
366
if (!isWellKnownFile(fe.getFile().getNameExt()))
367                         removeKey(fe.getFile());
368                     else
369                         // this causes resorting of the keys
370
doSetKeys();
371                 } else {
372                     // the key is not contained, so add it if it's well-known
373
if (isWellKnownFile(fe.getFile().getNameExt()))
374                         addKey(fe.getFile());
375                 }
376             }
377             
378             public void fileDeleted(FileEvent fe) {
379                 if (isWellKnownFile(fe.getFile().getNameExt())) {
380                     removeKey(fe.getFile());
381                 }
382             }
383         };
384         
385         private final FileChangeListener anyFileListener = new FileChangeAdapter() {
386             public void fileDataCreated(FileEvent fe) {
387                 addKey(fe.getFile());
388             }
389
390             public void fileFolderCreated(FileEvent fe) {
391                 addKey(fe.getFile());
392             }
393
394             public void fileRenamed(FileRenameEvent fe) {
395                 addKey(fe.getFile());
396             }
397
398             public void fileDeleted(FileEvent fe) {
399                 removeKey(fe.getFile());
400             }
401         };
402         
403         private final ConfigurationFilesListener serverSpecificFilesListener = new ConfigurationFilesListener() {
404             public void fileCreated(FileObject fo) {
405                 addKey(fo);
406             }
407             
408             public void fileDeleted(FileObject fo) {
409                 removeKey(fo);
410             }
411         };
412         
413         private ConfFilesChildren(ProjectWebModule pwm) {
414             this.pwm = pwm;
415             keys = new HashSet JavaDoc();
416         }
417         
418         public static Children forProject(Project project) {
419             ProjectWebModule pwm = (ProjectWebModule)project.getLookup().lookup(ProjectWebModule.class);
420             return new ConfFilesChildren(pwm);
421         }
422                 
423         protected void addNotify() {
424             createKeys();
425             doSetKeys();
426         }
427         
428         protected void removeNotify() {
429             removeListeners();
430         }
431         
432         public Node[] createNodes(Object JavaDoc key) {
433             Node n = null;
434             
435             if (keys.contains(key)) {
436                 FileObject fo = (FileObject)key;
437                 try {
438                     DataObject dataObject = DataObject.find(fo);
439                     n = dataObject.getNodeDelegate().cloneNode();
440                 }
441                 catch (DataObjectNotFoundException dnfe) {}
442             }
443                                     
444             return (n == null) ? new Node[0] : new Node[] { n };
445         }
446         
447         public synchronized void refreshNodes() {
448             addNotify();
449         }
450         
451         private synchronized void addKey(FileObject key) {
452             if (VisibilityQuery.getDefault().isVisible(key)) {
453                 //System.out.println("Adding " + key.getPath());
454
keys.add(key);
455                 doSetKeys();
456             }
457         }
458         
459         private synchronized void removeKey(FileObject key) {
460             //System.out.println("Removing " + key.getPath());
461
keys.remove(key);
462             doSetKeys();
463         }
464         
465         private synchronized void createKeys() {
466             keys.clear();
467             
468             addWellKnownFiles();
469             addConfDirectoryFiles();
470             addServerSpecificFiles();
471             addFrameworkFiles();
472         }
473         
474         private void doSetKeys() {
475             Object JavaDoc[] result = keys.toArray();
476             java.util.Arrays.sort(result, comparator);
477             //for (int i = 0; i < result.length; i++)
478
// System.out.println(result[i]);
479
setKeys(result);
480         }
481                 
482         private void addWellKnownFiles() {
483             FileObject webInf = pwm.getWebInf(true);
484             if (webInf == null)
485                 return;
486             
487             for (int i = 0; i < wellKnownFiles.length; i++) {
488                 FileObject fo = webInf.getFileObject(wellKnownFiles[i]);
489                 if (fo != null)
490                     keys.add(fo);
491             }
492             
493             webInf.addFileChangeListener(webInfListener);
494         }
495         
496         private void addConfDirectoryFiles() {
497             FileObject conf = pwm.getConfDir();
498             if (conf == null)
499                 return;
500             
501             FileObject[] children = conf.getChildren();
502             for (int i = 0; i < children.length; i++) {
503                 if (VisibilityQuery.getDefault().isVisible(children[i]))
504                     keys.add(children[i]);
505             }
506             
507             conf.addFileChangeListener(anyFileListener);
508         }
509         
510         private void addServerSpecificFiles() {
511             FileObject[] files = pwm.getConfigurationFiles();
512             
513             for (int i = 0; i < files.length; i++) {
514                 keys.add(files[i]);
515             }
516             
517             pwm.addConfigurationFilesListener(serverSpecificFilesListener);
518         }
519         
520         private void addFrameworkFiles(){
521             List JavaDoc providers = WebFrameworkSupport.getFrameworkProviders();
522             for (int i = 0; i < providers.size(); i++){
523                 WebFrameworkProvider provider = (WebFrameworkProvider)providers.get(i);
524                 FileObject wmBase = pwm.getDocumentBase();
525                 File JavaDoc files[] = null;
526                 if (wmBase != null) {
527                     files = provider.getConfigurationFiles(WebModule.getWebModule(wmBase));
528                 }
529                 if (files != null){
530                     for (int j = 0; j < files.length; j++){
531                         FileObject fo = FileUtil.toFileObject(files[j]);
532                         if (fo != null){
533                             keys.add(fo);
534                             // XXX - do we need listeners on these files?
535
//fo.addFileChangeListener(anyFileListener);
536
}
537                     }
538                 }
539             }
540         }
541         
542         private void removeListeners() {
543             pwm.removeConfigurationFilesListener(serverSpecificFilesListener);
544             
545             FileObject webInf = pwm.getWebInf(true);
546             if (webInf != null)
547                 pwm.getWebInf().removeFileChangeListener(webInfListener);
548             
549             FileObject conf = pwm.getConfDir();
550             if (conf != null)
551                 conf.removeFileChangeListener(anyFileListener);
552         }
553         
554         private boolean isWellKnownFile(String JavaDoc name) {
555             for (int i = 0; i < wellKnownFiles.length; i++)
556                 if (name.equals(wellKnownFiles[i]))
557                     return true;
558             
559             return false;
560         }
561                         
562         private static final class NodeComparator implements java.util.Comparator JavaDoc {
563             public int compare(Object JavaDoc o1, Object JavaDoc o2) {
564                 FileObject fo1 = (FileObject)o1;
565                 FileObject fo2 = (FileObject)o2;
566                 
567                 int result = compareType(fo1, fo2);
568                 if (result == 0)
569                     result = compareNames(fo1, fo2);
570                 if (result == 0)
571                     return fo1.getPath().compareTo(fo2.getPath());
572                 
573                 return result;
574             }
575             
576             private int compareType(FileObject fo1, FileObject fo2) {
577                 int folder1 = fo1.isFolder() ? 0 : 1;
578                 int folder2 = fo2.isFolder() ? 0 : 1;
579                 
580                 return folder1 - folder2;
581             }
582             
583             private int compareNames(FileObject do1, FileObject do2) {
584                 return do1.getNameExt().compareTo(do2.getNameExt());
585             }
586             
587             public boolean equals(Object JavaDoc o) {
588                 return (o instanceof NodeComparator);
589             }
590         }
591     }
592     
593     private static class ConfFilesRefreshAction extends CookieAction {
594         
595         protected Class JavaDoc[] cookieClasses() {
596             return new Class JavaDoc[] { RefreshCookie.class };
597         }
598         
599         protected boolean enable(Node[] activatedNodes) {
600             return true;
601         }
602         
603         protected int mode() {
604             return CookieAction.MODE_EXACTLY_ONE;
605         }
606         
607         protected boolean asynchronous() {
608             return false;
609         }
610         
611         public String JavaDoc getName() {
612             return NbBundle.getMessage(ConfFilesNodeFactory.class, "LBL_Refresh"); //NOI18N
613
}
614         
615         public HelpCtx getHelpCtx() {
616             return HelpCtx.DEFAULT_HELP;
617         }
618         
619         public void performAction(Node[] selectedNodes) {
620             for (int i = 0; i < selectedNodes.length; i++) {
621                 RefreshCookie cookie = (RefreshCookie)selectedNodes[i].getCookie(RefreshCookie.class);
622                 cookie.refresh();
623             }
624         }
625         
626         private interface RefreshCookie extends Node.Cookie {
627             public void refresh();
628         }
629     }
630
631 }
632
Popular Tags