1 19 20 package org.netbeans.modules.masterfs.filebasedfs.fileobjects; 21 22 import java.util.Iterator ; 23 import org.netbeans.modules.masterfs.filebasedfs.FileBasedFileSystem; 24 import org.netbeans.modules.masterfs.filebasedfs.Statistics; 25 import org.netbeans.modules.masterfs.filebasedfs.children.ChildrenCache; 26 import org.netbeans.modules.masterfs.filebasedfs.naming.FileNaming; 27 import org.netbeans.modules.masterfs.filebasedfs.naming.NamingFactory; 28 import org.netbeans.modules.masterfs.filebasedfs.utils.FSException; 29 import org.netbeans.modules.masterfs.filebasedfs.utils.FileInfo; 30 import org.netbeans.modules.masterfs.providers.Attributes; 31 import org.openide.filesystems.*; 32 import org.openide.filesystems.FileSystem; 33 import org.openide.util.Mutex; 34 35 import javax.swing.event.EventListenerList ; 36 import java.io.*; 37 import java.util.ArrayList ; 38 import java.util.Arrays ; 39 import java.util.Date ; 40 import java.util.Enumeration ; 41 import java.util.List ; 42 import org.netbeans.modules.masterfs.providers.ProvidedExtensions; 43 import org.openide.util.Enumerations; 44 45 50 52 public abstract class BaseFileObj extends FileObject { 53 private static final char EXTENSION_SEPARATOR = '.'; 55 private static final char UNC_PREFIX = '\\'; private static final String PATH_SEPARATOR = "/"; private static final char EXT_SEP = '.'; 59 static final long serialVersionUID = -1244650210876356809L; 61 static final Attributes attribs; 62 static { 63 final BridgeForAttributes attrBridge = new BridgeForAttributes(); 64 attribs = new Attributes(attrBridge, attrBridge, attrBridge); 65 } 66 67 68 private EventListenerList eventSupport; 70 private final FileNaming fileName; 71 72 73 protected BaseFileObj(final File file) { 74 this.fileName = NamingFactory.fromFile(file); 75 } 76 77 protected BaseFileObj(final File file, final FileNaming name) { 78 this.fileName = name; 79 } 80 81 public final String toString() { 82 return getFileName().toString(); 83 } 84 85 public final String getNameExt() { 86 final File file = getFileName().getFile(); 87 final String retVal = BaseFileObj.getNameExt(file); 88 return retVal; 89 90 } 91 92 static String getNameExt(final File file) { 93 String retVal = (file.getParentFile() == null) ? file.getAbsolutePath() : file.getName(); 94 if (retVal.endsWith(String.valueOf(UNC_PREFIX)) || retVal.endsWith(PATH_SEPARATOR)) { assert (file.getParentFile() == null) : 96 (file.getAbsolutePath() + " exists: " + file.exists()); final boolean isPermittedToStripSlash = !(file.getParentFile() == null && new FileInfo(file).isUNCFolder()); 98 if (isPermittedToStripSlash) { 99 retVal = retVal.substring(0, retVal.length() - 1); 100 } 101 102 } 103 return retVal; 104 } 105 106 public final boolean isData() { 107 return !isFolder(); 108 } 109 110 public final String getName() { 111 return FileInfo.getName(getNameExt()); 112 } 113 114 public final String getExt() { 115 return FileInfo.getExt(getNameExt()); 116 } 117 118 public final String getPath() { 119 return (isRoot()) ? "" : getFileName().getFile().getAbsolutePath().replace(UNC_PREFIX, '/'); } 121 122 public final FileSystem getFileSystem() throws FileStateInvalidException { 123 return getLocalFileSystem(); 124 } 125 126 public final boolean isRoot() { 127 return false; 128 } 129 130 public void move(FileLock lock, FolderObj target, String name, String ext, ProvidedExtensions.IOHandler moveHandler) throws IOException { 131 moveHandler.handle(); 132 String nameExt = FileInfo.composeName(name,ext); 133 target.getChildrenCache().getChild(nameExt, true); 134 BaseFileObj result = (BaseFileObj)FileBasedFileSystem.getFileObject( 135 new File(target.getFileName().getFile(),nameExt)); 136 assert result != null; 137 result.fireFileDataCreatedEvent(false); 138 fireFileDeletedEvent(false); 139 } 140 141 142 public void rename(final FileLock lock, final String name, final String ext, ProvidedExtensions.IOHandler handler) throws IOException { 143 if (!checkLock(lock)) { 144 FSException.io("EXC_InvalidLock", lock, getPath()); } 146 147 final File file = getFileName().getFile(); 148 final File parent = file.getParentFile(); 149 150 final File file2Rename = BaseFileObj.getFile(parent, name, ext); 151 if (parent == null || !parent.exists()) { 152 FileObject parentFo = getExistingParent(); 153 String parentPath = (parentFo != null) ? parentFo.getPath() : file.getParentFile().getAbsolutePath(); 154 FSException.io("EXC_CannotRename", file.getName(), parentPath, file2Rename.getName()); } 156 157 if (file2Rename.exists() && !file2Rename.equals(file)) { 158 FileObject parentFo = getExistingParent(); 159 String parentPath = (parentFo != null) ? parentFo.getPath() : file.getParentFile().getAbsolutePath(); 160 FSException.io("EXC_CannotRename", file.getName(), parentPath, file2Rename.getName()); } 162 163 final String originalName = getName(); 164 final String originalExt = getExt(); 165 166 FileNaming[] allRenamed = NamingFactory.rename(getFileName(),file2Rename.getName(),handler); 168 if (allRenamed == null) { 169 FileObject parentFo = getExistingParent(); 170 String parentPath = (parentFo != null) ? parentFo.getPath() : file.getParentFile().getAbsolutePath(); 171 FSException.io("EXC_CannotRename", file.getName(), parentPath, file2Rename.getName()); } 173 FileBasedFileSystem fs = getLocalFileSystem(); 174 fs.getFactory().rename(); 175 BaseFileObj.attribs.renameAttributes(file.getAbsolutePath().replace('\\', '/'), file2Rename.getAbsolutePath().replace('\\', '/')); for (int i = 0; i < allRenamed.length; i++) { 177 FolderObj par = (allRenamed[i].getParent() != null) ? 178 (FolderObj)fs.getFactory().get(allRenamed[i].getParent().getFile()) : null; 179 if (par != null) { 180 ChildrenCache childrenCache = par.getChildrenCache(); 181 final Mutex.Privileged mutexPrivileged = (childrenCache != null) ? childrenCache.getMutexPrivileged() : null; 182 if (mutexPrivileged != null) mutexPrivileged.enterWriteAccess(); 183 try { 184 childrenCache.removeChild(allRenamed[i]); 185 childrenCache.getChild(allRenamed[i].getName(), true); 186 } finally { 187 if (mutexPrivileged != null) mutexPrivileged.exitWriteAccess(); 188 } 189 } 190 } 191 WriteLock.relock(file,file2Rename); 192 fireFileRenamedEvent(originalName, originalExt); 193 } 194 195 196 public final void rename(final FileLock lock, final String name, final String ext) throws IOException { 197 rename(lock, name, ext, null); 198 } 199 200 201 public Object getAttribute(final String attrName) { 202 return BaseFileObj.attribs.readAttribute(getFileName().getFile().getAbsolutePath().replace('\\', '/'), attrName); } 204 205 public final void setAttribute(final String attrName, final Object value) throws java.io.IOException { 206 final Object oldValue = BaseFileObj.attribs.readAttribute(getFileName().getFile().getAbsolutePath().replace('\\', '/'), attrName); BaseFileObj.attribs.writeAttribute(getFileName().getFile().getAbsolutePath().replace('\\', '/'), attrName, value); fireFileAttributeChangedEvent(attrName, oldValue, value); 209 } 210 211 public final java.util.Enumeration getAttributes() { 212 return BaseFileObj.attribs.attributes(getFileName().getFile().getAbsolutePath().replace('\\', '/')); } 214 215 public final void addFileChangeListener(final org.openide.filesystems.FileChangeListener fcl) { 216 getEventSupport().add(FileChangeListener.class, fcl); 217 } 218 219 public final void removeFileChangeListener(final org.openide.filesystems.FileChangeListener fcl) { 220 getEventSupport().remove(FileChangeListener.class, fcl); 221 } 222 223 private Enumeration getListeners() { 224 if (eventSupport == null) { 225 return Enumerations.empty(); 226 } 227 return org.openide.util.Enumerations.array(getEventSupport().getListeners(FileChangeListener.class)); 228 } 229 230 231 public final long getSize() { 232 return getFileName().getFile().length(); 233 } 234 235 public final void setImportant(final boolean b) { 236 } 237 238 239 public boolean isReadOnly() { 240 final File f = getFileName().getFile(); 241 242 return !f.canWrite() && f.exists(); 243 } 244 245 public final FileObject getParent() { 246 final FileNaming parent = getFileName().getParent(); 247 FileObject retVal; 248 if ((parent != null)) { 249 final FileBasedFileSystem localFileSystem = getLocalFileSystem(); 250 final File file = parent.getFile(); 251 retVal = localFileSystem.getFactory().get(file); 252 retVal = (retVal == null) ? localFileSystem.findFileObject(file) : retVal; 253 } else { 254 retVal = getLocalFileSystem().getRoot(); 255 } 256 return retVal; 257 } 258 259 static File getFile(final File f, final String name, final String ext) { 260 File retVal; 261 262 final StringBuffer sb = new StringBuffer (); 263 sb.append(name); 264 if (ext != null && ext.length() > 0) { 265 sb.append(BaseFileObj.EXT_SEP); 266 sb.append(ext); 267 } 268 retVal = new File(f, sb.toString()); 269 return retVal; 270 } 271 272 final FileBasedFileSystem getLocalFileSystem() { 273 return FileBasedFileSystem.getInstance(getFileName().getFile()); 274 } 275 276 final void fireFileDataCreatedEvent(final boolean expected) { 277 Statistics.StopWatch stopWatch = Statistics.getStopWatch(Statistics.LISTENERS_CALLS); 278 stopWatch.start(); 279 280 final BaseFileObj parent = getExistingParent(); 281 Enumeration pListeners = (parent != null) ? parent.getListeners() : null; 282 283 assert this.isValid() : this.toString(); 284 fireFileDataCreatedEvent(getListeners(), new FileEvent(this, this, expected)); 285 286 if (parent != null && pListeners != null) { 287 assert parent.isValid() : parent.toString(); 288 parent.fireFileDataCreatedEvent(pListeners, new FileEvent(parent, this, expected)); 289 } 290 stopWatch.stop(); 291 } 292 293 294 final void fireFileFolderCreatedEvent(final boolean expected) { 295 Statistics.StopWatch stopWatch = Statistics.getStopWatch(Statistics.LISTENERS_CALLS); 296 stopWatch.start(); 297 298 299 final BaseFileObj parent = getExistingParent(); 300 Enumeration pListeners = (parent != null) ? parent.getListeners() : null; 301 302 fireFileFolderCreatedEvent(getListeners(), new FileEvent(this, this, expected)); 303 304 if (parent != null && pListeners != null) { 305 parent.fireFileFolderCreatedEvent(pListeners, new FileEvent(parent, this, expected)); 306 } 307 308 stopWatch.stop(); 309 } 310 311 FolderObj getExistingParent() { 312 final File parentFile = (getFileName().getParent() == null) ? null : getFileName().getParent().getFile(); 313 final FolderObj parent = (parentFile == null) ? null : (FolderObj) getLocalFileSystem().getFactory().get(parentFile); 314 return parent; 315 } 316 317 318 public final void fireFileChangedEvent(final boolean expected) { 319 Statistics.StopWatch stopWatch = Statistics.getStopWatch(Statistics.LISTENERS_CALLS); 320 stopWatch.start(); 321 322 FileObject p = getParent(); 323 final BaseFileObj parent = (BaseFileObj)((p instanceof BaseFileObj) ? p : null); Enumeration pListeners = (parent != null) ? parent.getListeners() : null; 325 326 fireFileChangedEvent(getListeners(), new FileEvent(this, this, expected)); 327 328 if (parent != null && pListeners != null) { 329 parent.fireFileChangedEvent(pListeners, new FileEvent(parent, this, expected)); 330 } 331 stopWatch.stop(); 332 } 333 334 335 final void fireFileDeletedEvent(final boolean expected) { 336 Statistics.StopWatch stopWatch = Statistics.getStopWatch(Statistics.LISTENERS_CALLS); 337 stopWatch.start(); 338 FileObject p = getParent(); 339 final BaseFileObj parent = (BaseFileObj)((p instanceof BaseFileObj) ? p : null); Enumeration pListeners = (parent != null) ?parent.getListeners() : null; 341 342 fireFileDeletedEvent(getListeners(), new FileEvent(this, this, expected)); 343 344 if (parent != null && pListeners != null) { 345 parent.fireFileDeletedEvent(pListeners, new FileEvent(parent, this, expected)); 346 } 347 stopWatch.stop(); 348 } 349 350 351 private void fireFileRenamedEvent(final String originalName, final String originalExt) { 352 Statistics.StopWatch stopWatch = Statistics.getStopWatch(Statistics.LISTENERS_CALLS); 353 stopWatch.start(); 354 355 final BaseFileObj parent = getExistingParent(); 356 Enumeration pListeners = (parent != null) ?parent.getListeners() : null; 357 358 fireFileRenamedEvent(getListeners(), new FileRenameEvent(this, originalName, originalExt)); 359 360 if (parent != null && pListeners != null) { 361 parent.fireFileRenamedEvent(pListeners, new FileRenameEvent(parent, this, originalName, originalExt)); 362 } 363 364 stopWatch.stop(); 365 } 366 367 private void fireFileAttributeChangedEvent(final String attrName, final Object oldValue, final Object newValue) { 368 final BaseFileObj parent = getExistingParent(); 369 Enumeration pListeners = (parent != null) ?parent.getListeners() : null; 370 371 fireFileAttributeChangedEvent(getListeners(), new FileAttributeEvent(this, this, attrName, oldValue, newValue)); 372 373 if (parent != null && pListeners != null) { 374 parent.fireFileAttributeChangedEvent(pListeners, new FileAttributeEvent(parent, this, attrName, oldValue, newValue)); 375 } 376 } 377 378 379 public final FileNaming getFileName() { 380 return fileName; 381 } 382 383 public final void delete(final FileLock lock) throws IOException { 384 delete(lock, null); 385 } 386 387 public void delete(final FileLock lock, ProvidedExtensions.DeleteHandler deleteHandler) throws IOException { 388 final File f = getFileName().getFile(); 389 390 final FolderObj existingParent = getExistingParent(); 391 final ChildrenCache childrenCache = (existingParent != null) ? existingParent.getChildrenCache() : null; 392 final Mutex.Privileged mutexPrivileged = (childrenCache != null) ? childrenCache.getMutexPrivileged() : null; 393 394 if (mutexPrivileged != null) mutexPrivileged.enterWriteAccess(); 395 try { 396 if (!checkLock(lock)) { 397 FSException.io("EXC_InvalidLock", lock, getPath()); } 399 400 boolean deleteStatus = (deleteHandler != null) ? deleteHandler.delete(f) : f.delete(); 401 if (!deleteStatus) { 402 FileObject parent = getExistingParent(); 403 String parentPath = (parent != null) ? parent.getPath() : f.getParentFile().getAbsolutePath(); 404 FSException.io("EXC_CannotDelete", f.getName(), parentPath); } 406 BaseFileObj.attribs.deleteAttributes(f.getAbsolutePath().replace('\\', '/')); if (childrenCache != null) { 408 if (deleteHandler != null) { 409 childrenCache.removeChild(getFileName()); 410 } else { 411 childrenCache.getChild(BaseFileObj.getNameExt(f), true); 412 } 413 } 414 } finally { 415 if (mutexPrivileged != null) mutexPrivileged.exitWriteAccess(); 416 setValid(false); 417 } 418 419 fireFileDeletedEvent(false); 420 421 } 422 423 abstract boolean checkLock(FileLock lock) throws IOException; 424 425 public Object writeReplace() { 426 return new ReplaceForSerialization(getFileName().getFile()); 427 } 428 429 abstract protected void setValid(boolean valid); 430 431 abstract public void refresh(final boolean expected, boolean fire); 432 433 434 446 private static final class BridgeForAttributes implements AbstractFileSystem.List, AbstractFileSystem.Change, AbstractFileSystem.Info { 447 public final Date lastModified(final String name) { 448 final File file = new File(name); 449 return new Date (file.lastModified()); 450 } 451 452 public final boolean folder(final String name) { 453 final File file = new File(name); 454 return file.isDirectory(); 455 } 456 457 public final boolean readOnly(final String name) { 458 final File file = new File(name); 459 return !file.canWrite(); 460 461 } 462 463 public final String mimeType(final String name) { 464 return "content/unknown"; } 466 467 public final long size(final String name) { 468 final File file = new File(name); 469 return file.length(); 470 } 471 472 public final InputStream inputStream(final String name) throws FileNotFoundException { 473 final File file = new File(name); 474 return new FileInputStream(file); 475 476 } 477 478 public final OutputStream outputStream(final String name) throws IOException { 479 final File file = new File(name); 480 return new FileOutputStream(file); 481 } 482 483 public final void lock(final String name) throws IOException { 484 } 485 486 public final void unlock(final String name) { 487 } 488 489 public final void markUnimportant(final String name) { 490 } 491 492 public final String [] children(final String f) { 493 final File file = new File(f); 494 return file.list(); 495 } 496 497 public final void createFolder(final String name) throws IOException { 498 final File file = new File(name); 499 if (!file.mkdirs()) { 500 final IOException ioException = new IOException(name); 501 throw ioException; 502 } 503 } 504 505 public final void createData(final String name) throws IOException { 506 final File file = new File(name); 507 if (!file.createNewFile()) { 508 throw new IOException(name); 509 } 510 } 511 512 public final void rename(final String oldName, final String newName) throws IOException { 513 final File file = new File(oldName); 514 final File dest = new File(newName); 515 516 if (!file.renameTo(dest)) { 517 FSException.io("EXC_CannotRename", file.getName(), "", dest.getName()); } 519 } 520 521 public final void delete(final String name) throws IOException { 522 final File file = new File(name); 523 final boolean isDeleted = (file.isFile()) ? file.delete() : deleteFolder(file); 524 if (isDeleted) { 525 FSException.io("EXC_CannotDelete", file.getName(), ""); } 527 } 528 529 private boolean deleteFolder(final File file) throws IOException { 530 final boolean ret = file.delete(); 531 532 if (ret) { 533 return true; 534 } 535 536 if (!file.exists()) { 537 return false; 538 } 539 540 if (file.isDirectory()) { 541 final File[] arr = file.listFiles(); 543 for (int i = 0; i < arr.length; i++) { 544 final File f2Delete = arr[i]; 545 if (!deleteFolder(f2Delete)) { 546 return false; 547 } 548 } 549 } 550 551 return file.delete(); 552 } 553 554 } 555 556 private synchronized EventListenerList getEventSupport() { 557 if (eventSupport == null) { 558 eventSupport = new EventListenerList (); 559 } 560 return eventSupport; 561 } 562 } 563 | Popular Tags |