Win32 filesystem

This commit is contained in:
Dmitry Avdeev
2009-10-21 13:27:25 +04:00
parent e20cb466db
commit ea91df4385
4 changed files with 54 additions and 47 deletions
@@ -42,6 +42,7 @@ import java.util.Locale;
* @author Dmitry Avdeev
*/
public abstract class LocalFileSystemBase extends LocalFileSystem {
protected static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl");
private final List<LocalFileOperationsHandler> myHandlers = new ArrayList<LocalFileOperationsHandler>();
@@ -20,10 +20,8 @@ import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.FileNotFoundException;
import java.util.*;
/**
* @author Dmitry Avdeev
@@ -46,6 +44,7 @@ public class Win32Kernel {
}};
public static class HANDLE extends PointerType {
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o)) return INVALID_HANDLE_VALUE;
@@ -53,59 +52,72 @@ public class Win32Kernel {
}
}
private static int DATA_SIZE = new WIN32_FIND_DATA().size();
private Map<String, WIN32_FIND_DATA> myCache = new HashMap<String, WIN32_FIND_DATA>();
private List<WIN32_FIND_DATA> myDatas = new ArrayList<WIN32_FIND_DATA>();
private WIN32_FIND_DATA getData() {
if (myDatas.isEmpty()) {
myDatas.add(new WIN32_FIND_DATA());
private static class FileInfo {
private FileInfo(WIN32_FIND_DATA data) {
this.dwFileAttributes = data.dwFileAttributes;
this.ftLastWriteTime = data.ftLastWriteTime.toLong();
}
return myDatas.remove(0);
int dwFileAttributes;
long ftLastWriteTime;
}
private final static WIN32_FIND_DATA DATA = new WIN32_FIND_DATA();
private Map<String, FileInfo> myCache = new HashMap<String, FileInfo>();
public String[] list(String absolutePath) {
myDatas.addAll(myCache.values());
myCache.clear();
ArrayList<String> list = new ArrayList<String>();
WIN32_FIND_DATA data = getData();
HANDLE hFind = myKernel.FindFirstFile(absolutePath.replace('/', '\\') + "\\*", data);
HANDLE hFind = myKernel.FindFirstFile(absolutePath.replace('/', '\\') + "\\*", DATA);
if (hFind == INVALID_HANDLE_VALUE) return new String[0];
do {
String name = toString(data.cFileName);
String name = toString(DATA.cFileName);
if (name.equals(".") || name.equals("..")) {
continue;
}
myCache.put(absolutePath + "/" + name, data);
myCache.put(absolutePath + "/" + name, new FileInfo(DATA));
list.add(name);
data = getData();
}
while (myKernel.FindNextFile(hFind, data));
while (myKernel.FindNextFile(hFind, DATA));
myKernel.FindClose(hFind);
return list.toArray(new String[list.size()]);
}
public boolean isDirectory(String path) throws NotAvailableException {
WIN32_FIND_DATA data = getData(path);
public boolean exists(String path) {
try {
getData(path);
return true;
}
catch (FileNotFoundException e) {
return false;
}
}
public boolean isDirectory(String path) throws FileNotFoundException {
FileInfo data = getData(path);
return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
public boolean isWritable(String path) throws NotAvailableException {
public boolean isWritable(String path) throws FileNotFoundException {
return (getData(path).dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
}
public long getTimeStamp(String path) throws NotAvailableException {
return getData(path).ftLastWriteTime.toLong();
public long getTimeStamp(String path) throws FileNotFoundException {
return getData(path).ftLastWriteTime;
}
private WIN32_FIND_DATA getData(String path) throws NotAvailableException {
WIN32_FIND_DATA data = myCache.get(path);
private FileInfo getData(String path) throws FileNotFoundException {
FileInfo data = myCache.get(path);
if (data == null) {
throw new NotAvailableException(path);
myCache.clear();
HANDLE hFind = myKernel.FindFirstFile(path.replace('/', '\\'), DATA);
if (hFind == INVALID_HANDLE_VALUE) throw new FileNotFoundException(path);
data = new FileInfo(DATA);
myKernel.FindClose(hFind);
myCache.put(path, data);
}
return data;
}
@@ -124,8 +136,6 @@ public class Win32Kernel {
boolean FindNextFile(HANDLE hFindFile, WIN32_FIND_DATA lpFindFileData);
boolean FindClose(HANDLE hFindFile);
int GetLastError();
}
public static class FILETIME extends Structure implements Structure.ByValue {
@@ -142,15 +152,11 @@ public class Win32Kernel {
}
public long toLong() {
long result = dwHighDateTime;
result = result << 32;
result = result + l(dwLowDateTime);
result = result / 10000;
result = result - 11644473600000l;
return result;
return (((long)dwHighDateTime << 32) + l(dwLowDateTime)) / 10000 - 11644473600000l;
}
}
@SuppressWarnings({"UnusedDeclaration"})
public static class WIN32_FIND_DATA extends Structure {
public int dwFileAttributes;
@@ -172,12 +178,5 @@ public class Win32Kernel {
public char[] cFileName = new char[MAX_PATH];
public char[] cAlternateFileName = new char[14];
}
public static class NotAvailableException extends Exception {
public NotAvailableException(String message) {
super(message);
}
}
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.local.LocalFileSystemBase;
import org.jetbrains.annotations.NotNull;
import java.io.FileNotFoundException;
import java.util.Collection;
import java.util.Set;
@@ -44,7 +45,7 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
try {
return myKernel.isDirectory(file.getPath());
}
catch (Win32Kernel.NotAvailableException e) {
catch (FileNotFoundException e) {
return super.isDirectory(file);
}
}
@@ -54,7 +55,7 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
try {
return myKernel.isWritable(file.getPath());
}
catch (Win32Kernel.NotAvailableException e) {
catch (FileNotFoundException e) {
return super.isWritable(file);
}
}
@@ -64,11 +65,16 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
try {
return myKernel.getTimeStamp(file.getPath());
}
catch (Win32Kernel.NotAvailableException e) {
catch (FileNotFoundException e) {
return super.getTimeStamp(file);
}
}
@Override
public boolean exists(VirtualFile fileOrDirectory) {
return myKernel.exists(fileOrDirectory.getPath());
}
@Override
public WatchRequest addRootToWatch(@NotNull String rootPath, boolean toWatchRecursively) {
throw new UnsupportedOperationException();
@@ -63,6 +63,7 @@ public class RefreshWorker {
(applicationEx.isUnitTestMode() || applicationEx.isInternal())) {
delegate = new Win32LocalFileSystem();
}
final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance();
while (!myRefreshQueue.isEmpty()) {