1 19 20 package org.netbeans.modules.masterfs.filebasedfs.fileobjects; 21 22 import org.netbeans.modules.masterfs.filebasedfs.FileBasedFileSystem; 23 import org.netbeans.modules.masterfs.filebasedfs.Statistics; 24 import org.netbeans.modules.masterfs.filebasedfs.children.ChildrenCache; 25 import org.netbeans.modules.masterfs.filebasedfs.children.ChildrenSupport; 26 import org.netbeans.modules.masterfs.filebasedfs.naming.FileName; 27 import org.netbeans.modules.masterfs.filebasedfs.naming.FileNaming; 28 import org.netbeans.modules.masterfs.filebasedfs.utils.FSException; 29 import org.netbeans.modules.masterfs.filebasedfs.utils.FileInfo; 30 import org.openide.filesystems.FileLock; 31 import org.openide.filesystems.FileObject; 32 import org.openide.util.Mutex; 33 34 import java.io.*; 35 import java.util.*; 36 import java.util.logging.Level ; 37 import java.util.logging.LogRecord ; 38 import java.util.logging.Logger ; 39 import org.netbeans.modules.masterfs.filebasedfs.naming.NamingFactory; 40 import org.netbeans.modules.masterfs.providers.ProvidedExtensions; 41 42 45 public final class FolderObj extends BaseFileObj { 46 static final long serialVersionUID = -1022430210876356809L; 47 private static final Mutex.Privileged mp = new Mutex.Privileged(); 48 private static final Mutex mutex = new Mutex(FolderObj.mp); 49 50 private FolderChildrenCache folderChildren; 51 boolean valid = true; 52 private int bitmask = 0; 53 static final String LIGHTWEIGHT_LOCK_SET = "LIGHTWEIGHT_LOCK_SET"; private static int LIGHTWEIGHT_LOCK = 1 << 0; 56 57 60 public FolderObj(final File file, final FileNaming name) { 61 super(file, name); 62 } 64 65 public final boolean isFolder() { 66 return true; 67 } 68 69 70 public final FileObject getFileObject(final String name, final String ext) { 71 FileObject retVal = null; 72 final File f = getFileName().getFile(); 73 final ChildrenCache childrenCache = getChildrenCache(); 74 FileNaming child; 75 File file; 76 final Mutex.Privileged mutexPrivileged = childrenCache.getMutexPrivileged(); 77 78 mutexPrivileged.enterReadAccess(); 79 try { 80 file = BaseFileObj.getFile(f, name, ext); 81 final String nameExt = BaseFileObj.getNameExt(file); 82 child = childrenCache.getChild(nameExt, false); 83 } finally { 84 mutexPrivileged.exitReadAccess(); 85 } 86 87 final FileBasedFileSystem lfs = getLocalFileSystem(); 88 assert lfs != null; 89 90 if (child != null) { 91 retVal = lfs.findFileObject(file); 92 } 93 94 return retVal; 95 } 96 97 public final FileObject[] getChildren() { 98 final List results = new ArrayList(); 99 100 final ChildrenCache childrenCache = getChildrenCache(); 101 final Mutex.Privileged mutexPrivileged = childrenCache.getMutexPrivileged(); 102 103 mutexPrivileged.enterWriteAccess(); 104 105 Set fileNames; 106 try { 107 fileNames = new HashSet(childrenCache.getChildren(false)); 108 } finally { 109 mutexPrivileged.exitWriteAccess(); 110 } 111 112 final FileBasedFileSystem lfs = getLocalFileSystem(); 113 for (Iterator iterator = fileNames.iterator(); iterator.hasNext();) { 114 final FileNaming fileName = (FileNaming) iterator.next(); 115 FileInfo fInfo = new FileInfo (fileName.getFile()); 116 fInfo.setFileNaming(fileName); 117 fInfo.setValueForFlag(FileInfo.FLAG_exists, true); 118 119 final FileObject fo = lfs.findFileObject(fInfo); 120 if (fo != null) { 121 results.add(fo); 122 } 123 } 124 return (FileObject[]) results.toArray(new FileObject[0]); 125 } 126 127 public final FileObject createFolder(final String name) throws java.io.IOException { 128 if (name.indexOf('\\') != -1 || name.indexOf('/') != -1) { throw new IllegalArgumentException (name); 130 } 131 132 FolderObj retVal = null; 133 File folder2Create; 134 final ChildrenCache childrenCache = getChildrenCache(); 135 136 final Mutex.Privileged mutexPrivileged = childrenCache.getMutexPrivileged(); 137 138 mutexPrivileged.enterWriteAccess(); 139 140 try { 141 folder2Create = BaseFileObj.getFile(getFileName().getFile(), name, null); 142 createFolder(folder2Create, name); 143 144 final FileNaming childName = this.getChildrenCache().getChild(folder2Create.getName(), true); 145 if (childName != null) { 146 NamingFactory.checkCaseSensitivity(childName, folder2Create); 147 } 148 } finally { 149 mutexPrivileged.exitWriteAccess(); 150 } 151 152 final FileBasedFileSystem localFileBasedFileSystem = getLocalFileSystem(); 153 if (localFileBasedFileSystem != null) { 154 retVal = (FolderObj) localFileBasedFileSystem.findFileObject(folder2Create); 155 } 156 if (retVal != null) { 157 retVal.fireFileFolderCreatedEvent(false); 158 } else { 159 FSException.io("EXC_CannotCreateFolder", folder2Create.getName(), getPath()); } 161 162 return retVal; 163 } 164 165 private void createFolder(final File folder2Create, final String name) throws IOException { 166 boolean isSupported = new FileInfo(folder2Create).isSupportedFile(); 167 if (!isSupported) { 168 FSException.io("EXC_CannotCreateFolder", folder2Create.getName(), getPath()); } else if (folder2Create.exists()) { 170 FSException.io("EXC_CannotCreateExistingFolder", folder2Create.getName(), getPath()); } else if (!folder2Create.mkdirs()) { 172 FSException.io("EXC_CannotCreateFolder", folder2Create.getName(), getPath()); } 174 LogRecord r = new LogRecord (Level.FINEST, "FolderCreated: "+ folder2Create.getAbsolutePath()); 175 r.setParameters(new Object [] {folder2Create}); 176 Logger.getLogger("org.netbeans.modules.masterfs.filebasedfs.fileobjects.FolderObj").log(r); 177 } 178 179 public final FileObject createData(final String name, final String ext) throws java.io.IOException { 180 if (name.indexOf('\\') != -1 || name.indexOf('/') != -1) { throw new IllegalArgumentException (name); 182 } 183 184 final ChildrenCache childrenCache = getChildrenCache(); 185 final Mutex.Privileged mutexPrivileged = childrenCache.getMutexPrivileged(); 186 187 mutexPrivileged.enterWriteAccess(); 188 189 FileObj retVal; 190 File file2Create; 191 try { 192 file2Create = BaseFileObj.getFile(getFileName().getFile(), name, ext); 193 createData(file2Create); 194 195 final FileNaming childName = getChildrenCache().getChild(file2Create.getName(), true); 196 if (childName != null) { 197 NamingFactory.checkCaseSensitivity(childName, file2Create); 198 } 199 200 } finally { 201 mutexPrivileged.exitWriteAccess(); 202 } 203 204 final FileBasedFileSystem localFileBasedFileSystem = getLocalFileSystem(); 205 retVal = null; 206 if (localFileBasedFileSystem != null) { 207 retVal = (FileObj) localFileBasedFileSystem.findFileObject(file2Create); 208 } 209 210 if (retVal != null) { 211 retVal.fireFileDataCreatedEvent(false); 212 } else { 213 FSException.io("EXC_CannotCreateData", file2Create.getName(), getPath()); } 215 216 return retVal; 217 } 218 219 private void createData(final File file2Create) throws IOException { 220 boolean isSupported = new FileInfo(file2Create).isSupportedFile(); 221 if (!isSupported) { 222 FSException.io("EXC_CannotCreateData", file2Create.getName(), getPath()); } else if (file2Create.exists()) { 224 FSException.io("EXC_CannotCreateExistingData", file2Create.getName(), getPath()); } else if (!file2Create.createNewFile()) { 226 FSException.io("EXC_CannotCreateData", file2Create.getName(), getPath()); } 228 LogRecord r = new LogRecord (Level.FINEST, "DataCreated: "+ file2Create.getAbsolutePath()); 229 r.setParameters(new Object [] {file2Create}); 230 Logger.getLogger("org.netbeans.modules.masterfs.filebasedfs.fileobjects.FolderObj").log(r); 231 } 232 233 public void delete(final FileLock lock, ProvidedExtensions.DeleteHandler deleteHandler) throws IOException { 234 final LinkedList all = new LinkedList(); 235 236 final File file = getFileName().getFile(); 237 if (!deleteFile(file, all, getLocalFileSystem().getFactory(), deleteHandler)) { 238 FileObject parent = getExistingParent(); 239 String parentPath = (parent != null) ? parent.getPath() : file.getParentFile().getAbsolutePath(); 240 FSException.io("EXC_CannotDelete", file.getName(), parentPath); } 242 243 BaseFileObj.attribs.deleteAttributes(file.getAbsolutePath().replace('\\', '/')); setValid(false); 245 for (int i = 0; i < all.size(); i++) { 246 final BaseFileObj toDel = (BaseFileObj) all.get(i); 247 final FolderObj existingParent = toDel.getExistingParent(); 248 assert existingParent == null || toDel.getParent().equals(existingParent); 249 final ChildrenCache childrenCache = (existingParent != null) ? existingParent.getChildrenCache() : null; 250 if (childrenCache != null) { 251 final Mutex.Privileged mutexPrivileged = (childrenCache != null) ? childrenCache.getMutexPrivileged() : null; 252 if (mutexPrivileged != null) mutexPrivileged.enterWriteAccess(); 253 try { 254 if (deleteHandler != null) { 255 childrenCache.removeChild(toDel.getFileName()); 256 } else { 257 childrenCache.getChild(BaseFileObj.getNameExt(file), true); 258 } 259 260 261 } finally { 262 if (mutexPrivileged != null) mutexPrivileged.exitWriteAccess(); 263 } 264 } 265 toDel.setValid(false); 266 toDel.fireFileDeletedEvent(false); 267 } 268 } 269 270 public void refresh(final boolean expected, boolean fire) { 271 Statistics.StopWatch stopWatch = Statistics.getStopWatch(Statistics.REFRESH_FOLDER); 272 stopWatch.start(); 273 274 if (isValid()) { 275 final ChildrenCache cache = getChildrenCache(); 276 final Mutex.Privileged mutexPrivileged = cache.getMutexPrivileged(); 277 278 Set oldChildren = null; 279 Map refreshResult = null; 280 mutexPrivileged.enterWriteAccess(); 281 try { 282 oldChildren = new HashSet(cache.getCachedChildren()); 283 refreshResult = cache.refresh(); 284 } finally { 285 mutexPrivileged.exitWriteAccess(); 286 } 287 288 oldChildren.removeAll(refreshResult.keySet()); 289 for (Iterator iterator = oldChildren.iterator(); iterator.hasNext();) { 290 final FileName child = (FileName) iterator.next(); 291 final BaseFileObj childObj = getLocalFileSystem().getFactory().get(child.getFile()); 292 if (childObj != null && childObj.isData()) { 293 ((FileObj)childObj).refresh(expected); 294 } 295 } 296 297 final FileBasedFileSystem localFileSystem = this.getLocalFileSystem(); 298 final FileObjectFactory factory = localFileSystem.getFactory(); 299 300 final Iterator iterator = refreshResult.entrySet().iterator(); 301 while (iterator.hasNext()) { 302 final Map.Entry entry = (Map.Entry) iterator.next(); 303 final FileName child = (FileName) entry.getKey(); 304 final Integer operationId = (Integer ) entry.getValue(); 305 306 BaseFileObj newChild = (operationId == ChildrenCache.ADDED_CHILD) ? (BaseFileObj) 307 factory.findFileObject(new FileInfo(child.getFile())): factory.get(child.getFile()); 308 newChild = (BaseFileObj) ((newChild != null) ? newChild : getFileObject(child.getName())); 309 if (operationId == ChildrenCache.ADDED_CHILD && newChild != null) { 310 311 if (newChild.isFolder()) { 312 if (fire) { 313 newChild.fireFileFolderCreatedEvent(expected); 314 } 315 } else { 316 if (fire) { 317 newChild.fireFileDataCreatedEvent(expected); 318 } 319 } 320 321 } else if (operationId == ChildrenCache.REMOVED_CHILD) { 322 if (newChild != null) { 323 if (newChild.isValid()) { 324 newChild.setValid(false); 325 if (fire) { 326 newChild.fireFileDeletedEvent(expected); 327 } 328 } 329 } else { 330 final File f = child.getFile(); 333 if (!(new FileInfo(f).isConvertibleToFileObject())) { 334 final BaseFileObj fakeInvalid; 335 if (child.isFile()) { 336 fakeInvalid = new FileObj(f, child); 337 } else { 338 fakeInvalid = new FolderObj(f, child); 339 } 340 341 fakeInvalid.setValid(false); 342 if (fire) { 343 fakeInvalid.fireFileDeletedEvent(expected); 344 } 345 } 346 } 347 348 } else { 349 assert !(new FileInfo(child.getFile()).isConvertibleToFileObject()); 350 } 351 352 } 353 boolean validityFlag = getFileName().getFile().exists(); 354 if (!validityFlag) { 355 setValid(false); 357 if (fire) { 358 fireFileDeletedEvent(expected); 359 } 360 } 361 } 362 stopWatch.stop(); 363 } 364 365 public final void refresh(final boolean expected) { 366 refresh(expected, true); 367 } 368 369 private boolean deleteFile(final File file, final LinkedList all, final FileObjectFactory factory, ProvidedExtensions.DeleteHandler deleteHandler) throws IOException { 371 final boolean ret = (deleteHandler != null) ? deleteHandler.delete(file) : file.delete(); 372 373 if (ret) { 374 final FileObject aliveFo = factory.get(file); 375 if (aliveFo != null) { 376 all.addFirst(aliveFo); 377 } 378 return true; 379 } 380 381 if (!file.exists()) { 382 return false; 383 } 384 385 if (file.isDirectory()) { 386 final File[] arr = file.listFiles(); 388 for (int i = 0; i < arr.length; i++) { 389 final File f2Delete = arr[i]; 390 if (!deleteFile(f2Delete, all, factory, deleteHandler)) { 391 return false; 392 } 393 } 394 } 395 396 399 400 final boolean retVal = (deleteHandler != null) ? deleteHandler.delete(file) : file.delete(); 401 if (retVal) { 402 final FileObject aliveFo = factory.get(file); 403 if (aliveFo != null) { 404 all.addFirst(aliveFo); 405 } 406 } 407 408 409 return true; 410 } 411 412 protected void setValid(final boolean valid) { 413 if (valid) { 414 assert isValid() : this.toString(); 416 } else { 417 this.valid = false; 418 } 419 420 } 421 422 public boolean isValid() { 423 return valid; 424 } 425 426 public final InputStream getInputStream() throws FileNotFoundException { 427 throw new FileNotFoundException(getPath()); 428 } 429 430 public final OutputStream getOutputStream(final FileLock lock) throws IOException { 431 throw new IOException(getPath()); 432 } 433 434 public final java.util.Date lastModified() { 435 final File f = getFileName().getFile(); 436 return new Date(f.lastModified()); 437 } 438 439 public final FileLock lock() throws IOException { 440 return new FileLock(); 441 } 442 443 final boolean checkLock(final FileLock lock) throws IOException { 444 return true; 445 } 446 447 public final synchronized ChildrenCache getChildrenCache() { 448 if (folderChildren == null) { 450 folderChildren = new FolderChildrenCache(); 451 } 452 return folderChildren; 453 } 454 455 public Object getAttribute(final String attrName) { 456 if (attrName.equals(LIGHTWEIGHT_LOCK_SET)) { 457 bitmask |= LIGHTWEIGHT_LOCK; 458 return new FileLock() { 459 public void releaseLock() { 460 super.releaseLock(); 461 bitmask &= ~LIGHTWEIGHT_LOCK; 462 } 463 464 }; 465 } 466 return super.getAttribute(attrName); 467 } 468 469 boolean isLightWeightLockRequired() { 470 return (bitmask & LIGHTWEIGHT_LOCK) == LIGHTWEIGHT_LOCK; 471 } 472 473 public final class FolderChildrenCache implements ChildrenCache { 474 public final ChildrenSupport ch = new ChildrenSupport(); 475 476 477 public final Set getChildren(final boolean rescan) { 478 return ch.getChildren(getFileName(), rescan); 479 } 480 481 public final FileNaming getChild(final String childName, final boolean rescan) { 482 return ch.getChild(childName, getFileName(), rescan); 483 } 484 485 public final Map refresh() { 486 return ch.refresh(getFileName()); 487 } 488 489 public final Mutex.Privileged getMutexPrivileged() { 490 return FolderObj.mp; 491 } 492 493 public final String toString() { 494 return getFileName().toString(); 495 } 496 497 public void removeChild(FileNaming childName) { 498 ch.removeChild(getFileName(), childName); 499 } 500 501 public Set getCachedChildren() { 502 return ch.getCachedChildren(); 503 } 504 } 505 506 } 507 | Popular Tags |