[vfs] unifies handling of archive file systems by the persistence layer

This commit is contained in:
Roman Shevchenko
2016-02-09 18:31:49 +01:00
parent e4a5d0446a
commit 064ca1aabd
3 changed files with 51 additions and 31 deletions
@@ -38,6 +38,7 @@ import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.List;
@@ -86,6 +87,13 @@ public class JrtFileSystem extends ArchiveFileSystem {
return PROTOCOL;
}
@Nullable
@Override
protected String normalize(@NotNull String path) {
int p = path.indexOf(SEPARATOR);
return p > 0 ? FileUtil.normalize(path.substring(0, p)) + path.substring(p) : super.normalize(path);
}
@NotNull
@Override
protected String extractLocalPath(@NotNull String rootPath) {
@@ -111,7 +119,7 @@ public class JrtFileSystem extends ArchiveFileSystem {
protected ArchiveHandler getHandler(@NotNull VirtualFile entryFile) {
checkSubscription();
String homePath = FileUtil.toSystemIndependentName(extractLocalPath(extractRootPath(entryFile.getPath())));
String homePath = extractLocalPath(extractRootPath(entryFile.getPath()));
ArchiveHandler handler = myHandlers.get(homePath);
if (handler == null) {
handler = isSupported() ? new JrtHandler(homePath) : new JrtHandlerStub(homePath);
@@ -180,6 +188,11 @@ public class JrtFileSystem extends ArchiveFileSystem {
VfsImplUtil.refresh(this, asynchronous);
}
@Override
protected boolean isCorrectFileType(@NotNull VirtualFile local) {
return isModularJdk(FileUtil.toSystemDependentName(local.getPath()));
}
public static boolean isSupported() {
return SUPPORTED;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -15,14 +15,13 @@
*/
package com.intellij.openapi.vfs.newvfs;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.impl.ArchiveHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -73,8 +72,8 @@ public abstract class ArchiveFileSystem extends NewVirtualFileSystem {
VirtualFile local = LOCAL_FILE.get(root);
if (local == null) {
String localPath = extractLocalPath(extractRootPath(entry.getPath()));
local = LocalFileSystem.getInstance().findFileByPath(localPath);
String localPath = extractLocalPath(root.getPath());
local = StandardFileSystems.local().findFileByPath(localPath);
if (local != null) LOCAL_FILE.set(root, local);
}
return local;
@@ -229,4 +228,25 @@ public abstract class ArchiveFileSystem extends NewVirtualFileSystem {
public OutputStream getOutputStream(@NotNull VirtualFile file, Object requestor, long modStamp, long timeStamp) throws IOException {
throw new IOException(VfsBundle.message("jar.modification.not.supported.error", file.getUrl()));
}
}
// service methods
/**
* Returns a local file of an archive which hosts a root with the given path
* (i.e.: "jar:///path/to/jar.jar!/" => file:///path/to/jar.jar),
* or null if the local file is of incorrect type.
*/
@Nullable
public VirtualFile findLocalByRootPath(@NotNull String rootPath) {
String localPath = extractLocalPath(rootPath);
VirtualFile local = StandardFileSystems.local().findFileByPath(localPath);
return local != null && isCorrectFileType(local) ? local : null;
}
/**
* Implementations should return {@code false} if the given file may not host this file system.
*/
protected boolean isCorrectFileType(@NotNull VirtualFile local) {
return FileTypeRegistry.getInstance().getFileTypeByFileName(local.getName()) == FileTypes.ARCHIVE;
}
}
@@ -20,9 +20,6 @@ import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.ShutDownTracker;
@@ -861,7 +858,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
@Override
@Nullable
public VirtualFileSystemEntry findRoot(@NotNull String basePath, @NotNull NewVirtualFileSystem fs) {
public VirtualFileSystemEntry findRoot(@NotNull final String basePath, @NotNull NewVirtualFileSystem fs) {
if (basePath.isEmpty()) {
LOG.error("Invalid root, fs=" + fs);
return null;
@@ -872,30 +869,21 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
VirtualFileSystemEntry root = myRoots.get(rootUrl);
if (root != null) return root;
final VirtualFileSystemEntry newRoot;
String rootPathBeforeSplash;
String rootName;
if (fs instanceof JarFileSystem) {
String parentPath = basePath.substring(0, basePath.indexOf(JarFileSystem.JAR_SEPARATOR));
VirtualFile parentFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
if (parentFile == null) return null;
FileType type = FileTypeRegistry.getInstance().getFileTypeByFileName(parentFile.getName());
if (type != FileTypes.ARCHIVE) return null;
rootName = parentFile.getName();
rootPathBeforeSplash = parentFile.getPath() + "!";
if (fs instanceof ArchiveFileSystem) {
VirtualFile localFile = ((ArchiveFileSystem)fs).findLocalByRootPath(basePath);
if (localFile == null) return null;
rootName = localFile.getName();
}
else {
rootName = basePath;
rootPathBeforeSplash = StringUtil.trimEnd(basePath, "/");
}
final String finalRootPathBeforeSplash = rootPathBeforeSplash;
FileAttributes attributes = fs.getAttributes(new StubVirtualFile() {
@NotNull
@Override
public String getPath() {
return finalRootPathBeforeSplash + "/";
return basePath;
}
@Nullable
@@ -912,7 +900,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
VfsData.Segment segment = VfsData.getSegment(rootId, true);
VfsData.DirectoryData directoryData = new VfsData.DirectoryData();
newRoot = new FsRoot(rootId, segment, directoryData, fs, rootName, rootPathBeforeSplash);
VirtualFileSystemEntry newRoot = new FsRoot(rootId, segment, directoryData, fs, rootName, StringUtil.trimEnd(basePath, "/"));
boolean mark;
synchronized (myRoots) {
@@ -1312,7 +1300,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
@NotNull
@Override
public String getPath() {
return myPathBeforeSlash + "/";
return myPathBeforeSlash + '/';
}
@NotNull
@@ -1321,5 +1309,4 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
return getFileSystem().getProtocol() + "://" + getPath();
}
}
}
}