mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
[java] for modular JDK, uses per-module class roots instead of a single one
This commit is contained in:
+1
-7
@@ -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.
|
||||
@@ -20,11 +20,9 @@ import com.intellij.ide.projectView.impl.nodes.PackageElement;
|
||||
import com.intellij.ide.projectView.impl.nodes.PackageUtil;
|
||||
import com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper;
|
||||
import com.intellij.ide.util.treeView.TreeViewUtil;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.impl.DirectoryIndex;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.impl.jrt.JrtFileSystem;
|
||||
import com.intellij.psi.JavaDirectoryService;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
@@ -70,10 +68,6 @@ public class JavaProjectViewDirectoryHelper extends ProjectViewDirectoryHelper {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getNodeName(final ViewSettings settings, final Object parentValue, final PsiDirectory directory) {
|
||||
if (JrtFileSystem.isRoot(directory.getVirtualFile())) {
|
||||
return LangBundle.message("jrt.node.short");
|
||||
}
|
||||
|
||||
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
|
||||
|
||||
PsiPackage parentPackage;
|
||||
|
||||
@@ -534,23 +534,24 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
}
|
||||
|
||||
private static List<VirtualFile> findClasses(File file, boolean isJre) {
|
||||
List<File> roots = JavaSdkUtil.getJdkClassesRoots(file, isJre);
|
||||
List<String> urls = ContainerUtil.newArrayListWithCapacity(roots.size() + 1);
|
||||
if (JrtFileSystem.isModularJdk(file.getPath())) {
|
||||
urls.add(VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(file.getPath()) + JrtFileSystem.SEPARATOR));
|
||||
}
|
||||
for (File root : roots) {
|
||||
urls.add(VfsUtil.getUrlForLibraryRoot(root));
|
||||
}
|
||||
List<VirtualFile> result = ContainerUtil.newArrayList();
|
||||
VirtualFileManager fileManager = VirtualFileManager.getInstance();
|
||||
|
||||
List<VirtualFile> result = ContainerUtil.newArrayListWithCapacity(urls.size());
|
||||
for (String url : urls) {
|
||||
VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
|
||||
if (vFile != null) {
|
||||
result.add(vFile);
|
||||
String path = file.getPath();
|
||||
if (JrtFileSystem.isModularJdk(path)) {
|
||||
String url = VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(path) + JrtFileSystem.SEPARATOR);
|
||||
for (String module : JrtFileSystem.listModules(path)) {
|
||||
ContainerUtil.addIfNotNull(result, fileManager.findFileByUrl(url + module));
|
||||
}
|
||||
}
|
||||
|
||||
for (File root : JavaSdkUtil.getJdkClassesRoots(file, isJre)) {
|
||||
String url = VfsUtil.getUrlForLibraryRoot(root);
|
||||
ContainerUtil.addIfNotNull(result, fileManager.findFileByUrl(url));
|
||||
}
|
||||
|
||||
Collections.sort(result, (o1, o2) -> o1.getPath().compareTo(o2.getPath()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,12 @@ import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -41,20 +43,34 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.intellij.util.containers.ContainerUtil.newTroveMap;
|
||||
|
||||
public class JrtFileSystem extends ArchiveFileSystem {
|
||||
public static final String PROTOCOL = StandardFileSystems.JRT_PROTOCOL;
|
||||
public static final String PROTOCOL_PREFIX = StandardFileSystems.JRT_PROTOCOL_PREFIX;
|
||||
public static final String SEPARATOR = JarFileSystem.JAR_SEPARATOR;
|
||||
|
||||
private static final boolean SUPPORTED =
|
||||
SystemInfo.isJavaVersionAtLeast("9") || SystemInfo.isJavaVersionAtLeast("1.8") && !SystemInfo.isJavaVersionAtLeast("1.9");
|
||||
|
||||
private static final URI ROOT_URI = URI.create("jrt:/");
|
||||
|
||||
private final Map<String, ArchiveHandler> myHandlers = newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
|
||||
private final AtomicBoolean mySubscribed = new AtomicBoolean(false);
|
||||
|
||||
@@ -63,18 +79,26 @@ public class JrtFileSystem extends ArchiveFileSystem {
|
||||
}
|
||||
|
||||
private static void scheduleConfiguredSdkCheck() {
|
||||
if (isSupported()) return;
|
||||
MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect();
|
||||
connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
|
||||
@Override
|
||||
public void appStarting(Project project) {
|
||||
for (Sdk sdk : ProjectJdkTable.getInstance().getSdksOfType(JavaSdk.getInstance())) {
|
||||
String homePath = sdk.getHomePath();
|
||||
if (homePath != null && isModularJdk(homePath)) {
|
||||
String title = LangBundle.message("jrt.not.available.title", sdk.getName());
|
||||
String message = LangBundle.message("jrt.not.available.message");
|
||||
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, title, message, NotificationType.WARNING));
|
||||
}
|
||||
Stream.of(sdk.getRootProvider().getUrls(OrderRootType.CLASSES))
|
||||
.filter(url -> url.startsWith(PROTOCOL_PREFIX))
|
||||
.findFirst()
|
||||
.ifPresent(url -> {
|
||||
if (!isSupported()) {
|
||||
String title = LangBundle.message("jrt.not.available.title", sdk.getName());
|
||||
String message = LangBundle.message("jrt.not.available.message");
|
||||
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, title, message, NotificationType.WARNING));
|
||||
}
|
||||
else if (url.endsWith(SEPARATOR)) {
|
||||
String title = LangBundle.message("jrt.outdated.title", sdk.getName());
|
||||
String message = LangBundle.message("jrt.outdated.message");
|
||||
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, title, message, NotificationType.WARNING));
|
||||
}
|
||||
});
|
||||
}
|
||||
connection.disconnect();
|
||||
}
|
||||
@@ -204,4 +228,36 @@ public class JrtFileSystem extends ArchiveFileSystem {
|
||||
public static boolean isRoot(@NotNull VirtualFile file) {
|
||||
return file.getParent() == null && file.getFileSystem() instanceof JrtFileSystem;
|
||||
}
|
||||
|
||||
public static boolean isModuleRoot(@NotNull VirtualFile file) {
|
||||
VirtualFile parent = file.getParent();
|
||||
return parent != null && isRoot(parent);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> listModules(@NotNull String path) {
|
||||
try {
|
||||
Path root = getFileSystem(path).getPath("/modules");
|
||||
return Files.list(root).map(p -> p.getFileName().toString()).collect(Collectors.toList());
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.getInstance(JrtFileSystem.class).debug(e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
static FileSystem getFileSystem(String path) throws IOException {
|
||||
FileSystem fs;
|
||||
if (SystemInfo.isJavaVersionAtLeast("9")) {
|
||||
fs = FileSystems.newFileSystem(ROOT_URI, Collections.singletonMap("java.home", path));
|
||||
}
|
||||
else {
|
||||
File file = new File(path, "jrt-fs.jar");
|
||||
if (!file.exists()) throw new IOException("Missing provider: " + file);
|
||||
URL url = file.toURI().toURL();
|
||||
ClassLoader loader = new URLClassLoader(new URL[]{url}, null);
|
||||
fs = FileSystems.newFileSystem(ROOT_URI, Collections.emptyMap(), loader);
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
@@ -15,39 +15,21 @@
|
||||
*/
|
||||
package com.intellij.openapi.vfs.impl.jrt;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.vfs.impl.ArchiveHandler;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.StringInterner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
class JrtHandler extends ArchiveHandler {
|
||||
private static final URI ROOT_URI = URI.create("jrt:/");
|
||||
|
||||
private static class JrtEntryInfo extends EntryInfo {
|
||||
private final String myModule;
|
||||
|
||||
public JrtEntryInfo(@NotNull String shortName, @NotNull String module, long length, long timestamp, EntryInfo parent) {
|
||||
super(shortName, false, length, timestamp, parent);
|
||||
myModule = module;
|
||||
}
|
||||
}
|
||||
|
||||
private SoftReference<FileSystem> myFileSystem;
|
||||
private final StringInterner myInterner = new StringInterner();
|
||||
|
||||
public JrtHandler(@NotNull String path) {
|
||||
super(path);
|
||||
@@ -56,16 +38,7 @@ class JrtHandler extends ArchiveHandler {
|
||||
private synchronized FileSystem getFileSystem() throws IOException {
|
||||
FileSystem fs = SoftReference.dereference(myFileSystem);
|
||||
if (fs == null) {
|
||||
if (SystemInfo.isJavaVersionAtLeast("9")) {
|
||||
fs = FileSystems.newFileSystem(ROOT_URI, Collections.singletonMap("java.home", getFile().getPath()));
|
||||
}
|
||||
else {
|
||||
File file = new File(getFile(), "jrt-fs.jar");
|
||||
if (!file.exists()) throw new IOException("Missing provider: " + file);
|
||||
URL url = file.toURI().toURL();
|
||||
ClassLoader loader = new URLClassLoader(new URL[]{url}, null);
|
||||
fs = FileSystems.newFileSystem(ROOT_URI, Collections.emptyMap(), loader);
|
||||
}
|
||||
fs = JrtFileSystem.getFileSystem(getFile().getPath());
|
||||
myFileSystem = new SoftReference<>(fs);
|
||||
}
|
||||
return fs;
|
||||
@@ -95,23 +68,17 @@ class JrtHandler extends ArchiveHandler {
|
||||
|
||||
private void process(Path entry, BasicFileAttributes attrs) throws IOException {
|
||||
int pathLength = entry.getNameCount();
|
||||
if (pathLength <= 2) return;
|
||||
if (pathLength > 1) {
|
||||
Path relativePath = entry.subpath(1, pathLength);
|
||||
String path = relativePath.toString();
|
||||
if (!map.containsKey(path)) {
|
||||
EntryInfo parent = map.get(pathLength > 2 ? relativePath.getParent().toString() : "");
|
||||
if (parent == null) throw new IOException("Out of order: " + entry);
|
||||
|
||||
Path relativePath = entry.subpath(2, pathLength);
|
||||
String path = relativePath.toString(), shortName = entry.getFileName().toString();
|
||||
if (map.containsKey(path) || "module-info.class".equals(shortName)) return;
|
||||
|
||||
EntryInfo parent = map.get(pathLength > 3 ? relativePath.getParent().toString() : "");
|
||||
if (parent == null) throw new IOException("Out of order: " + entry);
|
||||
|
||||
long length = attrs.size();
|
||||
long modified = attrs.lastModifiedTime().toMillis();
|
||||
if (attrs.isDirectory()) {
|
||||
map.put(path, new EntryInfo(shortName, true, length, modified, parent));
|
||||
}
|
||||
else {
|
||||
String module = myInterner.intern(entry.getName(1).toString());
|
||||
map.put(path, new JrtEntryInfo(shortName, module, length, modified, parent));
|
||||
String shortName = entry.getFileName().toString();
|
||||
long modified = attrs.lastModifiedTime().toMillis();
|
||||
map.put(path, new EntryInfo(shortName, attrs.isDirectory(), attrs.size(), modified, parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -123,8 +90,8 @@ class JrtHandler extends ArchiveHandler {
|
||||
@Override
|
||||
public byte[] contentsToByteArray(@NotNull String relativePath) throws IOException {
|
||||
EntryInfo entry = getEntryInfo(relativePath);
|
||||
if (!(entry instanceof JrtEntryInfo)) throw new FileNotFoundException(getFile() + " : " + relativePath);
|
||||
Path path = getFileSystem().getPath("/modules/" + ((JrtEntryInfo)entry).myModule + '/' + relativePath);
|
||||
if (entry == null) throw new FileNotFoundException(getFile() + " : " + relativePath);
|
||||
Path path = getFileSystem().getPath("/modules/" + relativePath);
|
||||
return Files.readAllBytes(path);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user