Handle long file names by IdeaWin32

This commit is contained in:
Roman Shevchenko
2012-07-25 19:28:23 +02:00
parent 460a02bfb6
commit b6ac7c8947
8 changed files with 79 additions and 20 deletions
Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -128,7 +128,7 @@ JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs
}
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo(JNIEnv *env, jobject method, jstring path) {
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo0(JNIEnv *env, jobject method, jstring path) {
WIN32_FIND_DATA data;
HANDLE h = FindFileInner(env, path, &data);
@@ -165,7 +165,7 @@ JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getI
}
JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink(JNIEnv *env, jobject method, jstring path) {
JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink0(JNIEnv *env, jobject method, jstring path) {
WIN32_FIND_DATA data;
HANDLE h = FindFileInner(env, path, &data);
if (h == INVALID_HANDLE_VALUE) {
@@ -209,7 +209,7 @@ JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_reso
}
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren(JNIEnv *env, jobject method, jstring path) {
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren0(JNIEnv *env, jobject method, jstring path) {
WIN32_FIND_DATA data;
HANDLE h = FindFileInner(env, path, &data);
if (h == INVALID_HANDLE_VALUE) {
+3 -3
View File
@@ -25,13 +25,13 @@ extern "C" {
JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs
(JNIEnv *, jclass);
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo0
(JNIEnv *, jobject, jstring);
JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink
JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink0
(JNIEnv *, jobject, jstring);
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren0
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
@@ -15,7 +15,6 @@
*/
package com.intellij.openapi.vfs.impl.win32;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.win32.FileInfo;
import com.intellij.openapi.util.io.win32.IdeaWin32;
@@ -32,7 +31,7 @@ import java.util.Map;
* @author Dmitry Avdeev
*/
class Win32FsCache {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32FsCache");
//private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32FsCache");
private final IdeaWin32 myKernel = IdeaWin32.getInstance();
private final Map<String, FileInfo> myCache = new THashMap<String, FileInfo>();
@@ -43,13 +42,13 @@ class Win32FsCache {
@NotNull
String[] list(@NotNull String absolutePath) {
FileInfo[] fileInfos = myKernel.listChildren(absolutePath.replace('/', '\\') + "\\*.*");
if (fileInfos == null) {
FileInfo[] fileInfo = myKernel.listChildren(absolutePath.replace('/', '\\'));
if (fileInfo == null) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
ArrayList<String> names = new ArrayList<String>(fileInfos.length);
for (FileInfo info : fileInfos) {
ArrayList<String> names = new ArrayList<String>(fileInfo.length);
for (FileInfo info : fileInfo) {
if (info.name.equals(".")) {
myCache.put(absolutePath, info);
continue;
@@ -351,9 +351,6 @@ public class FileSystemUtil {
private static class IdeaWin32MediatorImpl implements Mediator {
private static final String PATH_PREFIX = "\\\\?\\";
private static final int PREFIX_SIZE = PATH_PREFIX.length();
private IdeaWin32 myInstance = IdeaWin32.getInstance();
@Override
@@ -373,8 +370,7 @@ public class FileSystemUtil {
@Override
public String resolveSymLink(@NotNull final String path) throws Exception {
final String result = myInstance.resolveSymLink(path);
return result != null && result.startsWith(PATH_PREFIX) ? result.substring(PREFIX_SIZE) : result;
return myInstance.resolveSymLink(path);
}
@Override
@@ -19,6 +19,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Do not use this class directly.
@@ -29,6 +30,11 @@ import org.jetbrains.annotations.NotNull;
public class IdeaWin32 {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.win32.Win32LocalFileSystem");
private static final String PATH_PREFIX = "\\\\?\\";
private static final int PREFIX_SIZE = PATH_PREFIX.length();
private static final String PATH_SUFFIX = "\\*.*";
private static final int MAX_PATH = 260;
private static final IdeaWin32 ourInstance;
static {
@@ -87,9 +93,29 @@ public class IdeaWin32 {
private static native void initIDs();
public native FileInfo getInfo(String path);
@Nullable
public FileInfo getInfo(@NotNull final String path) {
return getInfo0(unc(path));
}
public native String resolveSymLink(String path);
@Nullable
public String resolveSymLink(@NotNull final String path) {
final String result = resolveSymLink0(unc(path));
return result != null && result.startsWith(PATH_PREFIX) ? result.substring(PREFIX_SIZE) : result;
}
public native FileInfo[] listChildren(String path);
@Nullable
public FileInfo[] listChildren(@NotNull final String path) {
return listChildren0(unc(path) + PATH_SUFFIX);
}
private static String unc(final String path) {
return path.length() < MAX_PATH ? path : PATH_PREFIX + path;
}
private native FileInfo getInfo0(String path);
private native String resolveSymLink0(String path);
private native FileInfo[] listChildren0(String path);
}
@@ -16,6 +16,9 @@
package com.intellij.openapi.util.io;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.win32.FileInfo;
import com.intellij.openapi.util.io.win32.IdeaWin32;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
@@ -201,6 +204,41 @@ public class FileAttributesReadingTest {
assertTimestampEquals(file.lastModified(), attributes.lastModified);
}
@Test
public void extraLongName() throws Exception {
final String prefix = StringUtil.repeatSymbol('a', 128) + ".";
final File dir = FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
FileUtil.createTempDirectory(
myTempDirectory, prefix, ".dir"),
prefix, ".dir"),
prefix, ".dir"),
prefix, ".dir"),
prefix, ".dir"),
prefix, ".dir");
final File file = FileUtil.createTempFile(dir, prefix, ".txt", true);
assertTrue(file.exists());
FileUtil.writeToFile(file, myTestData);
final FileAttributes attributes = getAttributes(file);
assertEquals(FileAttributes.Type.FILE, attributes.type);
assertEquals(0, attributes.flags);
assertEquals(myTestData.length, attributes.length);
assertTimestampEquals(file.lastModified(), attributes.lastModified);
assertTrue(attributes.isWritable());
if (SystemInfo.isWindows) {
final String[] list1 = dir.list();
assertNotNull(list1);
final FileInfo[] list2 = IdeaWin32.getInstance().listChildren(dir.getPath());
assertNotNull(list2);
assertEquals(list1.length + 2, list2.length);
}
}
@NotNull
private static FileAttributes getAttributes(@NotNull final File file) {
final FileAttributes attributes = FileSystemUtil.getAttributes(file);