KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > project > ant > FileChangeSupport


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-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.project.ant;
21
22 import java.io.File JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.WeakHashMap JavaDoc;
25 import org.openide.filesystems.FileObject;
26 import java.lang.ref.WeakReference JavaDoc;
27 import java.util.HashMap JavaDoc;
28
29 import org.openide.filesystems.FileChangeListener;
30 import org.openide.filesystems.FileAttributeEvent;
31 import org.openide.filesystems.FileEvent;
32 import org.openide.filesystems.FileRenameEvent;
33 import org.openide.filesystems.FileUtil;
34 import org.openide.util.Utilities;
35
36 // XXX current implementation is not efficient for listening to a large # of files
37

38 /**
39  * Utility class to notify clients of changes in the existence or timestamp
40  * of a named file or directory.
41  * Unlike the Filesystems API, permits you to listen to a file which does not
42  * yet exist, or continue listening to it after it is deleted and recreated, etc.
43  * @author Jesse Glick
44  * @see "Blockers: #44213, #44628, #42147, etc."
45  * @see "#33162: hierarchical listeners"
46  */

47 public final class FileChangeSupport {
48     
49     public static FileChangeSupport DEFAULT = new FileChangeSupport();
50     
51     private FileChangeSupport() {}
52     
53     private final Map JavaDoc<FileChangeSupportListener,Map JavaDoc<File JavaDoc,Holder>> holders = new WeakHashMap JavaDoc<FileChangeSupportListener,Map JavaDoc<File JavaDoc,Holder>>();
54     
55     /**
56      * Add a listener to changes in a given path.
57      * Can only add a given listener x path pair once.
58      * However a listener can listen to any number of paths.
59      * Note that listeners are always held weakly - if the listener is collected,
60      * it is quietly removed.
61      */

62     public void addListener(FileChangeSupportListener listener, File JavaDoc path) {
63         assert path.equals(FileUtil.normalizeFile(path)) : "Need to normalize " + path + " before passing to FCS!";
64         Map JavaDoc<File JavaDoc,Holder> f2H = holders.get(listener);
65         if (f2H == null) {
66             f2H = new HashMap JavaDoc<File JavaDoc,Holder>();
67             holders.put(listener, f2H);
68         }
69         if (f2H.containsKey(path)) {
70             throw new IllegalArgumentException JavaDoc("Already listening to " + path); // NOI18N
71
}
72         f2H.put(path, new Holder(listener, path));
73     }
74     
75     /**
76      * Remove a listener to changes in a given path.
77      */

78     public void removeListener(FileChangeSupportListener listener, File JavaDoc path) {
79         assert path.equals(FileUtil.normalizeFile(path)) : "Need to normalize " + path + " before passing to FCS!";
80         Map JavaDoc<File JavaDoc,Holder> f2H = holders.get(listener);
81         if (f2H == null) {
82             throw new IllegalArgumentException JavaDoc("Was not listening to " + path); // NOI18N
83
}
84         if (!f2H.containsKey(path)) {
85             throw new IllegalArgumentException JavaDoc(listener + " was not listening to " + path + "; only to " + f2H.keySet()); // NOI18N
86
}
87         f2H.remove(path);
88     }
89     
90     private static final class Holder extends WeakReference JavaDoc<FileChangeSupportListener> implements FileChangeListener, Runnable JavaDoc {
91         
92         private final File JavaDoc path;
93         private FileObject current;
94         private File JavaDoc currentF;
95         
96         public Holder(FileChangeSupportListener listener, File JavaDoc path) {
97             super(listener, Utilities.activeReferenceQueue());
98             assert path != null;
99             this.path = path;
100             locateCurrent();
101         }
102         
103         private void locateCurrent() {
104             FileObject oldCurrent = current;
105             currentF = path;
106             while (true) {
107                 try {
108                     current = FileUtil.toFileObject(currentF);
109                 } catch (IllegalArgumentException JavaDoc x) {
110                     // #73526: was originally normalized, but now is not. E.g. file changed case.
111
currentF = FileUtil.normalizeFile(currentF);
112                     current = FileUtil.toFileObject(currentF);
113                 }
114                 if (current != null) {
115                     break;
116                 }
117                 currentF = currentF.getParentFile();
118                 if (currentF == null) {
119                     // #47320: can happen on Windows in case the drive does not exist.
120
// (Inside constructor for Holder.) In that case skip it.
121
return;
122                 }
123             }
124             // XXX what happens with UNC paths?
125
assert current != null;
126             if (current != oldCurrent) {
127                 if (oldCurrent != null) {
128                     oldCurrent.removeFileChangeListener(this);
129                 }
130                 current.addFileChangeListener(this);
131                 current.getChildren();//to get events about children
132
}
133         }
134
135         private void someChange(FileObject modified) {
136             FileChangeSupportListener listener;
137             FileObject oldCurrent, nueCurrent;
138             File JavaDoc oldCurrentF, nueCurrentF;
139             synchronized (this) {
140                 if (current == null) {
141                     return;
142                 }
143                 listener = get();
144                 if (listener == null) {
145                     return;
146                 }
147                 oldCurrent = current;
148                 oldCurrentF = currentF;
149                 locateCurrent();
150                 nueCurrent = current;
151                 nueCurrentF = currentF;
152             }
153             if (modified != null && modified == nueCurrent) {
154                 FileChangeSupportEvent event = new FileChangeSupportEvent(DEFAULT, FileChangeSupportEvent.EVENT_MODIFIED, path);
155                 listener.fileModified(event);
156             } else {
157                 boolean oldWasCorrect = path.equals(oldCurrentF);
158                 boolean nueIsCorrect = path.equals(nueCurrentF);
159                 if (oldWasCorrect && !nueIsCorrect) {
160                     FileChangeSupportEvent event = new FileChangeSupportEvent(DEFAULT, FileChangeSupportEvent.EVENT_DELETED, path);
161                     listener.fileDeleted(event);
162                 } else if (nueIsCorrect && !oldWasCorrect) {
163                     FileChangeSupportEvent event = new FileChangeSupportEvent(DEFAULT, FileChangeSupportEvent.EVENT_CREATED, path);
164                     listener.fileCreated(event);
165                 }
166             }
167         }
168
169         public void fileChanged(FileEvent fe) {
170             someChange(fe.getFile());
171         }
172         
173         public void fileDeleted(FileEvent fe) {
174             someChange(null);
175         }
176
177         public void fileDataCreated(FileEvent fe) {
178             someChange(null);
179         }
180
181         public void fileFolderCreated(FileEvent fe) {
182             someChange(null);
183         }
184
185         public void fileRenamed(FileRenameEvent fe) {
186             someChange(null);
187         }
188         
189         public void fileAttributeChanged(FileAttributeEvent fe) {
190             // ignore
191
}
192         
193         public synchronized void run() {
194             if (current != null) {
195                 current.removeFileChangeListener(this);
196                 current = null;
197             }
198         }
199
200     }
201     
202 }
203
Popular Tags