1 19 package org.netbeans.modules.versioning; 20 21 import org.openide.filesystems.*; 22 import org.netbeans.modules.masterfs.providers.ProvidedExtensions; 23 import org.netbeans.modules.versioning.spi.VCSInterceptor; 24 import org.netbeans.modules.versioning.spi.VersioningSystem; 25 import java.io.File ; 26 import java.io.IOException ; 27 import java.util.*; 28 29 34 class FilesystemInterceptor extends ProvidedExtensions implements FileChangeListener { 35 36 private VersioningManager master; 37 38 40 45 void init(VersioningManager versioningManager) { 46 assert master == null; 47 master = versioningManager; 48 Set filesystems = getRootFilesystems(); 49 for (Iterator i = filesystems.iterator(); i.hasNext();) { 50 FileSystem fileSystem = (FileSystem) i.next(); 51 fileSystem.addFileChangeListener(this); 52 } 53 } 54 55 58 void shutdown() { 59 Set filesystems = getRootFilesystems(); 60 for (Iterator i = filesystems.iterator(); i.hasNext();) { 61 FileSystem fileSystem = (FileSystem) i.next(); 62 fileSystem.removeFileChangeListener(this); 63 } 64 } 65 66 71 private Set<FileSystem> getRootFilesystems() { 72 Set<FileSystem> filesystems = new HashSet<FileSystem>(); 73 File [] roots = File.listRoots(); 74 for (int i = 0; i < roots.length; i++) { 75 File root = roots[i]; 76 FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(root)); 77 if (fo == null) continue; 78 try { 79 filesystems.add(fo.getFileSystem()); 80 } catch (FileStateInvalidException e) { 81 } 83 } 84 return filesystems; 85 } 86 87 91 public void fileChanged(FileEvent fe) { 92 removeFromDeletedFiles(fe.getFile()); 93 getInterceptor(fe).afterChange(); 94 } 95 96 public void beforeChange(FileObject fo) { 97 getInterceptor(FileUtil.toFile(fo), fo.isFolder()).beforeChange(); 98 } 99 100 104 private void removeFromDeletedFiles(File file) { 105 synchronized(deletedFiles) { 106 deletedFiles.remove(file); 107 } 108 } 109 110 private void removeFromDeletedFiles(FileObject fo) { 111 synchronized(deletedFiles) { 112 if (deletedFiles.size() > 0) { 113 deletedFiles.remove(FileUtil.toFile(fo)); 114 } 115 } 116 } 117 118 public DeleteHandler getDeleteHandler(File file) { 119 removeFromDeletedFiles(file); 120 DelegatingInterceptor dic = getInterceptor(file, false); 121 return dic.beforeDelete() ? dic : null; 122 } 123 124 public void fileDeleted(FileEvent fe) { 125 removeFromDeletedFiles(fe.getFile()); 126 getInterceptor(fe).afterDelete(); 127 } 128 129 133 public void beforeCreate(FileObject parent, String name, boolean isFolder) { 134 File file = FileUtil.toFile(parent); 135 if (file == null) return; 136 file = new File (file, name); 137 DelegatingInterceptor dic = getInterceptor(file, isFolder); 138 dic.beforeCreate(); 139 } 140 141 public void fileFolderCreated(FileEvent fe) { 142 removeFromDeletedFiles(fe.getFile()); 143 getInterceptor(fe).afterCreate(); 144 } 145 146 public void fileDataCreated(FileEvent fe) { 147 removeFromDeletedFiles(fe.getFile()); 148 getInterceptor(fe).afterCreate(); 149 } 150 151 155 public IOHandler getMoveHandler(File from, File to) { 156 DelegatingInterceptor dic = getInterceptor(from, to); 157 return dic.beforeMove() ? dic : null; 158 } 159 160 public IOHandler getRenameHandler(File from, String newName) { 161 File to = new File (from.getParentFile(), newName); 162 return getMoveHandler(from, to); 163 } 164 165 public void fileRenamed(FileRenameEvent fe) { 166 removeFromDeletedFiles(fe.getFile()); 167 getInterceptor(fe).afterMove(); 168 } 169 170 public void fileAttributeChanged(FileAttributeEvent fe) { 171 } 173 174 private DelegatingInterceptor getInterceptor(FileEvent fe) { 175 FileObject fo = fe.getFile(); 176 if (fo == null) return nullDelegatingInterceptor; 177 File file = FileUtil.toFile(fo); 178 if (file == null) return nullDelegatingInterceptor; 179 180 VersioningSystem lh = master.getLocalHistory(file); 181 VersioningSystem vs = master.getOwner(file); 182 183 VCSInterceptor vsInterceptor = vs != null ? vs.getVCSInterceptor() : null; 184 VCSInterceptor lhInterceptor = lh != null ? lh.getVCSInterceptor() : null; 185 186 if (vsInterceptor == null && lhInterceptor == null) return nullDelegatingInterceptor; 187 188 if (fe instanceof FileRenameEvent) { 189 FileRenameEvent fre = (FileRenameEvent) fe; 190 File parent = file.getParentFile(); 191 if (parent != null) { 192 String name = fre.getName(); 193 String ext = fre.getExt(); 194 if (ext != null && ext.length() > 0) { name += "." + ext; } 197 File from = new File (parent, name); 198 return new DelegatingInterceptor(vsInterceptor, lhInterceptor, from, file, false); 199 } 200 return nullDelegatingInterceptor; 201 } else { 202 return new DelegatingInterceptor(vsInterceptor, lhInterceptor, file, null, false); 203 } 204 } 205 206 private DelegatingInterceptor getInterceptor(File file, boolean isDirectory) { 207 if (file == null) return nullDelegatingInterceptor; 208 209 VersioningSystem vs = master.getOwner(file); 210 VCSInterceptor vsInterceptor = vs != null ? vs.getVCSInterceptor() : nullVCSInterceptor; 211 212 VersioningSystem lhvs = master.getLocalHistory(file); 213 VCSInterceptor localHistoryInterceptor = lhvs != null ? lhvs.getVCSInterceptor() : nullVCSInterceptor; 214 215 return new DelegatingInterceptor(vsInterceptor, localHistoryInterceptor, file, null, isDirectory); 216 } 217 218 private DelegatingInterceptor getInterceptor(File from, File to) { 219 if (from == null || to == null) return nullDelegatingInterceptor; 220 221 VersioningSystem vs = master.getOwner(from); 222 VCSInterceptor vsInterceptor = vs != null ? vs.getVCSInterceptor() : nullVCSInterceptor; 223 224 VersioningSystem lhvs = master.getLocalHistory(from); 225 VCSInterceptor localHistoryInterceptor = lhvs != null ? lhvs.getVCSInterceptor() : nullVCSInterceptor; 226 227 return new DelegatingInterceptor(vsInterceptor, localHistoryInterceptor, from, to, false); 228 } 229 230 private final DelegatingInterceptor nullDelegatingInterceptor = new DelegatingInterceptor() { 231 public boolean beforeDelete() { return false; } 232 public void doDelete() throws IOException { } 233 public void afterDelete() { } 234 public boolean beforeMove() { return false; } 235 public void doMove() throws IOException { } 236 public boolean beforeCreate() { return false; } 237 public void doCreate() throws IOException { } 238 public void afterCreate() { } 239 public void beforeChange() { } 240 public void afterChange() { } 241 public void afterMove() { } 242 public void handle() throws IOException { } 243 public boolean delete(File file) { throw new UnsupportedOperationException (); } 244 }; 245 246 private final VCSInterceptor nullVCSInterceptor = new VCSInterceptor() {}; 247 248 251 private final Set<File > deletedFiles = new HashSet<File >(5); 252 253 private class DelegatingInterceptor implements IOHandler, DeleteHandler { 254 255 final VCSInterceptor interceptor; 256 final VCSInterceptor lhInterceptor; 257 final File file; 258 final File to; 259 private final boolean isDirectory; 260 261 private DelegatingInterceptor() { 262 this(null, null, null, null, false); 263 } 264 265 public DelegatingInterceptor(VCSInterceptor interceptor, VCSInterceptor lhInterceptor, File file, File to, boolean isDirectory) { 266 this.interceptor = interceptor != null ? interceptor : nullVCSInterceptor; 267 this.lhInterceptor = lhInterceptor != null ? lhInterceptor : nullVCSInterceptor; 268 this.file = file; 269 this.to = to; 270 this.isDirectory = isDirectory; 271 } 272 273 public boolean beforeDelete() { 274 lhInterceptor.beforeDelete(file); 275 return interceptor.beforeDelete(file); 276 } 277 278 public void doDelete() throws IOException { 279 lhInterceptor.doDelete(file); 280 interceptor.doDelete(file); 281 } 282 283 public void afterDelete() { 284 lhInterceptor.afterDelete(file); 285 interceptor.afterDelete(file); 286 } 287 288 public boolean beforeMove() { 289 lhInterceptor.beforeMove(file, to); 290 return interceptor.beforeMove(file, to); 291 } 292 293 public void doMove() throws IOException { 294 lhInterceptor.doMove(file, to); 295 interceptor.doMove(file, to); 296 } 297 298 public void afterMove() { 299 lhInterceptor.afterMove(file, to); 300 interceptor.afterMove(file, to); 301 } 302 303 public boolean beforeCreate() { 304 lhInterceptor.beforeCreate(file, isDirectory); 305 return interceptor.beforeCreate(file, isDirectory); 306 } 307 308 public void doCreate() throws IOException { 309 lhInterceptor.doCreate(file, isDirectory); 310 interceptor.doCreate(file, isDirectory); 311 } 312 313 public void afterCreate() { 314 lhInterceptor.afterCreate(file); 315 interceptor.afterCreate(file); 316 } 317 318 public void afterChange() { 319 lhInterceptor.afterChange(file); 320 interceptor.afterChange(file); 321 } 322 323 public void beforeChange() { 324 lhInterceptor.beforeChange(file); 325 interceptor.beforeChange(file); 326 } 327 328 333 public void handle() throws IOException { 334 lhInterceptor.doMove(file, to); 335 interceptor.doMove(file, to); 336 } 337 338 353 public boolean delete(File file) { 354 File [] children = file.listFiles(); 355 if (children != null) { 356 synchronized(deletedFiles) { 357 for (File child : children) { 358 if (!deletedFiles.contains(child)) return false; 359 } 360 } 361 } 362 try { 363 lhInterceptor.doDelete(file); 364 interceptor.doDelete(file); 365 synchronized(deletedFiles) { 366 if (file.isDirectory()) { 367 for (Iterator<File > i = deletedFiles.iterator(); i.hasNext(); ) { 369 File fakedFile = i.next(); 370 if (file.equals(fakedFile.getParentFile())) { 371 i.remove(); 372 } 373 } 374 } 375 if (file.exists()) { 376 deletedFiles.add(file); 377 } else { 378 deletedFiles.remove(file); 379 } 380 } 381 return true; 382 } catch (IOException e) { 383 return false; 385 } 386 } 387 388 } 392 } 393 | Popular Tags |