KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > persistenceapi > 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.j2ee.persistenceapi;
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<File,Holder>>*/ holders = new WeakHashMap JavaDoc();
55     
56     public static FileChangeSupport getDefault() {
57         return DEFAULT;
58     }
59     
60     /**
61      * Add a listener to changes in a given path.
62      * Can only add a given listener x path pair once.
63      * However a listener can listen to any number of paths.
64      * Note that listeners are always held weakly - if the listener is collected,
65      * it is quietly removed.
66      */

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

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