KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > versioning > system > cvss > FilesystemHandler


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.versioning.system.cvss;
21
22 import org.netbeans.modules.versioning.spi.VCSInterceptor;
23 import org.netbeans.modules.versioning.util.Utils;
24 import org.netbeans.lib.cvsclient.admin.StandardAdminHandler;
25 import org.netbeans.lib.cvsclient.admin.Entry;
26 import org.netbeans.lib.cvsclient.admin.AdminHandler;
27 import org.openide.ErrorManager;
28
29 import java.io.File JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.util.*;
32
33 /**
34  * Handles events fired from the filesystem such as file/folder create/delete/move.
35  *
36  * @author Maros Sandor
37  */

38 class FilesystemHandler extends VCSInterceptor {
39         
40     private final FileStatusCache cache;
41     private static Thread JavaDoc ignoredThread;
42
43     public FilesystemHandler(CvsVersioningSystem cvs) {
44         cache = cvs.getStatusCache();
45     }
46
47     /**
48      * We save all CVS metadata to be able to commit files that were in that directory.
49      *
50      * @param file File, we are only interested in files inside CVS directory
51      */

52     public boolean beforeDelete(File JavaDoc file) {
53         if (ignoringEvents()) return false;
54         return org.netbeans.modules.versioning.system.cvss.util.Utils.isPartOfCVSMetadata(file) || file.isDirectory() && hasMetadata(file);
55     }
56
57     public void doDelete(File JavaDoc file) throws IOException JavaDoc {
58         if (file.isDirectory() && hasMetadata(file)) {
59             new File JavaDoc(file, "CVS/.nb-removed").createNewFile();
60             cache.refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN, true);
61             return;
62         }
63         if (!org.netbeans.modules.versioning.system.cvss.util.Utils.isPartOfCVSMetadata(file)) {
64             if (!file.delete()) {
65                 throw new IOException JavaDoc("Failed to delete file: " + file.getAbsolutePath());
66             }
67         }
68     }
69
70     public void afterDelete(final File JavaDoc file) {
71         if (ignoringEvents()) return;
72         Utils.post(new Runnable JavaDoc() {
73             public void run() {
74                 fileDeletedImpl(file);
75             }
76         });
77     }
78     
79     /**
80      * We handle directory renames that are managed by CVS.
81      */

82     public boolean beforeMove(File JavaDoc from, File JavaDoc to) {
83         File JavaDoc destDir = to.getParentFile();
84         if (from != null && destDir != null && from.isDirectory()) {
85             FileInformation info = cache.getStatus(from);
86             return (info.getStatus() & FileInformation.STATUS_MANAGED) != 0;
87         }
88         return false;
89     }
90     
91     /**
92      * We only handle directories, file renames are examined ex post. Both directories share the same parent.
93      *
94      * @param from source directory to be renamed
95      * @param to new directory to be created
96      */

97     public void doMove(File JavaDoc from, File JavaDoc to) throws IOException JavaDoc {
98         List<File JavaDoc> affectedFiles = new ArrayList<File JavaDoc>();
99         moveRecursively(affectedFiles, from, to);
100         cvsRemoveRecursively(from);
101         refresh(affectedFiles);
102     }
103
104     private void moveRecursively(List<File JavaDoc> affectedFiles, File JavaDoc from, File JavaDoc to) throws IOException JavaDoc {
105         File JavaDoc [] files = from.listFiles();
106         if (files != null) {
107             for (File JavaDoc file : files) {
108                 String JavaDoc fileName = file.getName();
109                 if (file.isDirectory()) {
110                     if (fileName.equals("CVS")) {
111                         new File JavaDoc(file, ".nb-removed").createNewFile();
112                         continue;
113                     }
114                     File JavaDoc toFile = new File JavaDoc(to, fileName);
115                     moveRecursively(affectedFiles, file, toFile);
116                     affectedFiles.add(file);
117                     affectedFiles.add(toFile);
118                 } else {
119                     to.mkdirs();
120                     File JavaDoc toFile = new File JavaDoc(to, fileName);
121                     file.renameTo(toFile);
122                     affectedFiles.add(file);
123                     affectedFiles.add(toFile);
124                 }
125             }
126         }
127     }
128
129     private void cvsRemoveRecursively(File JavaDoc dir) {
130         StandardAdminHandler sah = new StandardAdminHandler();
131         Entry [] entries = null;
132         try {
133             entries = sah.getEntriesAsArray(dir);
134         } catch (IOException JavaDoc e) {
135             // the Entry is not available, continue with no Entry
136
}
137         
138         if (entries != null) {
139             for (Entry entry : entries) {
140                 if (entry != null && !entry.isDirectory() && !entry.isUserFileToBeRemoved()) {
141                     File JavaDoc file = new File JavaDoc(dir, entry.getName());
142                     cvsRemoveLocally(sah, file, entry);
143                 }
144             }
145         }
146         
147         File JavaDoc [] files = dir.listFiles();
148         for (File JavaDoc file : files) {
149             if (file.isDirectory()) cvsRemoveRecursively(file);
150         }
151     }
152
153     public void afterMove(final File JavaDoc from, final File JavaDoc to) {
154         if (ignoringEvents()) return;
155         Utils.post(new Runnable JavaDoc() {
156             public void run() {
157                 fileDeletedImpl(from);
158                 fileCreatedImpl(to);
159             }
160         });
161     }
162     
163     public boolean beforeCreate(File JavaDoc file, boolean isDirectory) {
164         if (ignoringEvents()) return false;
165         if (file.getName().equals(CvsVersioningSystem.FILENAME_CVS)) {
166             if (file.isDirectory()) {
167                 File JavaDoc f = new File JavaDoc(file, CvsLiteAdminHandler.INVALID_METADATA_MARKER);
168                 try {
169                     f.createNewFile();
170                 } catch (IOException JavaDoc e) {
171                     ErrorManager.getDefault().log(ErrorManager.ERROR, "Unable to create marker: " + f.getAbsolutePath()); // NOI18N
172
}
173             }
174             return true;
175         } else {
176             return false;
177         }
178     }
179
180     public void doCreate(File JavaDoc file, boolean isDirectory) throws IOException JavaDoc {
181         file.mkdir();
182         File JavaDoc f = new File JavaDoc(file, CvsLiteAdminHandler.INVALID_METADATA_MARKER);
183         try {
184             f.createNewFile();
185         } catch (IOException JavaDoc e) {
186             ErrorManager.getDefault().log(ErrorManager.ERROR, "Unable to create marker: " + f.getAbsolutePath()); // NOI18N
187
}
188     }
189
190     public void afterCreate(final File JavaDoc file) {
191         if (ignoringEvents()) return;
192         Utils.post(new Runnable JavaDoc() {
193             public void run() {
194                 fileCreatedImpl(file);
195             }
196         });
197     }
198
199     public void afterChange(final File JavaDoc file) {
200         if (ignoringEvents()) return;
201         Utils.post(new Runnable JavaDoc() {
202             public void run() {
203                 cache.refreshCached(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
204                 if (file.getName().equals(CvsVersioningSystem.FILENAME_CVSIGNORE)) cache.directoryContentChanged(file.getParentFile());
205             }
206         });
207     }
208
209     // private methods ---------------------------
210

211     private void fileCreatedImpl(File JavaDoc file) {
212         if (file == null) return;
213         int status = cache.refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN).getStatus();
214
215         if ((status & FileInformation.STATUS_MANAGED) == 0) return;
216
217         if (status == FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY) {
218             StandardAdminHandler sah = new StandardAdminHandler();
219             Entry entry = null;
220             try {
221                 entry = sah.getEntry(file);
222             } catch (IOException JavaDoc e) {
223                 // the Entry is not available, continue with no Entry
224
}
225             if (entry != null && !entry.isDirectory() && entry.isUserFileToBeRemoved()) {
226                 cvsUndoRemoveLocally(sah, file, entry);
227             }
228             cache.refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
229         }
230         if (file.getName().equals(CvsVersioningSystem.FILENAME_CVSIGNORE)) cache.directoryContentChanged(file.getParentFile());
231         if (file.isDirectory()) cache.directoryContentChanged(file);
232     }
233
234     /**
235      * If a regular file is deleted then update its Entries as if it has been removed.
236      *
237      * @param file deleted file
238      */

