diff --git a/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtFileSystem.java b/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtFileSystem.java index 99dcc6f6da05..0701359cb5c5 100644 --- a/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtFileSystem.java +++ b/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtFileSystem.java @@ -63,7 +63,7 @@ public class JrtFileSystem extends ArchiveFileSystem { private static void scheduleConfiguredSdkCheck() { if (isSupported()) return; - final MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); + MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() { @Override public void appStarting(Project project) { @@ -111,14 +111,14 @@ public class JrtFileSystem extends ArchiveFileSystem { protected ArchiveHandler getHandler(@NotNull VirtualFile entryFile) { checkSubscription(); - final String homePath = 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); myHandlers.put(homePath, handler); ApplicationManager.getApplication().invokeLater(() -> { - VirtualFile dir = LocalFileSystem.getInstance().refreshAndFindFileByPath(homePath + "/lib/modules"); - if (dir != null) dir.getChildren(); + VirtualFile modules = LocalFileSystem.getInstance().refreshAndFindFileByPath(homePath + "/lib/modules"); + if (modules != null && modules.isDirectory()) modules.getChildren(); }, ModalityState.defaultModalityState()); } return handler; @@ -136,9 +136,11 @@ public class JrtFileSystem extends ArchiveFileSystem { for (VFileEvent event : events) { if (event.getFileSystem() instanceof LocalFileSystem && event instanceof VFileContentChangeEvent) { VirtualFile file = event.getFile(); - if (file != null && "jimage".equals(file.getExtension())) { - String homePath = file.getParent().getParent().getParent().getPath(); - if (myHandlers.remove(homePath) != null) { + if (file != null) { + String homePath = null; + if ("modules".equals(file.getName())) homePath = file.getParent().getParent().getPath(); + else if ("jimage".equals(file.getExtension())) homePath = file.getParent().getParent().getParent().getPath(); + if (homePath != null && myHandlers.remove(homePath) != null) { VirtualFile root = findFileByPath(composeRootPath(homePath)); if (root != null) { ((NewVirtualFile)root).markDirtyRecursively(); @@ -183,7 +185,7 @@ public class JrtFileSystem extends ArchiveFileSystem { } public static boolean isModularJdk(@NotNull String homePath) { - return new File(homePath, "lib/modules").isDirectory(); + return new File(homePath, "lib/modules").exists() && new File(homePath, "jrt-fs.jar").isFile(); } public static boolean isRoot(@NotNull VirtualFile file) { diff --git a/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtHandler.java b/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtHandler.java index 15a055d9dc59..ebf29fbfcd9a 100644 --- a/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtHandler.java +++ b/java/java-impl/src/com/intellij/openapi/vfs/impl/jrt/JrtHandler.java @@ -94,20 +94,23 @@ class JrtHandler extends ArchiveHandler { private void process(Path entry, BasicFileAttributes attrs) throws IOException { int pathLength = entry.getNameCount(); - if (pathLength > 2) { - Path relativePath = entry.subpath(2, pathLength); - EntryInfo parent = map.get(pathLength > 3 ? relativePath.getParent().toString() : StringUtilRt.EMPTY_STRING); - if (parent == null) throw new IOException("Out of order: " + entry); - String path = relativePath.toString(), shortName = entry.getFileName().toString(); - 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)); - } + if (pathLength <= 2) return; + + 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() : StringUtilRt.EMPTY_STRING); + 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)); } } }); diff --git a/java/java-tests/testData/jrt/image1 b/java/java-tests/testData/jrt/image1 new file mode 100644 index 000000000000..194a8c3301d9 Binary files /dev/null and b/java/java-tests/testData/jrt/image1 differ diff --git a/java/java-tests/testData/jrt/image2 b/java/java-tests/testData/jrt/image2 new file mode 100644 index 000000000000..d2081d27f779 Binary files /dev/null and b/java/java-tests/testData/jrt/image2 differ diff --git a/java/java-tests/testData/jrt/jrt-fs.jar b/java/java-tests/testData/jrt/jrt-fs.jar new file mode 100644 index 000000000000..1c2a8d43bba1 Binary files /dev/null and b/java/java-tests/testData/jrt/jrt-fs.jar differ diff --git a/java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java b/java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java index cb15694b6c63..b8185dc08456 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java @@ -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,46 +15,84 @@ */ package com.intellij.openapi.vfs; +import com.intellij.JavaTestUtil; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.impl.jrt.JrtFileSystem; -import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.fixtures.BareTestFixtureTestCase; +import com.intellij.testFramework.rules.TempDirectory; +import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import static org.junit.Assert.*; -import static org.junit.Assume.assumeNotNull; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assume.assumeTrue; -public class JrtFileSystemTest { - private static String ourJdkHome = System.getenv("JDK_19"); +public class JrtFileSystemTest extends BareTestFixtureTestCase { + @Rule public TempDirectory myTempDir = new TempDirectory(); + + private Path myTestData; + private VirtualFile myRoot; @BeforeClass public static void setUpClass() { assumeTrue("skipped: java=" + SystemInfo.JAVA_VERSION, JrtFileSystem.isSupported()); - assumeTrue("skipped: JDK_19=" + ourJdkHome, ourJdkHome != null && JrtFileSystem.isModularJdk(ourJdkHome)); + } - LightPlatformTestCase.initApplication(); + @Before + public void setUp() throws IOException { + myTestData = Paths.get(JavaTestUtil.getJavaTestDataPath(), "jrt"); + Files.copy(myTestData.resolve("jrt-fs.jar"), myTempDir.getRoot().toPath().resolve("jrt-fs.jar")); + Path lib = Files.createDirectory(myTempDir.getRoot().toPath().resolve("lib")); + Files.copy(myTestData.resolve("image1"), lib.resolve("modules")); + + String url = VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, myTempDir.getRoot() + JrtFileSystem.SEPARATOR); + myRoot = VirtualFileManager.getInstance().findFileByUrl(url); + assertThat(myRoot).isNotNull(); + assertThat(JrtFileSystem.isRoot(myRoot)).isTrue(); } @Test - public void testBasicOps() throws IOException { - String url = VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(ourJdkHome) + JrtFileSystem.SEPARATOR); - VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(url); - assertNotNull(root); - assertTrue(JrtFileSystem.isRoot(root)); + public void basicOps() throws IOException { + assertThat(myRoot.findChild("test")).isNotNull(); - assumeNotNull(root.findChild("java")); - assumeNotNull(root.findChild("javax")); + List names = Stream.of(myRoot.getChildren()).map(VirtualFile::getName).collect(Collectors.toList()); + assertThat(names).containsOnly("test"); - VirtualFile object = root.findFileByRelativePath("java/lang/Object.class"); - assertNotNull(object); + VirtualFile classFile = myRoot.findFileByRelativePath("test/pkg1/Class1.class"); + assertThat(classFile).isNotNull(); - byte[] bytes = object.contentsToByteArray(); - assertTrue(bytes.length > 10); - assertEquals(0xCAFEBABE, ByteBuffer.wrap(bytes).getInt()); + byte[] bytes = classFile.contentsToByteArray(); + assertThat(bytes.length).isGreaterThan(10); + assertThat(ByteBuffer.wrap(bytes).getInt()).isEqualTo(0xCAFEBABE); } -} + + @Test + public void refresh() throws IOException { + VirtualFile dir = myRoot.findChild("test"); + assertThat(dir).isNotNull(); + + assertThat(dir.isValid()).isTrue(); + assertThat(Stream.of(dir.getChildren()).map(VirtualFile::getName).collect(Collectors.toList())).containsOnly("pkg1"); + assertThat(myRoot.findFileByRelativePath("test/pkg2/Class2.class")).isNull(); + + Files.copy(myTestData.resolve("image2"), myTempDir.getRoot().toPath().resolve("lib/modules"), StandardCopyOption.REPLACE_EXISTING); + VirtualFile local = LocalFileSystem.getInstance().findFileByIoFile(myTempDir.getRoot()); + assertThat(local).isNotNull(); + local.refresh(false, true); + + assertThat(dir.isValid()).isTrue(); + assertThat(Stream.of(dir.getChildren()).map(VirtualFile::getName).collect(Collectors.toList())).containsOnly("pkg1", "pkg2"); + assertThat(myRoot.findFileByRelativePath("test/pkg2/Class2.class")).isNotNull(); + } +} \ No newline at end of file diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java index f9363e383135..71c2564bb5f7 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java @@ -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. @@ -53,12 +53,12 @@ public class JavaSdkUtil { jarDirs = new File[]{libEndorsedDir, libDir, classesDir, libExtDir}; } } - else if (new File(home, "lib/modules").isDirectory()) { + else if (new File(home, "lib/modules").exists()) { File libDir = new File(home, "lib"); jarDirs = new File[]{libDir}; } else { - File libDir = isJre ? new File(home, "lib") : new File(home, "jre/lib"); + File libDir = new File(home, isJre ? "lib" : "jre/lib"); File libExtDir = new File(libDir, "ext"); File libEndorsedDir = new File(libDir, "endorsed"); jarDirs = new File[]{libEndorsedDir, libDir, libExtDir}; @@ -127,4 +127,4 @@ public class JavaSdkUtil { return null; } } -} +} \ No newline at end of file