From ee56fc6c403ab40f2617f75855fcbc705e3e2f20 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 6 Mar 2012 12:38:57 +0400 Subject: [PATCH] moved to FileUtil --- .../vfs/newvfs/NewVirtualFileSystem.java | 32 ++++----- .../openapi/vfs/ex/temp/TempFileSystem.java | 7 +- .../vfs/impl/jar/JarFileSystemImpl.java | 12 ++-- .../vfs/impl/local/LocalFileSystemBase.java | 65 +++--------------- .../openapi/vfs/impl/win32/Win32Kernel.java | 22 +++---- .../vfs/newvfs/impl/VirtualDirectoryImpl.java | 6 +- .../newvfs/impl/VirtualFileSystemEntry.java | 2 +- .../vfs/newvfs/persistent/PersistentFS.java | 66 ++++++++++++------- .../vfs/newvfs/persistent/RefreshWorker.java | 25 ++++--- .../intellij/openapi/util/io/FileUtil.java | 57 +++++++++++++++- 10 files changed, 161 insertions(+), 133 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java index f2ba97153912..b7f274080b78 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java @@ -19,11 +19,11 @@ */ package com.intellij.openapi.vfs.newvfs; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileListener; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileSystem; -import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,10 +45,12 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements return path; } + @Override public void refreshWithoutFileWatcher(final boolean asynchronous) { refresh(asynchronous); } + @Override public boolean isReadOnly() { return true; } @@ -70,6 +72,7 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements protected abstract String extractRootPath(@NotNull String path); + @Override public void addVirtualFileListener(@NotNull final VirtualFileListener listener) { synchronized (myListenerWrappers) { VirtualFileListener wrapper = new VirtualFileFilteringListener(listener, this); @@ -78,6 +81,7 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements } } + @Override public void removeVirtualFileListener(@NotNull final VirtualFileListener listener) { synchronized (myListenerWrappers) { final VirtualFileListener wrapper = myListenerWrappers.remove(listener); @@ -89,12 +93,18 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements public abstract int getRank(); + @Override public abstract VirtualFile copyFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent, @NotNull final String copyName) throws IOException; + @Override @NotNull public abstract VirtualFile createChildDirectory(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String dir) throws IOException; + @Override public abstract VirtualFile createChildFile(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String file) throws IOException; + @Override public abstract void deleteFile(final Object requestor, @NotNull final VirtualFile file) throws IOException; + @Override public abstract void moveFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent) throws IOException; + @Override public abstract void renameFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final String newName) throws IOException; public boolean markNewFilesAsDirty() { @@ -105,14 +115,6 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements return file.getName(); } - public static final int BA_EXISTS = 0x01; - public static final int BA_REGULAR = 0x02; - public static final int BA_DIRECTORY = 0x04; - public static final int BA_HIDDEN = 0x08; - - @MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN}) - public @interface FileBooleanAttributes {} - /** * Queries the file about several attributes at once, and returns them ORed together. * This method is typically faster than several methods calls querying corresponding file attributes one by one. @@ -122,10 +124,10 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements * Each attribute is an int constant from this class. * Following attributes are defined: * * Attributes can be bitwise ORed together to query several file attributes at once. * -1 as an argument value will query all attributes. @@ -146,6 +148,6 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements * boolean isDirectory = (attributes & BA_DIRECTORY) != 0; * }} */ - @FileBooleanAttributes - public abstract int getBooleanAttributes(@NotNull final VirtualFile file, @FileBooleanAttributes int flags); + @FileUtil.FileBooleanAttributes + public abstract int getBooleanAttributes(@NotNull final VirtualFile file, @FileUtil.FileBooleanAttributes int flags); } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java index 7f35b77eba8c..c1da943f68a8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java @@ -21,6 +21,7 @@ package com.intellij.openapi.vfs.ex.temp; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.ManagingFS; @@ -369,9 +370,9 @@ public class TempFileSystem extends NewVirtualFileSystem { @Override public int getBooleanAttributes(@NotNull VirtualFile file, int flags) { FSItem item = convert(file); - int isDir = item instanceof FSDir ? BA_DIRECTORY : 0; - int exists = item == null ? 0 : BA_EXISTS; - int regular = isDir == 0 ? BA_REGULAR : 0; + int isDir = item instanceof FSDir ? FileUtil.BA_DIRECTORY : 0; + int exists = item == null ? 0 : FileUtil.BA_EXISTS; + int regular = isDir == 0 ? FileUtil.BA_REGULAR : 0; return isDir | exists | regular; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index 6d1e3a3687a2..c7c451895759 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -368,16 +368,16 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo public int getBooleanAttributes(@NotNull VirtualFile file, int flags) { int exists = 0; JarHandler handler = getHandler(file); - if ((flags & BA_EXISTS) != 0) { - exists = handler.exists(file) ? BA_EXISTS : 0; + if ((flags & FileUtil.BA_EXISTS) != 0) { + exists = handler.exists(file) ? FileUtil.BA_EXISTS : 0; } int isDir = 0; - if ((flags & BA_DIRECTORY) != 0) { - isDir = handler.isDirectory(file) ? BA_DIRECTORY : 0; + if ((flags & FileUtil.BA_DIRECTORY) != 0) { + isDir = handler.isDirectory(file) ? FileUtil.BA_DIRECTORY : 0; } int regular = 0; - if ((flags & BA_REGULAR) != 0) { - regular = isDir == 0 ? BA_REGULAR : 0; + if ((flags & FileUtil.BA_REGULAR) != 0) { + regular = isDir == 0 ? FileUtil.BA_REGULAR : 0; } return exists | isDir | regular; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index 4a43a8c8a897..0b839baafafb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -35,12 +35,10 @@ import com.intellij.util.Processor; import com.intellij.util.ThrowableConsumer; import com.intellij.util.io.SafeFileOutputStream; import com.intellij.util.io.fs.IFile; -import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.*; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -137,44 +135,13 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { return new File(path); } - private static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD; - private static final Object/* java.io.FileSystem */ JAVA_IO_FILESYSTEM; - // copied from FileSystem - - static { - Object fs; - Method getBooleanAttributes; - try { - Class fsClass = Class.forName("java.io.FileSystem"); - Method getFileSystem = fsClass.getMethod("getFileSystem"); - getFileSystem.setAccessible(true); - fs = getFileSystem.invoke(null); - getBooleanAttributes = fsClass.getDeclaredMethod("getBooleanAttributes", File.class); - if (fs == null || getBooleanAttributes == null) { - fs = null; - getBooleanAttributes = null; - } - else { - getBooleanAttributes.setAccessible(true); - } - } - catch (Exception e) { - fs = null; - getBooleanAttributes = null; - } - JAVA_IO_FILESYSTEM = fs; - JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD = getBooleanAttributes; - } - - - @NotNull private static File convertToIOFileAndCheck(@NotNull final VirtualFile file) throws FileNotFoundException { final File ioFile = convertToIOFile(file); - int intFlags = getBooleanAttributes(ioFile); + int intFlags = FileUtil.getBooleanAttributes(ioFile); if (intFlags != -1) { - if ((intFlags & BA_EXISTS) != 0 && (intFlags & BA_REGULAR) == 0) { + if ((intFlags & FileUtil.BA_EXISTS) != 0 && (intFlags & FileUtil.BA_REGULAR) == 0) { throw new FileNotFoundException("Not a file: " + ioFile); } return ioFile; @@ -186,20 +153,6 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { return ioFile; } - // todo[r.sh] use NIO2 API after migration to JDK 7 - // returns -1 if could not get attributes - @MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN}) - private static int getBooleanAttributes(@NotNull File f) { - if (JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD != null) { - try { - Object flags = JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD.invoke(JAVA_IO_FILESYSTEM, f); - return ((Integer)flags).intValue(); - } - catch (Exception ignored) { } - } - return -1; - } - @Override public boolean exists(@NotNull final VirtualFile fileOrDirectory) { String path = fileOrDirectory.getPath(); @@ -246,9 +199,9 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { } private static boolean isSpecialFile(@NotNull File ioFile) { - int flags = getBooleanAttributes(ioFile); + int flags = FileUtil.getBooleanAttributes(ioFile); if (flags != -1) { - return (flags & (BA_REGULAR | BA_DIRECTORY | BA_EXISTS)) == (~BA_REGULAR & ~BA_DIRECTORY & BA_EXISTS); + return (flags & (FileUtil.BA_REGULAR | FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS)) == (~FileUtil.BA_REGULAR & ~FileUtil.BA_DIRECTORY & FileUtil.BA_EXISTS); } return !ioFile.isFile() && !ioFile.isDirectory() && ioFile.exists(); } @@ -774,12 +727,12 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { @Override public int getBooleanAttributes(@NotNull VirtualFile file, int flags) { - int attributes = getBooleanAttributes(convertToIOFile(file)); + int attributes = FileUtil.getBooleanAttributes(convertToIOFile(file)); if (attributes != -1) return attributes & flags; - return ((flags & BA_EXISTS) != 0 && exists(file) ? BA_EXISTS : 0) | - ((flags & BA_DIRECTORY) != 0 && isDirectory(file) ? BA_DIRECTORY : 0) | - ((flags & BA_REGULAR) != 0 && !isSpecialFile(file) ? BA_REGULAR : 0) | - ((flags & BA_HIDDEN) != 0 && convertToIOFile(file).isHidden() ? BA_HIDDEN : 0) + return ((flags & FileUtil.BA_EXISTS) != 0 && exists(file) ? FileUtil.BA_EXISTS : 0) | + ((flags & FileUtil.BA_DIRECTORY) != 0 && isDirectory(file) ? FileUtil.BA_DIRECTORY : 0) | + ((flags & FileUtil.BA_REGULAR) != 0 && !isSpecialFile(file) ? FileUtil.BA_REGULAR : 0) | + ((flags & FileUtil.BA_HIDDEN) != 0 && convertToIOFile(file).isHidden() ? FileUtil.BA_HIDDEN : 0) ; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java index 18450eb9ea6c..501b706420db 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.vfs.impl.win32; -import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -109,21 +109,21 @@ public class Win32Kernel { return info; } - @NewVirtualFileSystem.FileBooleanAttributes - public int getBooleanAttributes(@NotNull String path, @NewVirtualFileSystem.FileBooleanAttributes int flags) { + @FileUtil.FileBooleanAttributes + public int getBooleanAttributes(@NotNull String path, @FileUtil.FileBooleanAttributes int flags) { FileInfo info = doGetInfo(path); int result = 0; - if ((flags & NewVirtualFileSystem.BA_EXISTS) != 0) { - result |= info == null ? 0 : NewVirtualFileSystem.BA_EXISTS; + if ((flags & FileUtil.BA_EXISTS) != 0) { + result |= info == null ? 0 : FileUtil.BA_EXISTS; } - if ((flags & NewVirtualFileSystem.BA_DIRECTORY) != 0) { - result |= info == null || (info.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : NewVirtualFileSystem.BA_DIRECTORY; + if ((flags & FileUtil.BA_DIRECTORY) != 0) { + result |= info == null || (info.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : FileUtil.BA_DIRECTORY; } - if ((flags & NewVirtualFileSystem.BA_REGULAR) != 0) { - result |= info == null || (info.attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0 ? 0 : NewVirtualFileSystem.BA_REGULAR; + if ((flags & FileUtil.BA_REGULAR) != 0) { + result |= info == null || (info.attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0 ? 0 : FileUtil.BA_REGULAR; } - if ((flags & NewVirtualFileSystem.BA_HIDDEN) != 0) { - result |= info == null || (info.attributes & FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : NewVirtualFileSystem.BA_HIDDEN; + if ((flags & FileUtil.BA_HIDDEN) != 0) { + result |= info == null || (info.attributes & FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : FileUtil.BA_HIDDEN; } return result; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 5363593d452a..79f208e07e03 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -321,10 +321,10 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { private VirtualFileSystemEntry createAndFindChildWithEventFire(@NotNull String name) { final NewVirtualFileSystem delegate = getFileSystem(); VirtualFile fake = new FakeVirtualFile(this, name); - int attributes = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY); - if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) { + int attributes = delegate.getBooleanAttributes(fake, FileUtil.BA_EXISTS | FileUtil.BA_DIRECTORY); + if ((attributes & FileUtil.BA_EXISTS) != 0) { final String realName = delegate.getCanonicallyCasedName(fake); - boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0; + boolean isDir = (attributes & FileUtil.BA_DIRECTORY) != 0; VFileCreateEvent event = new VFileCreateEvent(null, this, realName, isDir, true); RefreshQueue.getInstance().processSingleEvent(event); return findChild(realName); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.java index 08cf80c6f47e..0d26031e5b77 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.java @@ -145,7 +145,7 @@ public abstract class VirtualFileSystemEntry extends NewVirtualFile { return pattern.regionMatches(ignoreCase, length, suffix, 0, suffix.length()); } - private Object rawName() { + protected Object rawName() { return myName; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java index 125445349646..79d7c701a32a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java @@ -292,7 +292,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { final int parentId, @NotNull VirtualFile file, @NotNull NewVirtualFileSystem delegate, - @NewVirtualFileSystem.FileBooleanAttributes int attributes) { + @FileUtil.FileBooleanAttributes int attributes) { String name = file.getName(); if (!name.isEmpty() && namesEqual(delegate, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change. @@ -308,11 +308,11 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { FSRecords.setTimestamp(id, delegate.getTimeStamp(file)); - boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0; + boolean isDir = (attributes & FileUtil.BA_DIRECTORY) != 0; FSRecords.setLength(id, isDir ? -1L : delegate.getLength(file)); - boolean isSpecial = (attributes & (NewVirtualFileSystem.BA_REGULAR | NewVirtualFileSystem.BA_DIRECTORY | NewVirtualFileSystem.BA_EXISTS)) == - NewVirtualFileSystem.BA_EXISTS; + boolean isSpecial = (attributes & (FileUtil.BA_REGULAR | FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS)) == + FileUtil.BA_EXISTS; FSRecords.setFlags(id, (isDir ? IS_DIRECTORY_FLAG : 0) | (delegate.isWritable(file) ? 0 : IS_READ_ONLY) | (delegate.isSymLink(file) ? IS_SYMLINK : 0) | @@ -408,7 +408,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { VirtualFile fake = new FakeVirtualFile(parent, childName); int attributes = delegate.getBooleanAttributes(fake, -1); - if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) { + if ((attributes & FileUtil.BA_EXISTS) != 0) { int child = createAndCopyRecord(delegate, fake, parentId, attributes); FSRecords.updateList(parentId, ArrayUtil.append(children, child)); return child; @@ -673,6 +673,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { } }; + @NotNull private static List validateEvents(@NotNull List events) { final List deletionEvents = Lists.newArrayList(); for (int i = 0, size = events.size(); i < size; i++) { @@ -756,25 +757,22 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { }; } else { - root = new VirtualDirectoryImpl(basePath, null, fs, rootId) { - @NotNull - @Override - public String getName() { - final String name = super.getName(); - - // TODO: HACK!!! Get to simpler solution. - if (getFileSystem() instanceof JarFileSystem) { - String jarName = name.substring(0, name.length() - JarFileSystem.JAR_SEPARATOR.length()); - return jarName.substring(jarName.lastIndexOf('/') + 1); - } - - return name; - } - }; + if (fs instanceof JarFileSystem) { + // optimization: for jar roots do not store base path in the myName field, use local FS file's getPath() + String parentPath = basePath.substring(0, basePath.indexOf(JarFileSystem.JAR_SEPARATOR)); + final VirtualFile parentLocalFile = LocalFileSystem.getInstance().findFileByPath(parentPath); + if (parentLocalFile == null) return null; + root = new JarRoot(fs, rootId, parentLocalFile); + } + else { + root = new VirtualDirectoryImpl(basePath, null, fs, rootId); + } + } + if (!fs.exists(root)) { + return null; } - if (!fs.exists(root)) return null; - int attributes = NewVirtualFileSystem.BA_DIRECTORY | NewVirtualFileSystem.BA_EXISTS; + int attributes = FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS; boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs, attributes); if (!newRoot) { if (fs.getTimeStamp(root) != FSRecords.getTimestamp(rootId)) { @@ -964,7 +962,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { final NewVirtualFileSystem delegate = getDelegate(parent); VirtualFile fake = new FakeVirtualFile(parent, name); int attributes = delegate.getBooleanAttributes(fake, -1); - if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) { + if ((attributes & FileUtil.BA_EXISTS) != 0) { final int parentId = getFileId(parent); int childId = createAndCopyRecord(delegate, fake, parentId, attributes); appendIdToParentList(parentId, childId); @@ -973,7 +971,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { } } - private static int createAndCopyRecord(@NotNull NewVirtualFileSystem delegateSystem, @NotNull VirtualFile delegateFile, int parentId, @NewVirtualFileSystem.FileBooleanAttributes int attributes) { + private static int createAndCopyRecord(@NotNull NewVirtualFileSystem delegateSystem, @NotNull VirtualFile delegateFile, int parentId, @FileUtil.FileBooleanAttributes int attributes) { int childId = FSRecords.createRecord(); copyRecordFromDelegateFS(childId, parentId, delegateFile, delegateSystem, attributes); return childId; @@ -1140,4 +1138,24 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { } return delegate; } + + private static class JarRoot extends VirtualDirectoryImpl { + private final VirtualFile myParentLocalFile; + + public JarRoot(@NotNull NewVirtualFileSystem fs, int rootId, @NotNull VirtualFile parentLocalFile) { + super("", null, fs, rootId); + myParentLocalFile = parentLocalFile; + } + + @NotNull + @Override + public String getName() { + return myParentLocalFile.getName(); + } + + @Override + protected Object rawName() { + return myParentLocalFile.getPath() + JarFileSystem.JAR_SEPARATOR; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java index 4b7cdb8a2e78..77abe7f40088 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java @@ -17,6 +17,7 @@ package com.intellij.openapi.vfs.newvfs.persistent; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.ManagingFS; @@ -32,8 +33,6 @@ import org.jetbrains.annotations.NotNull; import java.util.*; -import static com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem.*; - /** * @author max */ @@ -53,14 +52,14 @@ public class RefreshWorker { public void scan() { final NewVirtualFile root = (NewVirtualFile)myRefreshRoot; NewVirtualFileSystem delegate = root.getFileSystem(); - final int rootAttributes = delegate.getBooleanAttributes(root, BA_EXISTS | BA_DIRECTORY); + final int rootAttributes = delegate.getBooleanAttributes(root, FileUtil.BA_EXISTS | FileUtil.BA_DIRECTORY); - if (root.isDirty() && (rootAttributes & BA_EXISTS) == 0) { + if (root.isDirty() && (rootAttributes & FileUtil.BA_EXISTS) == 0) { scheduleDeletion(root); root.markClean(); } else { - if ((rootAttributes & BA_DIRECTORY) != 0) { + if ((rootAttributes & FileUtil.BA_DIRECTORY) != 0) { delegate = PersistentFS.replaceWithNativeFS(delegate); } @@ -106,7 +105,7 @@ public class RefreshWorker { else { for (VirtualFile child : file.getCachedChildren()) { final int childAttributes = delegate.getBooleanAttributes(child, -1); - if ((childAttributes & BA_EXISTS) != 0) { + if ((childAttributes & FileUtil.BA_EXISTS) != 0) { scheduleChildRefresh(file, child, delegate, childAttributes); } else { @@ -119,9 +118,9 @@ public class RefreshWorker { if (name.isEmpty()) continue; final VirtualFile fake = new FakeVirtualFile(file, name); - final int attributes = delegate.getBooleanAttributes(fake, BA_EXISTS | BA_DIRECTORY); - if ((attributes & BA_EXISTS) != 0) { - final boolean isDir = (attributes & BA_DIRECTORY) != 0; + final int attributes = delegate.getBooleanAttributes(fake, FileUtil.BA_EXISTS | FileUtil.BA_DIRECTORY); + if ((attributes & FileUtil.BA_EXISTS) != 0) { + final boolean isDir = (attributes & FileUtil.BA_DIRECTORY) != 0; scheduleCreation(file, name, isDir); } } @@ -150,20 +149,20 @@ public class RefreshWorker { } } - private static final int SPECIAL_MASK = BA_REGULAR | BA_DIRECTORY | BA_EXISTS; + private static final int SPECIAL_MASK = FileUtil.BA_REGULAR | FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS; // todo[r.sh] compare link targets for files too private void scheduleChildRefresh(@NotNull VirtualFileSystemEntry parent, @NotNull VirtualFile child, @NotNull NewVirtualFileSystem delegate, - @FileBooleanAttributes int childAttributes) { + @FileUtil.FileBooleanAttributes int childAttributes) { final boolean currentIsDirectory = child.isDirectory(); final boolean currentIsSymlink = child.isSymLink(); final boolean currentIsSpecial = child.isSpecialFile(); final String currentLinkTarget = child instanceof SymlinkDirectory ? ((SymlinkDirectory)child).getTargetPath() : null; - final boolean upToDateIsDirectory = (childAttributes & BA_DIRECTORY) != 0; + final boolean upToDateIsDirectory = (childAttributes & FileUtil.BA_DIRECTORY) != 0; final boolean upToDateIsSymlink = delegate.isSymLink(child); - final boolean upToDateIsSpecial = (childAttributes & SPECIAL_MASK) == BA_EXISTS; + final boolean upToDateIsSpecial = (childAttributes & SPECIAL_MASK) == FileUtil.BA_EXISTS; final String upToDateLinkTarget = currentLinkTarget != null ? delegate.resolveSymLink(child) : null; if (currentIsDirectory != upToDateIsDirectory || diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 923655c66b55..a3837cda2ba5 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -28,6 +28,7 @@ import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import com.intellij.util.io.URLUtil; +import org.intellij.lang.annotations.MagicConstant; import org.intellij.lang.annotations.RegExp; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -57,6 +58,8 @@ public class FileUtil { private static final long CHANNELS_COPYING_LIMIT = 5L * MEGABYTE; private static String ourCanonicalTempPathCache = null; private static final int MAX_FILE_DELETE_ATTEMPTS = 10; + public static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD; + public static final Object/* java.io.FileSystem */ JAVA_IO_FILESYSTEM; @Nullable public static String getRelativePath(File base, File file) { @@ -613,7 +616,10 @@ public class FileUtil { String parentDirPath = file.getParent(); if (parentDirPath != null) { final File parentFile = new File(parentDirPath); - return parentFile.exists() && parentFile.isDirectory() || parentFile.mkdirs(); + int attributes = getBooleanAttributes(file); + boolean ok = attributes != -1 && (attributes & (BA_EXISTS | BA_DIRECTORY)) == (BA_EXISTS | BA_DIRECTORY) + || parentFile.exists() && parentFile.isDirectory(); + return ok || parentFile.mkdirs(); } } return true; @@ -1327,4 +1333,53 @@ public class FileUtil { } return firstLine.contains(marker); } + + // copied from FileSystem: they are package local there + public static final int BA_EXISTS = 0x01; + public static final int BA_REGULAR = 0x02; + public static final int BA_DIRECTORY = 0x04; + public static final int BA_HIDDEN = 0x08; + + // todo[r.sh] use NIO2 API after migration to JDK 7 + // returns -1 if could not get attributes + @MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN}) + public static int getBooleanAttributes(@NotNull File f) { + if (JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD != null) { + try { + Object flags = JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD.invoke(JAVA_IO_FILESYSTEM, f); + return ((Integer)flags).intValue(); + } + catch (Exception ignored) { } + } + return -1; + } + + @MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN}) + public @interface FileBooleanAttributes {} + + + static { + Object fs; + Method getBooleanAttributes; + try { + Class fsClass = Class.forName("java.io.FileSystem"); + Method getFileSystem = fsClass.getMethod("getFileSystem"); + getFileSystem.setAccessible(true); + fs = getFileSystem.invoke(null); + getBooleanAttributes = fsClass.getDeclaredMethod("getBooleanAttributes", File.class); + if (fs == null || getBooleanAttributes == null) { + fs = null; + getBooleanAttributes = null; + } + else { + getBooleanAttributes.setAccessible(true); + } + } + catch (Exception e) { + fs = null; + getBooleanAttributes = null; + } + JAVA_IO_FILESYSTEM = fs; + JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD = getBooleanAttributes; + } }