239     private void fileDeletedImpl(File JavaDoc file) {
240         if (file == null) return;
241         
242         StandardAdminHandler sah = new StandardAdminHandler();
243         Entry entry = null;
244         try {
245             entry = sah.getEntry(file);
246         } catch (IOException JavaDoc e) {
247             // the Entry is not available, continue with no Entry
248
}
249         if (entry != null && !entry.isDirectory() && !entry.isUserFileToBeRemoved()) {
250             cvsRemoveLocally(sah, file, entry);
251         }
252
253         cache.refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
254         if (file.getName().equals(CvsVersioningSystem.FILENAME_CVSIGNORE)) cache.directoryContentChanged(file.getParentFile());
255     }
256     
257     /**
258      * Emulates the 'cvs remove' command by modifying Entries. We do this to avoid contacting the
259      * server.
260      *
261      * @param ah
262      * @param file
263      * @param entry
264      */

265     private void cvsRemoveLocally(AdminHandler ah, File JavaDoc file, Entry entry) {
266         try {
267             if (entry.isNewUserFile()) {
268                 ah.removeEntry(file);
269             } else {
270                 entry.setRevision("-" + entry.getRevision()); // NOI18N
271
entry.setConflict(Entry.DUMMY_TIMESTAMP);
272                 ah.setEntry(file, entry);
273             }
274         } catch (IOException JavaDoc e) {
275             // failed to set/remove entry, there is no way to recover from this
276
}
277     }
278
279     private void cvsUndoRemoveLocally(AdminHandler ah, File JavaDoc file, Entry entry) {
280         entry.setRevision(entry.getRevision().substring(1));
281         entry.setConflict(Entry.getLastModifiedDateFormatter().format(new Date(System.currentTimeMillis() - 1000)));
282         try {
283             ah.setEntry(file, entry);
284         } catch (IOException JavaDoc e) {
285             // failed to set entry, the file will be probably resurrected during update
286
}
287     }
288     
289     private void refresh(List<File JavaDoc> files) {
290         for (File JavaDoc file : files) {
291             cache.refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN, true);
292         }
293     }
294
295     private boolean hasMetadata(File JavaDoc file) {
296         return new File JavaDoc(file, "CVS/Repository").canRead();
297     }
298     
299     /**
300      * Ignores (internal) events from current thread. E.g.:
301      * <pre>
302      * try {
303      * FilesystemHandler.ignoreEvents(true);
304      * fo.createData(file.getName());
305      * } finally {
306      * FilesystemHandler.ignoreEvents(false);
307      * }
308      * </pre>
309      *
310      * <p>It assumes that filesystem operations fire
311      * synchronous events.
312      * @see {http://javacvs.netbeans.org/nonav/issues/show_bug.cgi?id=68961}
313      */

314     static void ignoreEvents(boolean ignore) {
315         if (ignore) {
316             ignoredThread = Thread.currentThread();
317         } else {
318             ignoredThread = null;
319         }
320     }
321
322     /**
323      * @return true if filesystem events are ignored in current thread, false otherwise
324      */

325     private static boolean ignoringEvents() {
326         return ignoredThread == Thread.currentThread();
327     }
328 }
329
Popular Tags