KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > ruby > modules > project > rake > 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.ruby.modules.project.rake;
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.Reference JavaDoc;
27 import java.lang.ref.WeakReference JavaDoc;
28 import java.util.HashMap JavaDoc;
29
30 import org.openide.filesystems.FileChangeListener;
31 import org.openide.filesystems.FileAttributeEvent;
32 import org.openide.filesystems.FileEvent;
33 import org.openide.filesystems.FileRenameEvent;
34 import org.openide.filesystems.FileUtil;
35 import org.openide.util.Utilities;
36
37 // XXX current implementation is not efficient for listening to a large # of files
38

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

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

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

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