Use bulk file attributes reading

This commit is contained in:
Roman Shevchenko
2012-07-30 20:32:14 +02:00
parent 8d1bb377ba
commit bb6ae1d5c1
18 changed files with 283 additions and 387 deletions
@@ -38,6 +38,9 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class JarHandlerBase {
private static final long DEFAULT_LENGTH = 0L;
private static final long DEFAULT_TIMESTAMP = -1L;
protected final TimedReference<JarFile> myJarFile = new TimedReference<JarFile>(null);
protected SoftReference<Map<String, EntryInfo>> myRelPathsToEntries = new SoftReference<Map<String, EntryInfo>>(null);
protected final Object lock = new Object();
@@ -246,7 +249,7 @@ public class JarHandlerBase {
public long getLength(@NotNull final VirtualFile file) {
synchronized (lock) {
final JarFile.JarEntry entry = convertToEntry(file);
return entry != null ? entry.getSize() : 0;
return entry != null ? entry.getSize() : DEFAULT_LENGTH;
}
}
@@ -282,7 +285,7 @@ public class JarHandlerBase {
if (file.getParent() == null) return getOriginalFile().lastModified(); // Optimization
synchronized (lock) {
final JarFile.JarEntry entry = convertToEntry(file);
return entry != null ? entry.getTime() : -1L;
return entry != null ? entry.getTime() : DEFAULT_TIMESTAMP;
}
}
@@ -307,8 +310,12 @@ public class JarHandlerBase {
@Nullable
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
synchronized (lock) {
final EntryInfo entryInfo = getEntryInfo(getRelativePath(file));
if (entryInfo == null) return null;
final JarFile.JarEntry entry = convertToEntry(file);
return entry != null ? new FileAttributes(entry.isDirectory(), false, false, false, entry.getSize(), entry.getTime(), false) : null;
final long length = entry != null ? entry.getSize() : DEFAULT_LENGTH;
final long timeStamp = entry != null ? entry.getTime() : DEFAULT_TIMESTAMP;
return new FileAttributes(entryInfo.isDirectory, false, false, false, length, timeStamp, false);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,11 @@ import java.io.InputStream;
import java.io.OutputStream;
public interface FileSystemInterface {
boolean exists(@NotNull VirtualFile fileOrDirectory);
// default values for missing files (same as in corresponding java.io.File methods)
long DEFAULT_LENGTH = 0;
long DEFAULT_TIMESTAMP = 0;
boolean exists(@NotNull VirtualFile file);
@NotNull
String[] list(@NotNull VirtualFile file);
@@ -17,7 +17,6 @@
package com.intellij.openapi.vfs.newvfs;
import com.intellij.openapi.util.io.FileAttributes;
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;
@@ -116,42 +115,6 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements
return file.getName();
}
/**
* 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.
*
* @param file to query.
* @param flags Attributes to query the file for.
* Each attribute is an int constant from this class.
* Following attributes are defined:
* <ul>
* <li>{@link com.intellij.openapi.util.io.FileUtil#BA_EXISTS} is set if {@link java.io.File#exists()} returns true</li>
* <li>{@link com.intellij.openapi.util.io.FileUtil#BA_DIRECTORY} is set if {@link java.io.File#isDirectory()} returns true</li>
* <li>{@link com.intellij.openapi.util.io.FileUtil#BA_HIDDEN} is set if {@link java.io.File#isHidden()} returns true</li>
* <li>{@link com.intellij.openapi.util.io.FileUtil#BA_REGULAR} is set if {@link java.io.File#isFile()} returns true</li>
* </ul>
* Attributes can be bitwise ORed together to query several file attributes at once.
* <code>-1</code> as an argument value will query all attributes.
* @return Attributes mask for the file, where the bit is set if the corresponding attribute for the file is true.
* That is, the return value is <pre>{@code
* (file.exists() ? BA_EXISTS : 0) |
* (file.isDirectory()() ? BA_DIRECTORY : 0) |
* (file.isRegular()() ? BA_REGULAR : 0) |
* (file.isHidden()() ? BA_HIDDEN : 0)
* }</pre>
* Except that the bit in the return value is undefined if the corresponding bit in the flags parameter is not set.
* <p>
* Example usage:
* <pre>{@code
* int attributes = getBooleanAttributes(file, BA_EXISTS | BA_DIRECTORY);
* if ((attributes & BA_EXISTS) != 0) {
* // file exists
* boolean isDirectory = (attributes & BA_DIRECTORY) != 0;
* }}</pre>
*/
@FileUtil.FileBooleanAttributes
public abstract int getBooleanAttributes(@NotNull final VirtualFile file, @FileUtil.FileBooleanAttributes int flags);
/**
* Reads various file attributes in one shot (to reduce the number of native I/O calls).
*
@@ -19,7 +19,6 @@ 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.FileAttributes;
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;
@@ -368,15 +367,6 @@ public class TempFileSystem extends NewVirtualFileSystem {
}
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
FSItem item = convert(file);
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;
}
@Override
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
final FSItem item = convert(file);
@@ -359,24 +359,6 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
return VfsImplUtil.refreshAndFindFileByPath(this, path);
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
int exists = 0;
JarHandler handler = getHandler(file);
if ((flags & FileUtil.BA_EXISTS) != 0) {
exists = handler.exists(file) ? FileUtil.BA_EXISTS : 0;
}
int isDir = 0;
if ((flags & FileUtil.BA_DIRECTORY) != 0) {
isDir = handler.isDirectory(file) ? FileUtil.BA_DIRECTORY : 0;
}
int regular = 0;
if ((flags & FileUtil.BA_REGULAR) != 0) {
regular = isDir == 0 ? FileUtil.BA_REGULAR : 0;
}
return exists | isDir | regular;
}
@Override
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
final JarHandler handler = getHandler(file);
@@ -385,8 +367,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
if (file.getParent() == null) {
final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
final VirtualFile originalFile = localFileSystem.findFileByIoFile(handler.getOriginalFile());
assert originalFile != null : file;
return localFileSystem.getAttributes(originalFile);
return originalFile != null ? localFileSystem.getAttributes(originalFile) : null;
}
return handler.getAttributes(file);
@@ -52,8 +52,8 @@ import java.util.Locale;
public abstract class LocalFileSystemBase extends LocalFileSystem {
protected static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl");
protected static final long DEFAULT_LENGTH = 0;
protected static final long DEFAULT_TIMESTAMP = 0;
private static final FileAttributes FAKE_ROOT_ATTRIBUTES =
new FileAttributes(true, false, false, false, DEFAULT_LENGTH, DEFAULT_TIMESTAMP, false);
private final List<LocalFileOperationsHandler> myHandlers = new ArrayList<LocalFileOperationsHandler>();
@@ -143,14 +143,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
private static File convertToIOFileAndCheck(@NotNull final VirtualFile file) throws FileNotFoundException {
final File ioFile = convertToIOFile(file);
int intFlags = FileUtil.getBooleanAttributes(ioFile);
if (intFlags != -1) {
if ((intFlags & FileUtil.BA_EXISTS) != 0 && (intFlags & FileUtil.BA_REGULAR) == 0) {
throw new FileNotFoundException("Not a file: " + ioFile);
}
return ioFile;
}
if (ioFile.exists() && !ioFile.isFile()) {
final FileAttributes attributes = FileSystemUtil.getAttributes(ioFile);
if (attributes != null && !attributes.isFile()) {
throw new FileNotFoundException("Not a file: " + ioFile);
}
@@ -158,36 +152,38 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
}
@Override
public boolean exists(@NotNull final VirtualFile fileOrDirectory) {
String path = fileOrDirectory.getPath();
if (fileOrDirectory.getParent() == null && path.startsWith("//")) return true; // Windows UNC root like //unit-333
if (StringUtil.isEmpty(path)) return true; // fake top dir for Windows
return convertToIOFile(fileOrDirectory).exists();
public boolean exists(@NotNull final VirtualFile file) {
return getAttributes(file) != null;
}
@Override
public long getLength(@NotNull final VirtualFile file) {
return convertToIOFile(file).length();
final FileAttributes attributes = getAttributes(file);
return attributes != null ? attributes.length : DEFAULT_LENGTH;
}
@Override
public long getTimeStamp(@NotNull final VirtualFile file) {
return convertToIOFile(file).lastModified();
final FileAttributes attributes = getAttributes(file);
return attributes != null ? attributes.lastModified : DEFAULT_TIMESTAMP;
}
@Override
public boolean isDirectory(@NotNull final VirtualFile file) {
return convertToIOFile(file).isDirectory();
final FileAttributes attributes = getAttributes(file);
return attributes != null && attributes.isDirectory();
}
@Override
public boolean isWritable(@NotNull final VirtualFile file) {
return convertToIOFile(file).canWrite();
final FileAttributes attributes = getAttributes(file);
return attributes != null && attributes.isWritable();
}
@Override
public boolean isSymLink(@NotNull final VirtualFile file) {
return FileSystemUtil.isSymLink(file.getPath());
final FileAttributes attributes = getAttributes(file);
return attributes != null && attributes.isSymLink();
}
@Override
@@ -197,17 +193,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
@Override
public boolean isSpecialFile(@NotNull final VirtualFile file) {
if (!SystemInfo.isUnix) return false;
final File ioFile = convertToIOFile(file);
return isSpecialFile(ioFile);
}
private static boolean isSpecialFile(@NotNull File ioFile) {
int flags = FileUtil.getBooleanAttributes(ioFile);
if (flags != -1) {
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();
final FileAttributes attributes = getAttributes(file);
return attributes != null && attributes.isSpecial();
}
@Override
@@ -243,6 +230,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
return names == null ? ArrayUtil.EMPTY_STRING_ARRAY : names;
}
// todo[r.sh] drop the restriction in favor of VfsUtilCore.visitChildrenRecursively()
protected static boolean isInvalidSymLink(@NotNull final VirtualFile file) {
if (!file.isSymLink()) return false;
final VirtualFile target = file.getCanonicalFile();
@@ -301,7 +289,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
}
}
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtil.toVirtualFileArray(filesToRefresh));
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtilCore.toVirtualFileArray(filesToRefresh));
}
finally {
if (fireCommonRefreshSession) manager.fireAfterRefreshFinish(false);
@@ -323,7 +311,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
collection = new ArrayList<VirtualFile>();
ContainerUtil.addAll(collection, files);
}
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtil.toVirtualFileArray(collection));
RefreshQueue.getInstance().refresh(async, recursive, onFinish, VfsUtilCore.toVirtualFileArray(collection));
}
@Override
@@ -570,11 +558,13 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
@NotNull final VirtualFile vFile,
@NotNull final VirtualFile newParent,
@NotNull final String copyName) throws IOException {
File physicalFile = convertToIOFile(vFile);
if (isSpecialFile(physicalFile)) {
throw new FileNotFoundException("Not a file: " + physicalFile);
final FileAttributes attributes = getAttributes(vFile);
if (attributes == null || attributes.isSpecial()) {
throw new FileNotFoundException("Not a file: " + vFile);
}
File physicalFile = convertToIOFile(vFile);
File physicalCopy = auxCopy(vFile, newParent, copyName);
try {
@@ -583,7 +573,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
physicalCopy = new File(newPhysicalParent, copyName);
try {
if (physicalFile.isDirectory()) {
if (attributes.isDirectory()) {
FileUtil.copyDir(physicalFile, physicalCopy);
}
else {
@@ -604,6 +594,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
}
});
}
return new FakeVirtualFile(newParent, copyName);
}
@@ -725,19 +716,13 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
}
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
int attributes = FileUtil.getBooleanAttributes(convertToIOFile(file));
if (attributes != -1) return attributes & flags;
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);
}
@Override
public FileAttributes getAttributes(@NotNull final VirtualFile file) {
return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(file.getPath()));
final String path = file.getPath();
if (StringUtil.isEmpty(path) || file.getParent() == null && path.startsWith("//")) {
return FAKE_ROOT_ATTRIBUTES; // fake Windows roots
}
return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(path));
}
@Override
@@ -15,7 +15,6 @@
*/
package com.intellij.openapi.vfs.impl.win32;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.win32.FileInfo;
import com.intellij.openapi.util.io.win32.IdeaWin32;
import com.intellij.openapi.vfs.VirtualFile;
@@ -81,26 +80,4 @@ class Win32FsCache {
}
return info;
}
@FileUtil.FileBooleanAttributes
int getBooleanAttributes(@NotNull VirtualFile file, @FileUtil.FileBooleanAttributes int flags) {
FileInfo info = getInfo(file);
if (info == null) return 0;
int result = 0;
if ((flags & FileUtil.BA_EXISTS) != 0) {
result |= FileUtil.BA_EXISTS;
}
if ((flags & FileUtil.BA_DIRECTORY) != 0) {
result |= (info.attributes & FileInfo.FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : FileUtil.BA_DIRECTORY;
}
if ((flags & FileUtil.BA_REGULAR) != 0) {
result |= (info.attributes & (FileInfo.FILE_ATTRIBUTE_DIRECTORY | FileInfo.FILE_ATTRIBUTE_DEVICE | FileInfo.FILE_ATTRIBUTE_REPARSE_POINT)) != 0
? 0 : FileUtil.BA_REGULAR;
}
if ((flags & FileUtil.BA_HIDDEN) != 0) {
result |= (info.attributes & FileInfo.FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : FileUtil.BA_HIDDEN;
}
return result;
}
}
@@ -66,9 +66,9 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
}
@Override
public boolean exists(@NotNull VirtualFile fileOrDirectory) {
if (fileOrDirectory.getParent() == null) return true;
return myFsCache.getInfo(fileOrDirectory) != null;
public boolean exists(@NotNull VirtualFile file) {
if (file.getParent() == null) return true;
return myFsCache.getInfo(file) != null;
}
@Override
@@ -83,6 +83,18 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
return fileInfo != null && notSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_READONLY);
}
@Override
public boolean isSymLink(@NotNull VirtualFile file) {
final FileInfo fileInfo = myFsCache.getInfo(file);
return fileInfo != null && isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_REPARSE_POINT);
}
@Override
public boolean isSpecialFile(@NotNull VirtualFile file) {
final FileInfo fileInfo = myFsCache.getInfo(file);
return fileInfo != null && isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_DEVICE);
}
@Override
public long getTimeStamp(@NotNull VirtualFile file) {
final FileInfo fileInfo = myFsCache.getInfo(file);
@@ -112,9 +124,4 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
@Nullable Collection<String> flatRoots) {
throw new UnsupportedOperationException();
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
return myFsCache.getBooleanAttributes(file, flags);
}
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
@@ -311,12 +312,11 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
@Nullable
private VirtualFileSystemEntry createAndFindChildWithEventFire(@NotNull String name) {
final NewVirtualFileSystem delegate = getFileSystem();
VirtualFile fake = new FakeVirtualFile(this, name);
int attributes = delegate.getBooleanAttributes(fake, FileUtil.BA_EXISTS | FileUtil.BA_DIRECTORY);
if ((attributes & FileUtil.BA_EXISTS) != 0) {
final VirtualFile fake = new FakeVirtualFile(this, name);
final FileAttributes attributes = delegate.getAttributes(fake);
if (attributes != null) {
final String realName = delegate.getCanonicallyCasedName(fake);
boolean isDir = (attributes & FileUtil.BA_DIRECTORY) != 0;
VFileCreateEvent event = new VFileCreateEvent(null, this, realName, isDir, true);
final VFileCreateEvent event = new VFileCreateEvent(null, this, realName, attributes.isDirectory(), true);
RefreshQueue.getInstance().processSingleEvent(event);
return findChild(realName);
}
@@ -19,7 +19,6 @@ import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileTooBigException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -87,8 +86,9 @@ public abstract class VirtualFileSystemEntry extends NewVirtualFile {
}
private void calcLinkStatus() {
putUserData(SYMLINK_TARGET, isSymLink() ? FileSystemUtil.resolveSymLink(getPath()) : null);
setFlagInt(HAS_SYMLINK_FLAG, isSymLink() || ((VirtualFileSystemEntry)myParent).getFlagInt(HAS_SYMLINK_FLAG));
boolean symLink = isSymLink();
putUserData(SYMLINK_TARGET, symLink ? myParent.getFileSystem().resolveSymLink(this) : null);
setFlagInt(HAS_SYMLINK_FLAG, symLink || ((VirtualFileSystemEntry)myParent).getFlagInt(HAS_SYMLINK_FLAG));
}
private static Object encodeName(@NotNull String name) {
@@ -23,10 +23,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.ByteSequence;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem;
@@ -189,9 +186,10 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
childrenIds[i] = currentIds[idx];
}
else {
FakeVirtualFile child = new FakeVirtualFile(file, name);
int attributes = delegate.getBooleanAttributes(child, -1);
int childId = createAndCopyRecord(delegate, child, id, attributes);
final FakeVirtualFile child = new FakeVirtualFile(file, name);
final FileAttributes attributes = delegate.getAttributes(child);
assert attributes != null : delegate + ": " + child;
final int childId = createAndCopyRecord(delegate, child, id, attributes);
childrenIds[i] = childId;
}
}
@@ -289,32 +287,26 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
private static boolean copyRecordFromDelegateFS(final int id,
final int parentId,
@NotNull VirtualFile file,
@NotNull NewVirtualFileSystem delegate,
@FileUtil.FileBooleanAttributes int attributes) {
@NotNull NewVirtualFileSystem fs,
@NotNull FileAttributes attributes) {
String name = file.getName();
if (!name.isEmpty() && namesEqual(delegate, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
if (name.isEmpty()) { // TODO: hack
if (areChildrenLoaded(id)) return false;
if (!name.isEmpty()) {
if (namesEqual(fs, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
}
else {
if (areChildrenLoaded(id)) return false; // TODO: hack
}
FSRecords.setParent(id, parentId);
FSRecords.setName(id, name);
delegate = replaceWithNativeFS(delegate);
FSRecords.setTimestamp(id, attributes.lastModified);
FSRecords.setLength(id, attributes.isDirectory() ? -1L : attributes.length);
FSRecords.setTimestamp(id, delegate.getTimeStamp(file));
boolean isDir = (attributes & FileUtil.BA_DIRECTORY) != 0;
FSRecords.setLength(id, isDir ? -1L : delegate.getLength(file));
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) |
(isSpecial ? IS_SPECIAL : 0), true);
FSRecords.setFlags(id, (attributes.isDirectory() ? IS_DIRECTORY_FLAG : 0) |
(attributes.isWritable() ? 0 : IS_READ_ONLY) |
(attributes.isSymLink() ? IS_SYMLINK : 0) |
(attributes.isSpecial() ? IS_SPECIAL : 0), true);
return true;
}
@@ -404,10 +396,10 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
if (namesEqual(delegate, childName, FSRecords.getName(childId))) return childId;
}
VirtualFile fake = new FakeVirtualFile(parent, childName);
int attributes = delegate.getBooleanAttributes(fake, -1);
if ((attributes & FileUtil.BA_EXISTS) != 0) {
int child = createAndCopyRecord(delegate, fake, parentId, attributes);
final VirtualFile fake = new FakeVirtualFile(parent, childName);
final FileAttributes attributes = delegate.getAttributes(fake);
if (attributes != null) {
final int child = createAndCopyRecord(delegate, fake, parentId, attributes);
FSRecords.updateList(parentId, ArrayUtil.append(children, child));
return child;
}
@@ -764,6 +756,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
if (basePath.isEmpty()) {
// fake root for windows
root = new VirtualDirectoryImpl("", null, fs, rootId) {
@SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod")
@Override
@NotNull
public VirtualFile[] getChildren() {
@@ -789,14 +782,15 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
root = new VirtualDirectoryImpl(basePath, null, fs, rootId);
}
}
if (!fs.exists(root)) {
final FileAttributes attributes = fs.getAttributes(root);
if (attributes == null) {
return null;
}
int attributes = FileUtil.BA_DIRECTORY | FileUtil.BA_EXISTS;
boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs, attributes);
final boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs, attributes);
if (!newRoot) {
if (fs.getTimeStamp(root) != FSRecords.getTimestamp(rootId)) {
if (attributes.lastModified != FSRecords.getTimestamp(rootId)) {
root.markDirtyRecursively();
}
}
@@ -981,11 +975,11 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
private static void executeCreateChild(@NotNull VirtualFile parent, @NotNull String name) {
final NewVirtualFileSystem delegate = getDelegate(parent);
VirtualFile fake = new FakeVirtualFile(parent, name);
int attributes = delegate.getBooleanAttributes(fake, -1);
if ((attributes & FileUtil.BA_EXISTS) != 0) {
final VirtualFile fake = new FakeVirtualFile(parent, name);
final FileAttributes attributes = delegate.getAttributes(fake);
if (attributes != null) {
final int parentId = getFileId(parent);
int childId = createAndCopyRecord(delegate, fake, parentId, attributes);
final int childId = createAndCopyRecord(delegate, fake, parentId, attributes);
appendIdToParentList(parentId, childId);
assert parent instanceof VirtualDirectoryImpl : parent;
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)parent;
@@ -993,8 +987,11 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
}
private static int createAndCopyRecord(@NotNull NewVirtualFileSystem delegateSystem, @NotNull VirtualFile delegateFile, int parentId, @FileUtil.FileBooleanAttributes int attributes) {
int childId = FSRecords.createRecord();
private static int createAndCopyRecord(@NotNull NewVirtualFileSystem delegateSystem,
@NotNull VirtualFile delegateFile,
int parentId,
@NotNull FileAttributes attributes) {
final int childId = FSRecords.createRecord();
copyRecordFromDelegateFS(childId, parentId, delegateFile, delegateSystem, attributes);
return childId;
}
@@ -1097,8 +1094,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
final NewVirtualFileSystem delegate = getDelegate(file);
FSRecords.setLength(getFileId(file), delegate.getLength(file));
FSRecords.setTimestamp(getFileId(file), delegate.getTimeStamp(file));
final FileAttributes attributes = delegate.getAttributes(file);
FSRecords.setLength(getFileId(file), attributes != null ? attributes.length : DEFAULT_LENGTH);
FSRecords.setTimestamp(getFileId(file), attributes != null ? attributes.lastModified : DEFAULT_TIMESTAMP);
((VirtualFileSystemEntry)file).setModificationStamp(newModificationStamp);
}
@@ -16,8 +16,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.util.io.FileAttributes;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
@@ -36,152 +35,149 @@ import java.util.*;
* @author max
*/
public class RefreshWorker {
private final VirtualFile myRefreshRoot;
private final boolean myIsRecursive;
private final Queue<VirtualFile> myRefreshQueue = new Queue<VirtualFile>(100);
private final List<VFileEvent> myEvents = new ArrayList<VFileEvent>();
public RefreshWorker(final VirtualFile refreshRoot, final boolean isRecursive) {
myRefreshRoot = refreshRoot;
myIsRecursive = isRecursive;
myRefreshQueue.addLast(refreshRoot);
}
public void scan() {
final NewVirtualFile root = (NewVirtualFile)myRefreshRoot;
NewVirtualFileSystem delegate = root.getFileSystem();
final int rootAttributes = delegate.getBooleanAttributes(root, -1);
final NewVirtualFile root = (NewVirtualFile)myRefreshQueue.peekFirst();
if (!root.isDirty()) return;
if (root.isDirty() && (rootAttributes & FileUtil.BA_EXISTS) == 0) {
NewVirtualFileSystem fs = root.getFileSystem();
final FileAttributes rootAttributes = fs.getAttributes(root);
if (rootAttributes == null) {
scheduleDeletion(root);
root.markClean();
return;
}
else {
if ((rootAttributes & FileUtil.BA_DIRECTORY) != 0) {
delegate = PersistentFS.replaceWithNativeFS(delegate);
if (rootAttributes != null && rootAttributes.isDirectory()) {
fs = PersistentFS.replaceWithNativeFS(fs);
}
final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance();
while (!myRefreshQueue.isEmpty()) {
final VirtualFileSystemEntry file = (VirtualFileSystemEntry)myRefreshQueue.pullFirst();
if (!file.isDirty()) continue;
final FileAttributes attributes = Comparing.equal(file, root) ? rootAttributes : fs.getAttributes(file);
if (attributes == null) {
scheduleDeletion(file);
continue;
}
final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance();
boolean checkFurther = true;
final VirtualFileSystemEntry parent = file.getParent();
if (parent != null && checkAndScheduleAttributesChange(parent, file, attributes)) {
// ignore everything else
checkFurther = false;
}
else if (file.isDirectory()) {
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)file;
final boolean fullSync = dir.allChildrenLoaded();
if (fullSync) {
final Set<String> currentNames = new HashSet<String>(Arrays.asList(persistence.list(file)));
final Set<String> upToDateNames = new HashSet<String>(Arrays.asList(VfsUtil.filterNames(fs.list(file))));
while (!myRefreshQueue.isEmpty()) {
final VirtualFileSystemEntry file = (VirtualFileSystemEntry)myRefreshQueue.pullFirst();
if (!file.isDirty()) continue;
final Set<String> newNames = new HashSet<String>(upToDateNames);
newNames.removeAll(currentNames);
int attributes = Comparing.equal(file, root) ? rootAttributes : delegate.getBooleanAttributes(file, -1);
VirtualFileSystemEntry parent = file.getParent();
if (parent != null && checkAndScheduleAttributesChange(parent, file, delegate, attributes)) {
// ignore everything else
}
else if (file.isDirectory()) {
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)file;
final boolean fullSync = dir.allChildrenLoaded();
if (fullSync) {
final Set<String> currentNames = new HashSet<String>(Arrays.asList(persistence.list(file)));
final Set<String> upToDateNames = new HashSet<String>(Arrays.asList(VfsUtil.filterNames(delegate.list(file))));
final Set<String> deletedNames = new HashSet<String>(currentNames);
deletedNames.removeAll(upToDateNames);
final Set<String> newNames = new HashSet<String>(upToDateNames);
newNames.removeAll(currentNames);
final Set<String> deletedNames = new HashSet<String>(currentNames);
deletedNames.removeAll(upToDateNames);
for (String name : deletedNames) {
scheduleDeletion(file.findChild(name));
}
for (String name : newNames) {
boolean isDirectory = delegate.isDirectory(new FakeVirtualFile(file, name));
scheduleCreation(file, name, isDirectory);
}
for (VirtualFile child : file.getChildren()) {
if (!deletedNames.contains(child.getName())) {
final int childAttributes = delegate.getBooleanAttributes(child, -1);
scheduleChildRefresh(file, child, delegate, childAttributes);
}
}
for (String name : deletedNames) {
scheduleDeletion(file.findChild(name));
}
else {
for (VirtualFile child : file.getCachedChildren()) {
final int childAttributes = delegate.getBooleanAttributes(child, -1);
if ((childAttributes & FileUtil.BA_EXISTS) != 0) {
scheduleChildRefresh(file, child, delegate, childAttributes);
}
else {
scheduleDeletion(child);
}
}
final List<String> names = dir.getSuspiciousNames();
for (String name : names) {
if (name.isEmpty()) continue;
for (String name : newNames) {
boolean isDirectory = fs.isDirectory(new FakeVirtualFile(file, name));
scheduleCreation(file, name, isDirectory);
}
final VirtualFile fake = new FakeVirtualFile(file, name);
final int childAttributes = delegate.getBooleanAttributes(fake, FileUtil.BA_EXISTS | FileUtil.BA_DIRECTORY);
if ((childAttributes & FileUtil.BA_EXISTS) != 0) {
final boolean isDir = (childAttributes & FileUtil.BA_DIRECTORY) != 0;
scheduleCreation(file, name, isDir);
}
for (VirtualFile child : file.getChildren()) {
if (!deletedNames.contains(child.getName())) {
checkAndScheduleChildRefresh(file, child, fs.getAttributes(child));
}
}
}
else {
long currentTimestamp = persistence.getTimeStamp(file);
long upToDateTimestamp = delegate.getTimeStamp(file);
long currentLength = SystemInfo.isUnix ? persistence.getLengthNoFollow(file) : -1;
long upToDateLength = SystemInfo.isUnix ? delegate.getLength(file) : -1;
for (VirtualFile child : file.getCachedChildren()) {
final FileAttributes childAttributes = fs.getAttributes(child);
if (childAttributes != null) {
checkAndScheduleChildRefresh(file, child, childAttributes);
}
else {
scheduleDeletion(child);
}
}
if (currentTimestamp != upToDateTimestamp || currentLength != upToDateLength) {
scheduleUpdateContent(file);
final List<String> names = dir.getSuspiciousNames();
for (String name : names) {
if (name.isEmpty()) continue;
final VirtualFile fake = new FakeVirtualFile(file, name);
final FileAttributes childAttributes = fs.getAttributes(fake);
if (childAttributes != null) {
scheduleCreation(file, name, childAttributes.isDirectory());
}
}
}
}
else {
final long currentTimestamp = persistence.getTimeStamp(file);
final long upToDateTimestamp = attributes.lastModified;
final long currentLength = persistence.getLengthNoFollow(file);
final long upToDateLength = attributes.length;
boolean currentWritable = persistence.isWritable(file);
boolean upToDateWritable = delegate.isWritable(file);
if (currentTimestamp != upToDateTimestamp || currentLength != upToDateLength) {
scheduleUpdateContent(file);
}
}
if (checkFurther) {
final boolean currentWritable = persistence.isWritable(file);
final boolean upToDateWritable = attributes.isWritable();
if (currentWritable != upToDateWritable) {
scheduleWritableAttributeChange(file, currentWritable, upToDateWritable);
}
file.markClean();
}
file.markClean();
}
}
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,
@FileUtil.FileBooleanAttributes int childAttributes) {
if (!checkAndScheduleAttributesChange(parent, child, delegate, childAttributes)) {
boolean upToDateIsDirectory = (childAttributes & FileUtil.BA_DIRECTORY) != 0;
private void checkAndScheduleChildRefresh(@NotNull VirtualFileSystemEntry parent,
@NotNull VirtualFile child,
@NotNull FileAttributes childAttributes) {
if (!checkAndScheduleAttributesChange(parent, child, childAttributes)) {
final boolean upToDateIsDirectory = childAttributes.isDirectory();
if (myIsRecursive || !upToDateIsDirectory) {
myRefreshQueue.addLast(child);
}
}
}
// returns true if change was detected and events scheduled
private boolean checkAndScheduleAttributesChange(@NotNull VirtualFileSystemEntry parent,
@NotNull VirtualFile child,
@NotNull NewVirtualFileSystem delegate,
@FileUtil.FileBooleanAttributes int childAttributes) {
@NotNull FileAttributes 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 & FileUtil.BA_DIRECTORY) != 0;
final boolean upToDateIsSymlink = delegate.isSymLink(child);
final boolean upToDateIsSpecial = (childAttributes & SPECIAL_MASK) == FileUtil.BA_EXISTS;
//final String upToDateLinkTarget = currentLinkTarget != null ? delegate.resolveSymLink(child) : null;
final boolean upToDateIsDirectory = childAttributes.isDirectory();
final boolean upToDateIsSymlink = childAttributes.isSymLink();
final boolean upToDateIsSpecial = child.isSpecialFile();
if (currentIsDirectory != upToDateIsDirectory ||
currentIsSymlink != upToDateIsSymlink ||
currentIsSpecial != upToDateIsSpecial /*||
!Comparing.equal(currentLinkTarget, upToDateLinkTarget)*/) {
currentIsSpecial != upToDateIsSpecial) {
scheduleDeletion(child);
scheduleReCreation(parent, child.getName(), upToDateIsDirectory);
return true;
@@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.testFramework.PlatformLangTestCase;
import com.intellij.testFramework.PlatformTestUtil;
@@ -245,10 +246,7 @@ public class LocalFileSystemTest extends PlatformLangTestCase {
assertNotNull(virtualFile);
NewVirtualFileSystem fs = (NewVirtualFileSystem)virtualFile.getFileSystem();
fs = PersistentFS.replaceWithNativeFS(fs);
assertTrue(fs.exists(virtualFile));
final FileAttributes attributes = fs.getAttributes(virtualFile);
FileAttributes attributes = fs.getAttributes(virtualFile);
assertNotNull(attributes);
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(FileAttributes.HIDDEN, attributes.flags);
@@ -285,4 +283,21 @@ public class LocalFileSystemTest extends PlatformLangTestCase {
}
assertEquals(expectedCount, children.length);
}
public void testSingleFileRootRefresh() throws Exception {
File file = FileUtil.createTempFile("test.", ".txt");
VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
assertNotNull(virtualFile);
assertTrue(virtualFile.exists());
assertTrue(virtualFile.isValid());
virtualFile.refresh(false, false);
assertFalse(((VirtualFileSystemEntry)virtualFile).isDirty());
FileUtil.delete(file);
assertFalse(file.exists());
virtualFile.refresh(false, false);
assertFalse(virtualFile.exists());
assertFalse(virtualFile.isValid());
}
}
@@ -54,21 +54,33 @@ public class SymlinkHandlingTest extends LightPlatformLangTestCase {
}
}
public void testBadLinksAreIgnored() throws Exception {
public void testBadLinks() throws Exception {
final File missingFile = new File(FileUtil.getTempDirectory(), "missing_file");
assertTrue(missingFile.getAbsolutePath(), !missingFile.exists() || missingFile.delete());
final File missingLinkFile = createTempLink(missingFile.getAbsolutePath(), "missing_link");
final VirtualFile missingLinkVFile = refreshAndFind(missingLinkFile);
assertNull(missingLinkVFile);
assertBrokenLink(missingLinkVFile);
final File selfLinkFile = createTempLink("self_link", "self_link");
final VirtualFile selfLinkVFile = refreshAndFind(selfLinkFile);
assertNull(selfLinkVFile);
assertBrokenLink(selfLinkVFile);
final File pointLinkFile = createTempLink(".", "point_link");
final VirtualFile pointLinkVFile = refreshAndFind(pointLinkFile);
assertNotNull(pointLinkVFile);
assertTrue(pointLinkVFile.isSymLink());
assertTrue(pointLinkVFile.isDirectory());
assertEquals(0, pointLinkVFile.getChildren().length);
System.out.println(pointLinkVFile.getCanonicalPath());
final File upLinkDir = FileUtil.createTempDirectory("dir1.", null);
final File upLinkFile = createTempLink(upLinkDir.getAbsolutePath(), new File(upLinkDir, "up_link").getAbsolutePath());
final VirtualFile upLinkVFile = refreshAndFind(upLinkFile);
assertNotNull(upLinkVFile);
assertTrue(upLinkVFile.isSymLink());
assertTrue(upLinkVFile.isDirectory());
assertEquals(0, upLinkVFile.getChildren().length);
System.out.println(upLinkVFile.getCanonicalPath());
final File circularDir1 = FileUtil.createTempDirectory("dir1.", null);
final File circularDir2 = FileUtil.createTempDirectory("dir2.", null);
@@ -84,6 +96,13 @@ public class SymlinkHandlingTest extends LightPlatformLangTestCase {
assertEquals(0, circularLink2VFile.getChildren()[0].getChildren().length);
}
private static void assertBrokenLink(@Nullable VirtualFile link) {
assertNotNull(link);
assertTrue(link.isSymLink());
assertEquals(0, link.getLength());
assertNull(link.getCanonicalPath(), link.getCanonicalPath());
}
public void testTargetIsWritable() throws Exception {
final File targetFile = FileUtil.createTempFile("target", "");
final File linkFile = createTempLink(targetFile.getAbsolutePath(), "link");
@@ -241,11 +241,6 @@ public class MockLocalFileSystem extends LocalFileSystem {
return 1;
}
@Override
public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
return 0;
}
@Override
public FileAttributes getAttributes(@NotNull VirtualFile file) {
return null;
@@ -123,6 +123,18 @@ public final class FileAttributes {
return flags;
}
public boolean isFile() {
return type == Type.FILE;
}
public boolean isDirectory() {
return type == Type.DIRECTORY;
}
public boolean isSpecial() {
return type == Type.SPECIAL;
}
public boolean isSymLink() {
return isSet(flags, SYM_LINK);
}
@@ -411,7 +411,7 @@ public class FileSystemUtil {
private JnaUnixMediatorImpl() throws Exception {
myLibC = (LibC)Native.loadLibrary("c", LibC.class);
mySharedMem = new Memory(512);
mySharedMem = new Memory(256);
myModeOffset = SystemInfo.isLinux ? (SystemInfo.is32Bit ? 16 : 24) :
SystemInfo.isMac | SystemInfo.isFreeBSD ? 8 :
SystemInfo.isSolaris ? (SystemInfo.is32Bit ? 20 : 16) :
@@ -436,7 +436,6 @@ public class FileSystemUtil {
int mode = (SystemInfo.isLinux ? mySharedMem.getInt(myModeOffset) : mySharedMem.getShort(myModeOffset)) & LibC.S_MASK;
final boolean isSymlink = (mode & LibC.S_IFLNK) == LibC.S_IFLNK;
if (isSymlink) {
mySharedMem.clear();
res = SystemInfo.isLinux ? myLibC.__xstat64(0, path, mySharedMem) : myLibC.stat(path, mySharedMem);
if (res != 0) {
return FileAttributes.BROKEN_SYMLINK;
@@ -28,7 +28,6 @@ import com.intellij.util.containers.Stack;
import com.intellij.util.io.URLUtil;
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
import gnu.trove.TObjectHashingStrategy;
import org.intellij.lang.annotations.MagicConstant;
import org.intellij.lang.annotations.RegExp;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -396,20 +395,16 @@ public class FileUtil extends FileUtilRt {
public static boolean createParentDirs(@NotNull File file) {
if (!file.exists()) {
String parentDirPath = file.getParent();
if (parentDirPath != null) {
final File parentFile = new File(parentDirPath);
final File parentFile = file.getParentFile();
if (parentFile != null) {
return createDirectory(parentFile);
}
}
return true;
}
public static boolean createDirectory(File parentFile) {
int parentAttributes = getBooleanAttributes(parentFile);
boolean ok = parentAttributes != -1 ? (parentAttributes & (BA_EXISTS | BA_DIRECTORY)) == (BA_EXISTS | BA_DIRECTORY)
: parentFile.exists() && parentFile.isDirectory();
return ok || parentFile.mkdirs();
public static boolean createDirectory(@NotNull File path) {
return path.isDirectory() || path.mkdirs();
}
public static boolean createIfDoesntExist(@NotNull File file) {
@@ -1008,12 +1003,13 @@ public class FileUtil extends FileUtilRt {
@NotNull
public static List<File> findFilesByMask(@NotNull Pattern pattern, @NotNull File dir) {
final ArrayList<File> found = new ArrayList<File>();
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
found.addAll(findFilesByMask(pattern, file));
}
else {
if (pattern.matcher(file.getName()).matches()) {
final File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
found.addAll(findFilesByMask(pattern, file));
}
else if (pattern.matcher(file.getName()).matches()) {
found.add(file);
}
}
@@ -1024,13 +1020,15 @@ public class FileUtil extends FileUtilRt {
@NotNull
public static List<File> findFilesOrDirsByMask(@NotNull Pattern pattern, @NotNull File dir) {
final ArrayList<File> found = new ArrayList<File>();
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
found.addAll(findFilesOrDirsByMask(pattern, file));
}
if (pattern.matcher(file.getName()).matches()) {
found.add(file);
final File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (pattern.matcher(file.getName()).matches()) {
found.add(file);
}
if (file.isDirectory()) {
found.addAll(findFilesOrDirsByMask(pattern, file));
}
}
}
return found;
@@ -1039,7 +1037,7 @@ public class FileUtil extends FileUtilRt {
/**
* Returns empty string for empty path.
* First checks whether provided path is a path of a file with sought-for name.
* Unless found, checks if provided file was a directory. In this case checks existance
* Unless found, checks if provided file was a directory. In this case checks existence
* of child files with given names in order "as provided". Finally checks filename among
* brother-files of provided. Returns null if nothing found.
*
@@ -1152,7 +1150,7 @@ public class FileUtil extends FileUtilRt {
@NotNull
public static File createTempDirectory(@NotNull File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean deleteOnExit) throws IOException {
return FileUtilRt.createTempDirectory(dir, prefix, suffix,deleteOnExit);
return FileUtilRt.createTempDirectory(dir, prefix, suffix, deleteOnExit);
}
@NotNull
@@ -1243,58 +1241,6 @@ public class FileUtil extends FileUtilRt {
return FileUtilRt.loadBytes(stream, length);
}
// 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;
@MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN})
public @interface FileBooleanAttributes {}
private static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD;
private static final Object JAVA_IO_FILESYSTEM;
// todo[r.sh] use NIO2 API after migration to JDK 7
// returns -1 if could not get attributes
@FileBooleanAttributes
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);
//noinspection MagicConstant
return ((Integer)flags).intValue();
}
catch (Exception ignored) { }
}
return -1;
}
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;
}
private static final class CompletedFuture<T> implements Future<T> {
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
@@ -1305,9 +1251,11 @@ public class FileUtil extends FileUtilRt {
public boolean isDone() {
return true;
}
@Nullable
public T get() throws InterruptedException, ExecutionException {
return null;
}
@Nullable
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return null;
}