diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index 2d95f6d02559..703dc8a58ef1 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -17,6 +17,7 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.jrt.JrtFileSystem; import com.intellij.util.PathUtil; @@ -32,6 +33,8 @@ import org.jetbrains.jps.model.java.impl.JavaSdkUtil; import javax.swing.*; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; @@ -238,15 +241,15 @@ public class JavaSdkImpl extends JavaSdk { File jdkHome = new File(homePath); SdkModificator sdkModificator = sdk.getSdkModificator(); - List classes = findClasses(jdkHome, false); - Set previousRoots = new LinkedHashSet<>(Arrays.asList(sdkModificator.getRoots(OrderRootType.CLASSES))); + List classes = findClasses(jdkHome, false); + Set previousRoots = new LinkedHashSet<>(Arrays.asList(sdkModificator.getUrls(OrderRootType.CLASSES))); sdkModificator.removeRoots(OrderRootType.CLASSES); previousRoots.removeAll(new HashSet<>(classes)); - for (VirtualFile aClass : classes) { - sdkModificator.addRoot(aClass, OrderRootType.CLASSES); + for (String url : classes) { + sdkModificator.addRoot(url, OrderRootType.CLASSES); } - for (VirtualFile root : previousRoots) { - sdkModificator.addRoot(root, OrderRootType.CLASSES); + for (String url : previousRoots) { + sdkModificator.addRoot(url, OrderRootType.CLASSES); } addSources(jdkHome, sdkModificator); @@ -379,37 +382,67 @@ public class JavaSdkImpl extends JavaSdk { } private static void addClasses(@NotNull File file, @NotNull SdkModificator sdkModificator, boolean isJre) { - for (VirtualFile virtualFile : findClasses(file, isJre)) { - sdkModificator.addRoot(virtualFile, OrderRootType.CLASSES); + for (String url : findClasses(file, isJre)) { + sdkModificator.addRoot(url, OrderRootType.CLASSES); } } + private static List readModulesFromReleaseFile(File jrtBaseDir) { + File releaseFile = new File(jrtBaseDir, "release"); + if (releaseFile.isFile()) { + Properties p = new Properties(); + try (FileInputStream stream = new FileInputStream(releaseFile)) { + p.load(stream); + String modules = p.getProperty("MODULES"); + if (modules != null) { + return StringUtil.split(StringUtil.unquoteString(modules), " "); + } + } + catch (IOException | IllegalArgumentException e) { + LOG.info(e); + } + } + return null; + } + @NotNull - private static List findClasses(@NotNull File file, boolean isJre) { - List result = ContainerUtil.newArrayList(); + private static List findClasses(@NotNull File file, boolean isJre) { + List result = ContainerUtil.newArrayList(); VirtualFileManager fileManager = VirtualFileManager.getInstance(); if (JdkUtil.isExplodedModularRuntime(file.getPath())) { VirtualFile exploded = fileManager.findFileByUrl(StandardFileSystems.FILE_PROTOCOL_PREFIX + getPath(new File(file, "modules"))); if (exploded != null) { - ContainerUtil.addAll(result, exploded.getChildren()); + for (VirtualFile virtualFile : exploded.getChildren()) { + result.add(virtualFile.getUrl()); + } } } else if (JdkUtil.isModularRuntime(file)) { - VirtualFile jrt = fileManager.findFileByUrl(JrtFileSystem.PROTOCOL_PREFIX + getPath(file) + JrtFileSystem.SEPARATOR); - if (jrt != null) { - ContainerUtil.addAll(result, jrt.getChildren()); + String jrtBaseUrl = JrtFileSystem.PROTOCOL_PREFIX + getPath(file) + JrtFileSystem.SEPARATOR; + List modules = readModulesFromReleaseFile(file); + if (modules != null) { + for (String module : modules) { + result.add(jrtBaseUrl + module); + } + } + else { + VirtualFile jrt = fileManager.findFileByUrl(jrtBaseUrl); + if (jrt != null) { + for (VirtualFile virtualFile : jrt.getChildren()) { + result.add(virtualFile.getUrl()); + } + } } } else { for (File root : JavaSdkUtil.getJdkClassesRoots(file, isJre)) { String url = VfsUtil.getUrlForLibraryRoot(root); - ContainerUtil.addIfNotNull(result, fileManager.findFileByUrl(url)); + result.add(url); } } - Collections.sort(result, Comparator.comparing(VirtualFile::getPath)); - + Collections.sort(result); return result; } diff --git a/java/java-tests/testSrc/com/intellij/java/openapi/vfs/JrtFileSystemTest.java b/java/java-tests/testSrc/com/intellij/java/openapi/vfs/JrtFileSystemTest.java index 6e8365a37643..d28b5a304b38 100644 --- a/java/java-tests/testSrc/com/intellij/java/openapi/vfs/JrtFileSystemTest.java +++ b/java/java-tests/testSrc/com/intellij/java/openapi/vfs/JrtFileSystemTest.java @@ -17,6 +17,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.Files; @@ -39,16 +40,26 @@ public class JrtFileSystemTest extends BareTestFixtureTestCase { @Before public void setUp() throws IOException { myTestData = Paths.get(JavaTestUtil.getJavaTestDataPath(), "jrt"); - myTempPath = myTempDir.newFolder("jrt").toPath(); - Files.write(myTempPath.resolve("release"), "JAVA_VERSION=9\n".getBytes(CharsetToolkit.UTF8_CHARSET)); - Path lib = Files.createDirectory(myTempPath.resolve("lib")); - Files.copy(myTestData.resolve("jrt-fs.jar"), lib.resolve("jrt-fs.jar")); - Files.copy(myTestData.resolve("image1"), lib.resolve("modules")); - LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myTempDir.getRoot()); + File jrtDir = myTempDir.newFolder("jrt"); + myTempPath = jrtDir.toPath(); + myRoot = setupJrtFileSystem(jrtDir); + } - myRoot = findRoot(myTempPath.toString()); - assertThat(myRoot).isNotNull(); - assertThat(JrtFileSystem.isRoot(myRoot)).isTrue(); + public static VirtualFile setupJrtFileSystem(File jrtDir) throws IOException { + Path jrtPath = jrtDir.toPath(); + + Files.write(jrtPath.resolve("release"), "JAVA_VERSION=9\n".getBytes(CharsetToolkit.UTF8_CHARSET)); + Path lib = Files.createDirectory(jrtPath.resolve("lib")); + + Path testData = Paths.get(JavaTestUtil.getJavaTestDataPath(), "jrt"); + Files.copy(testData.resolve("jrt-fs.jar"), lib.resolve("jrt-fs.jar")); + Files.copy(testData.resolve("image1"), lib.resolve("modules")); + LocalFileSystem.getInstance().refreshAndFindFileByIoFile(jrtDir.getParentFile()); + + VirtualFile root = findRoot(jrtPath.toString()); + assertThat(root).isNotNull(); + assertThat(JrtFileSystem.isRoot(root)).isTrue(); + return root; } @Test diff --git a/java/java-tests/testSrc/com/intellij/java/openapi/vfs/JrtVirtualFilePointerTest.java b/java/java-tests/testSrc/com/intellij/java/openapi/vfs/JrtVirtualFilePointerTest.java new file mode 100644 index 000000000000..4b50f05cf497 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/openapi/vfs/JrtVirtualFilePointerTest.java @@ -0,0 +1,117 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.java.openapi.vfs; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl; +import com.intellij.openapi.vfs.jrt.JrtFileSystem; +import com.intellij.openapi.vfs.pointers.VirtualFilePointer; +import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; +import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; + +import static com.intellij.openapi.vfs.impl.VirtualFilePointerTest.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assume.assumeTrue; + +/** + * @author yole + */ +public class JrtVirtualFilePointerTest extends LightPlatformCodeInsightFixtureTestCase { + + private VirtualFilePointerManagerImpl myVirtualFilePointerManager; + private Disposable myDisposable; + + public void setUp() throws Exception { + super.setUp(); + myVirtualFilePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); + myDisposable = Disposer.newDisposable(); + } + + public void tearDown() throws Exception { + try { + Disposer.dispose(myDisposable); + } + finally { + super.tearDown(); + } + } + + public void testJrt() throws Exception { + assumeTrue(SystemInfo.isUnix); + final File tempDir = FileUtil.createTempDirectory("jrt", ""); + LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempDir); + JrtFileSystemTest.setupJrtFileSystem(tempDir); + + VirtualFile vTemp = PlatformTestUtil.notNull(refreshAndFindFile(tempDir)); + assertThat(vTemp.isValid()).isTrue(); + + final VirtualFilePointer[] pointersToWatch = new VirtualFilePointer[2]; + final VirtualFilePointerListener listener = new VirtualFilePointerListener() { + @Override + public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { + verifyPointersInCorrectState(pointersToWatch); + } + + @Override + public void validityChanged(@NotNull VirtualFilePointer[] pointers) { + verifyPointersInCorrectState(pointersToWatch); + } + }; + final VirtualFilePointer jrtParentPointer = createPointerByFile(tempDir, listener); + final String jrtUrl = VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, tempDir + JrtFileSystem.SEPARATOR); + final VirtualFilePointer jrtPointer = myVirtualFilePointerManager.create(jrtUrl, myDisposable, listener); + pointersToWatch[0] = jrtParentPointer; + pointersToWatch[1] = jrtPointer; + assertThat(jrtParentPointer.isValid()).isTrue(); + assertThat(jrtPointer.isValid()).isTrue(); + + assertThat(FileUtil.delete(tempDir)).isTrue(); + refreshVFS(); + + verifyPointersInCorrectState(pointersToWatch); + assertThat(jrtParentPointer.isValid()).isFalse(); + assertThat(jrtPointer.isValid()).isFalse(); + UIUtil.dispatchAllInvocationEvents(); + + FileUtil.createDirectory(tempDir); + LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempDir); + JrtFileSystemTest.setupJrtFileSystem(tempDir); + + refreshVFS(); + verifyPointersInCorrectState(pointersToWatch); + assertThat(jrtParentPointer.isValid()).isTrue(); + assertThat(jrtPointer.isValid()).isTrue(); + UIUtil.dispatchAllInvocationEvents(); + + assertThat(FileUtil.delete(tempDir)).isTrue(); + refreshVFS(); + UIUtil.dispatchAllInvocationEvents(); + + verifyPointersInCorrectState(pointersToWatch); + assertThat(jrtParentPointer.isValid()).isFalse(); + assertThat(jrtPointer.isValid()).isFalse(); + UIUtil.dispatchAllInvocationEvents(); + } + + @NotNull + private VirtualFilePointer createPointerByFile(@NotNull File file, @Nullable VirtualFilePointerListener fileListener) throws IOException { + final String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, file.getCanonicalPath().replace(File.separatorChar, '/')); + final VirtualFile vFile = refreshAndFind(url); + return vFile == null + ? myVirtualFilePointerManager.create(url, myDisposable, fileListener) + : myVirtualFilePointerManager.create(vFile, myDisposable, fileListener); + } +} diff --git a/java/openapi/src/com/intellij/openapi/vfs/jrt/JrtFileSystem.java b/java/openapi/src/com/intellij/openapi/vfs/jrt/JrtFileSystem.java index b7d5988e5839..bc3c37195508 100644 --- a/java/openapi/src/com/intellij/openapi/vfs/jrt/JrtFileSystem.java +++ b/java/openapi/src/com/intellij/openapi/vfs/jrt/JrtFileSystem.java @@ -1,27 +1,14 @@ -/* - * Copyright 2000-2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vfs.jrt; import com.intellij.openapi.vfs.StandardFileSystems; +import com.intellij.openapi.vfs.VfpCapableArchiveFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem; import com.intellij.util.io.URLUtil; import org.jetbrains.annotations.NotNull; -public abstract class JrtFileSystem extends ArchiveFileSystem { +public abstract class JrtFileSystem extends ArchiveFileSystem implements VfpCapableArchiveFileSystem { public static final String PROTOCOL = StandardFileSystems.JRT_PROTOCOL; public static final String PROTOCOL_PREFIX = StandardFileSystems.JRT_PROTOCOL_PREFIX; public static final String SEPARATOR = URLUtil.JAR_SEPARATOR; diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java index 2b0b6051026f..b35005a5e4da 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots.ui; import com.intellij.icons.AllIcons; @@ -34,7 +20,6 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.PlatformIcons; -import java.util.HashSet; import com.intellij.util.ui.UIUtil; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; @@ -42,10 +27,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.*; import java.util.List; -import java.util.Set; /** * @author MYakovlev diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java index 32423497f2f8..db1d8c8a43a8 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vfs; import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem; @@ -20,7 +6,7 @@ import com.intellij.util.io.URLUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public abstract class JarFileSystem extends ArchiveFileSystem implements JarCopyingFileSystem, LocalFileProvider { +public abstract class JarFileSystem extends ArchiveFileSystem implements JarCopyingFileSystem, LocalFileProvider, VfpCapableArchiveFileSystem { public static final String PROTOCOL = StandardFileSystems.JAR_PROTOCOL; public static final String PROTOCOL_PREFIX = StandardFileSystems.JAR_PROTOCOL_PREFIX; public static final String JAR_SEPARATOR = URLUtil.JAR_SEPARATOR; diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/VfpCapableArchiveFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/VfpCapableArchiveFileSystem.java new file mode 100644 index 000000000000..b6a29a329102 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/vfs/VfpCapableArchiveFileSystem.java @@ -0,0 +1,10 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.vfs; + +/** + * Marker interface for ArchiveFileSystem implementations that support virtual file pointers to entries. + * + * @author yole + */ +public interface VfpCapableArchiveFileSystem { +} diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java index f3403f2db82a..b6f67f8552c7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vfs.impl; import com.intellij.concurrency.ConcurrentCollectionFactory; @@ -53,7 +39,6 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl"); private final TempFileSystem TEMP_FILE_SYSTEM; private final LocalFileSystem LOCAL_FILE_SYSTEM; - private final JarFileSystem JAR_FILE_SYSTEM; // guarded by this private final Map myPointers = new LinkedHashMap<>(); @@ -67,14 +52,12 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp VirtualFilePointerManagerImpl(@NotNull VirtualFileManager virtualFileManager, @NotNull MessageBus bus, @NotNull TempFileSystem tempFileSystem, - @NotNull LocalFileSystem localFileSystem, - @NotNull JarFileSystem jarFileSystem) { + @NotNull LocalFileSystem localFileSystem) { myVirtualFileManager = virtualFileManager; myBus = bus; bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, this); TEMP_FILE_SYSTEM = tempFileSystem; LOCAL_FILE_SYSTEM = localFileSystem; - JAR_FILE_SYSTEM = jarFileSystem; } @Override @@ -176,7 +159,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp return found == null ? new LightFilePointer(url) : new LightFilePointer(found); } - boolean isJar = fileSystem == JAR_FILE_SYSTEM; + boolean isJar = fileSystem instanceof VfpCapableArchiveFileSystem; if (fileSystem != LOCAL_FILE_SYSTEM && !isJar) { // we are unable to track alien file systems for now VirtualFile found = fileSystem == null ? null : file != null ? file : VirtualFileManager.getInstance().findFileByUrl(url); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java index 5024fb696dce..799d8a0c90a3 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vfs.impl; import com.intellij.concurrency.Job; @@ -562,14 +548,14 @@ public class VirtualFilePointerTest extends PlatformTestCase { LOG.debug("final i = " + i); } - private static void refreshVFS() { + public static void refreshVFS() { ApplicationManager.getApplication().runWriteAction(() -> { VirtualFileManager.getInstance().syncRefresh(); }); UIUtil.dispatchAllInvocationEvents(); } - private static void verifyPointersInCorrectState(VirtualFilePointer[] pointers) { + public static void verifyPointersInCorrectState(VirtualFilePointer[] pointers) { for (VirtualFilePointer pointer : pointers) { final VirtualFile file = pointer.getFile(); assertTrue(file == null || file.isValid()); @@ -644,7 +630,7 @@ public class VirtualFilePointerTest extends PlatformTestCase { assertFalse(pointer.isValid()); } - private static VirtualFile refreshAndFind(@NotNull final String url) { + public static VirtualFile refreshAndFind(@NotNull final String url) { return WriteCommandAction.runWriteCommandAction(null, (Computable)() -> VirtualFileManager.getInstance().refreshAndFindFileByUrl(url)); } diff --git a/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkModificator.java b/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkModificator.java index 0cb80102d89d..1fd2484ddf86 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkModificator.java +++ b/platform/projectModel-api/src/com/intellij/openapi/projectRoots/SdkModificator.java @@ -1,22 +1,11 @@ -/* - * Copyright 2000-2009 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,10 +36,31 @@ public interface SdkModificator { @NotNull VirtualFile[] getRoots(@NotNull OrderRootType rootType); + @NotNull + default String[] getUrls(@NotNull OrderRootType rootType) { + return ContainerUtil.map(getRoots(rootType), file -> file.getUrl(), ArrayUtil.EMPTY_STRING_ARRAY); + } + void addRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType); + default void addRoot(@NotNull String url, @NotNull OrderRootType rootType) { + VirtualFile rootFile = VirtualFileManager.getInstance().findFileByUrl(url); + if (rootFile != null) { + addRoot(rootFile, rootType); + } + } + void removeRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType); + default void removeRoot(@NotNull String url, @NotNull OrderRootType rootType) { + for (VirtualFile file : getRoots(rootType)) { + if (file.getUrl().equals(url)) { + removeRoot(file, rootType); + break; + } + } + } + void removeRoots(@NotNull OrderRootType rootType); void removeAllRoots(); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java index 940edf8eff7f..f6b373e63d7a 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java @@ -1,18 +1,4 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots.impl; import com.intellij.openapi.Disposable; @@ -358,16 +344,32 @@ public class ProjectJdkImpl extends UserDataHolderBase implements Sdk, SdkModifi return myRoots.getFiles(rootType); } + @NotNull + @Override + public String[] getUrls(@NotNull OrderRootType rootType) { + return myRoots.getUrls(rootType); + } + @Override public void addRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType) { myRoots.addRoot(root, rootType); } + @Override + public void addRoot(@NotNull String url, @NotNull OrderRootType rootType) { + myRoots.addRoot(url, rootType); + } + @Override public void removeRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType) { myRoots.removeRoot(root, rootType); } + @Override + public void removeRoot(@NotNull String url, @NotNull OrderRootType rootType) { + myRoots.removeRoot(url, rootType); + } + @Override public void removeRoots(@NotNull OrderRootType rootType) { myRoots.removeAllRoots(rootType); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/RootsAsVirtualFilePointers.java b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/RootsAsVirtualFilePointers.java index 58407fdf3a48..223bb31d1d8b 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/RootsAsVirtualFilePointers.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/RootsAsVirtualFilePointers.java @@ -1,4 +1,4 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots.impl; @@ -56,13 +56,21 @@ public class RootsAsVirtualFilePointers implements RootProvider { myRoots.get(type).add(virtualFile); } + public void addRoot(@NotNull String url, @NotNull OrderRootType type) { + myRoots.get(type).add(url); + } + public void removeAllRoots(@NotNull OrderRootType type) { myRoots.get(type).clear(); } public void removeRoot(@NotNull VirtualFile root, @NotNull OrderRootType type) { + removeRoot(root.getUrl(), type); + } + + public void removeRoot(@NotNull String url, @NotNull OrderRootType type) { VirtualFilePointerContainer container = myRoots.get(type); - VirtualFilePointer pointer = container.findByUrl(root.getUrl()); + VirtualFilePointer pointer = container.findByUrl(url); if (pointer != null) { container.remove(pointer); } @@ -104,8 +112,8 @@ public class RootsAsVirtualFilePointers implements RootProvider { void copyRootsFrom(@NotNull RootProvider rootContainer) { removeAllRoots(); for (OrderRootType rootType : OrderRootType.getAllTypes()) { - final VirtualFile[] newRoots = rootContainer.getFiles(rootType); - for (VirtualFile newRoot : newRoots) { + final String[] newRoots = rootContainer.getUrls(rootType); + for (String newRoot : newRoots) { addRoot(newRoot, rootType); } }