Lines 79-84
Link Here
|
79 |
import org.openide.filesystems.FileEvent; |
79 |
import org.openide.filesystems.FileEvent; |
80 |
import org.openide.filesystems.FileLock; |
80 |
import org.openide.filesystems.FileLock; |
81 |
import org.openide.filesystems.FileObject; |
81 |
import org.openide.filesystems.FileObject; |
|
|
82 |
import org.openide.filesystems.FileRenameEvent; |
82 |
import org.openide.util.Exceptions; |
83 |
import org.openide.util.Exceptions; |
83 |
|
84 |
|
84 |
/** |
85 |
/** |
Lines 533-538
Link Here
|
533 |
return true; |
534 |
return true; |
534 |
} |
535 |
} |
535 |
|
536 |
|
|
|
537 |
@Override |
538 |
protected final void renameChild(FileLock lock, RemoteFileObjectBase directChild2Rename, String newNameExt) throws |
539 |
ConnectException, IOException, InterruptedException, CancellationException, ExecutionException { |
540 |
String nameExt2Rename = directChild2Rename.getNameExt(); |
541 |
String name2Rename = directChild2Rename.getName(); |
542 |
String ext2Rename = directChild2Rename.getExt(); |
543 |
String path2Rename = directChild2Rename.getPath(); |
544 |
File storageFile = new File(getCache(), RemoteFileSystem.CACHE_FILE_NAME); |
545 |
|
546 |
checkConnection(this, true); |
547 |
|
548 |
Lock writeLock = RemoteFileSystem.getLock(getCache()).writeLock(); |
549 |
if (trace) {trace("waiting for lock");} // NOI18N |
550 |
writeLock.lock(); |
551 |
try { |
552 |
DirectoryStorage storage = getExistingDirectoryStorage(); |
553 |
boolean fromMemOrDiskCache = (storage != DirectoryStorage.EMPTY); |
554 |
if (!getCache().exists()) { |
555 |
getCache().mkdirs(); |
556 |
if (!getCache().exists()) { |
557 |
throw new IOException("Can not create cache directory " + getCache()); // NOI18N |
558 |
} |
559 |
} |
560 |
if (trace) {trace("renaming");} // NOI18N |
561 |
ProcessUtils.ExitStatus ret = ProcessUtils.executeInDir(getPath(), getExecutionEnvironment(), "mv", nameExt2Rename, newNameExt);// NOI18N |
562 |
if (!ret.isOK()) { |
563 |
throw new IOException(ret.error); |
564 |
} |
565 |
|
566 |
if (trace) {trace("synchronizing");} // NOI18N |
567 |
Exception problem = null; |
568 |
Map<String, DirEntry> newEntries = Collections.emptyMap(); |
569 |
try { |
570 |
newEntries = readEntries(storage, true, newNameExt); |
571 |
} catch (FileNotFoundException ex) { |
572 |
throw ex; |
573 |
} catch (IOException ex) { |
574 |
problem = ex; |
575 |
} catch (ExecutionException ex) { |
576 |
problem = ex; |
577 |
} |
578 |
if (problem != null) { |
579 |
if (!ConnectionManager.getInstance().isConnectedTo(getExecutionEnvironment())) { |
580 |
// connection was broken while we read directory content - add notification |
581 |
getFileSystem().getRemoteFileSupport().addPendingFile(this); |
582 |
throw new ConnectException(problem.getMessage()); |
583 |
} else { |
584 |
boolean fileNotFoundException = isFileNotFoundException(problem); |
585 |
if (fileNotFoundException) { |
586 |
synchronized (refLock) { |
587 |
storageRef = new SoftReference<DirectoryStorage>(DirectoryStorage.EMPTY); |
588 |
} |
589 |
} |
590 |
if (!fileNotFoundException) { |
591 |
if (problem instanceof IOException) { |
592 |
throw (IOException) problem; |
593 |
} else if (problem instanceof ExecutionException) { |
594 |
throw (ExecutionException) problem; |
595 |
} else { |
596 |
throw new IllegalStateException("Unexpected exception class: " + problem.getClass().getName(), problem); //NOI18N |
597 |
} |
598 |
} |
599 |
} |
600 |
} |
601 |
getFileSystem().incrementDirSyncCount(); |
602 |
Map<String, List<DirEntry>> dupLowerNames = new HashMap<String, List<DirEntry>>(); |
603 |
boolean hasDups = false; |
604 |
boolean changed = true; |
605 |
Set<DirEntry> keepCacheNames = new HashSet<DirEntry>(); |
606 |
List<DirEntry> entriesToFireChanged = new ArrayList<DirEntry>(); |
607 |
List<DirEntry> entriesToFireCreated = new ArrayList<DirEntry>(); |
608 |
List<FileObject> filesToFireDeleted = new ArrayList<FileObject>(); |
609 |
for (DirEntry newEntry : newEntries.values()) { |
610 |
if (newEntry.isValid()) { |
611 |
String cacheName; |
612 |
DirEntry oldEntry = storage.getValidEntry(newEntry.getName()); |
613 |
if (oldEntry == null || !oldEntry.isValid()) { |
614 |
changed = true; |
615 |
cacheName = RemoteFileSystemUtils.escapeFileName(newEntry.getName()); |
616 |
if (newEntry.getName().equals(newNameExt)) { |
617 |
DirEntry renamedEntry = storage.getValidEntry(nameExt2Rename); |
618 |
// NPE check? |
619 |
cacheName = renamedEntry.getCache(); |
620 |
} else if (fromMemOrDiskCache) { |
621 |
entriesToFireCreated.add(newEntry); |
622 |
} |
623 |
} else { |
624 |
if (oldEntry.isSameType(newEntry)) { |
625 |
cacheName = oldEntry.getCache(); |
626 |
keepCacheNames.add(newEntry); |
627 |
boolean fire = false; |
628 |
if (!newEntry.isSameLastModified(oldEntry)) { |
629 |
if (newEntry.isPlainFile()) { |
630 |
changed = fire = true; |
631 |
File entryCache = new File(getCache(), oldEntry.getCache()); |
632 |
if (entryCache.exists()) { |
633 |
if (trace) { |
634 |
trace("removing cache for updated file {0}", entryCache.getAbsolutePath()); |
635 |
} // NOI18N |
636 |
entryCache.delete(); // TODO: We must just mark it as invalid instead of physically deleting cache file... |
637 |
} |
638 |
} |
639 |
} else if (!equals(newEntry.getLinkTarget(), oldEntry.getLinkTarget())) { |
640 |
changed = fire = true; // TODO: we forgot old link path, probably should be passed to change event |
641 |
getFileSystem().getFactory().setLink(this, getPath() + '/' + newEntry.getName(), newEntry.getLinkTarget()); |
642 |
} else if (!newEntry.getAccessAsString().equals(oldEntry.getAccessAsString())) { |
643 |
changed = fire = true; |
644 |
} else if (!newEntry.isSameUser(oldEntry)) { |
645 |
changed = fire = true; |
646 |
} else if (!newEntry.isSameGroup(oldEntry)) { |
647 |
changed = fire = true; |
648 |
} else if (newEntry.getSize() != oldEntry.getSize()) { |
649 |
changed = fire = true;// TODO: shouldn't it be the same as time stamp change? |
650 |
} |
651 |
if (fire) { |
652 |
entriesToFireChanged.add(newEntry); |
653 |
} |
654 |
} else { |
655 |
changed = true; |
656 |
FileObject removedFO = invalidate(oldEntry); |
657 |
// remove old |
658 |
if (removedFO != null) { |
659 |
filesToFireDeleted.add(removedFO); |
660 |
} |
661 |
// add new |
662 |
entriesToFireCreated.add(newEntry); |
663 |
cacheName = RemoteFileSystemUtils.escapeFileName(newEntry.getName()); |
664 |
} |
665 |
} |
666 |
newEntry.setCache(cacheName); |
667 |
if (!RemoteFileSystemUtils.isSystemCaseSensitive()) { |
668 |
String lowerCacheName = newEntry.getCache().toLowerCase(); |
669 |
List<DirEntry> dupEntries = dupLowerNames.get(lowerCacheName); |
670 |
if (dupEntries == null) { |
671 |
dupEntries = new ArrayList<DirEntry>(); |
672 |
dupLowerNames.put(lowerCacheName, dupEntries); |
673 |
} else { |
674 |
hasDups = true; |
675 |
} |
676 |
dupEntries.add(newEntry); |
677 |
} |
678 |
} else { |
679 |
changed = true; |
680 |
} |
681 |
} |
682 |
if (changed) { |
683 |
// Check for removal |
684 |
for (DirEntry oldEntry : storage.listValid()) { |
685 |
if (!oldEntry.getName().equals(nameExt2Rename)) { |
686 |
DirEntry newEntry = newEntries.get(oldEntry.getName()); |
687 |
if (newEntry == null || !newEntry.isValid()) { |
688 |
FileObject removedFO = invalidate(oldEntry); |
689 |
if (removedFO != null) { |
690 |
filesToFireDeleted.add(removedFO); |
691 |
} |
692 |
} |
693 |
} |
694 |
} |
695 |
if (hasDups) { |
696 |
for (Map.Entry<String, List<DirEntry>> mapEntry : |
697 |
new ArrayList<Map.Entry<String, List<DirEntry>>>(dupLowerNames.entrySet())) { |
698 |
|
699 |
List<DirEntry> dupEntries = mapEntry.getValue(); |
700 |
if (dupEntries.size() > 1) { |
701 |
for (int i = 0; i < dupEntries.size(); i++) { |
702 |
DirEntry entry = dupEntries.get(i); |
703 |
if (keepCacheNames.contains(entry)) { |
704 |
continue; // keep the one that already exists |
705 |
} |
706 |
// all duplicates will have postfix |
707 |
for (int j = 0; j < Integer.MAX_VALUE; j++) { |
708 |
String cacheName = mapEntry.getKey() + '_' + j; |
709 |
String lowerCacheName = cacheName.toLowerCase(); |
710 |
if (!dupLowerNames.containsKey(lowerCacheName)) { |
711 |
if (trace) { |
712 |
trace("resolving cache names conflict in {0}: {1} -> {2}", // NOI18N |
713 |
getCache().getAbsolutePath(), entry.getCache(), cacheName); |
714 |
} |
715 |
entry.setCache(cacheName); |
716 |
dupLowerNames.put(lowerCacheName, Collections.singletonList(entry)); |
717 |
break; |
718 |
} |
719 |
} |
720 |
} |
721 |
} |
722 |
} |
723 |
} |
724 |
storage = new DirectoryStorage(storageFile, newEntries.values()); |
725 |
storage.store(); |
726 |
} else { |
727 |
storage.touch(); |
728 |
} |
729 |
// always put new content in cache |
730 |
// do it before firing events, to give liseners real content |
731 |
synchronized (refLock) { |
732 |
storageRef = new SoftReference<DirectoryStorage>(storage); |
733 |
} |
734 |
// fire all event under lock |
735 |
if (changed) { |
736 |
for (FileObject deleted : filesToFireDeleted) { |
737 |
fireFileDeletedEvent(getListeners(), new FileEvent(this, deleted)); |
738 |
} |
739 |
for (DirEntry entry : entriesToFireCreated) { |
740 |
RemoteFileObjectBase fo = createFileObject(entry); |
741 |
fireRemoteFileObjectCreated(fo); |
742 |
} |
743 |
for (DirEntry entry : entriesToFireChanged) { |
744 |
RemoteFileObjectBase fo = getFileSystem().getFactory().getCachedFileObject(getPath() + '/' + entry.getName()); |
745 |
if (fo != null) { |
746 |
fireFileChangedEvent(getListeners(), new FileEvent(fo)); |
747 |
} |
748 |
} |
749 |
// rename itself |
750 |
String newPath = getPath() + '/' + newNameExt; |
751 |
getFileSystem().getFactory().rename(path2Rename, newPath, directChild2Rename); |
752 |
// fire rename |
753 |
fireFileRenamedEvent(directChild2Rename.getListeners(), new FileRenameEvent(directChild2Rename, directChild2Rename, name2Rename, ext2Rename)); |
754 |
fireFileRenamedEvent(this.getListeners(), new FileRenameEvent(this, directChild2Rename, name2Rename, ext2Rename)); |
755 |
//fireFileChangedEvent(getListeners(), new FileEvent(this)); |
756 |
} |
757 |
} finally { |
758 |
writeLock.unlock(); |
759 |
} |
760 |
} |
761 |
|
536 |
private DirectoryStorage getDirectoryStorageImpl(boolean forceRefresh, String expectedName, String childName) throws |
762 |
private DirectoryStorage getDirectoryStorageImpl(boolean forceRefresh, String expectedName, String childName) throws |
537 |
ConnectException, IOException, InterruptedException, CancellationException, ExecutionException { |
763 |
ConnectException, IOException, InterruptedException, CancellationException, ExecutionException { |
538 |
|
764 |
|