mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
simplify PluginDescriptorLoader
GitOrigin-RevId: e4c68aa7049cbcd85c3a40fca93458c96d0338b5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d92e089eb1
commit
d286794a13
@@ -7,19 +7,19 @@ import com.intellij.openapi.util.SafeJdomFactory;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
||||
import org.jdom.*;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.file.ProviderNotFoundException;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
final class DescriptorListLoadingContext implements AutoCloseable {
|
||||
@ApiStatus.Internal
|
||||
public final class DescriptorListLoadingContext implements AutoCloseable {
|
||||
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
|
||||
private static final boolean unitTestWithBundledPlugins = Boolean.getBoolean("idea.run.tests.with.bundled.plugins");
|
||||
|
||||
@@ -46,8 +46,6 @@ final class DescriptorListLoadingContext implements AutoCloseable {
|
||||
|
||||
private final Map<String, PluginId> optionalConfigNames;
|
||||
|
||||
private FileSystemProvider zipFsProvider;
|
||||
|
||||
public static @NotNull DescriptorListLoadingContext createSingleDescriptorContext(@NotNull Set<PluginId> disabledPlugins) {
|
||||
return new DescriptorListLoadingContext(IGNORE_MISSING_SUB_DESCRIPTOR, disabledPlugins, PluginManagerCore.createLoadingResult(null));
|
||||
}
|
||||
@@ -70,28 +68,6 @@ final class DescriptorListLoadingContext implements AutoCloseable {
|
||||
});
|
||||
}
|
||||
|
||||
FileSystemProvider getZipFsProvider() {
|
||||
FileSystemProvider result = zipFsProvider;
|
||||
if (result == null) {
|
||||
result = findZipFsProvider();
|
||||
zipFsProvider = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static @NotNull FileSystemProvider findZipFsProvider() {
|
||||
for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
|
||||
try {
|
||||
if (provider.getScheme().equals("jar")) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
catch (UnsupportedOperationException ignored) {
|
||||
}
|
||||
}
|
||||
throw new ProviderNotFoundException("Provider not found");
|
||||
}
|
||||
|
||||
boolean isPluginDisabled(@NotNull PluginId id) {
|
||||
return id != PluginManagerCore.CORE_ID && disabledPlugins.contains(id);
|
||||
}
|
||||
|
||||
@@ -1,57 +1,58 @@
|
||||
// Copyright 2000-2021 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.ide.plugins;
|
||||
package com.intellij.ide.plugins
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.io.IOException
|
||||
import java.nio.file.FileSystem
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.ProviderNotFoundException
|
||||
import java.nio.file.spi.FileSystemProvider
|
||||
import java.util.*
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
// parentContext is null only for CoreApplicationEnvironment - it is not valid otherwise because in this case XML is not interned.
|
||||
internal class DescriptorLoadingContext : AutoCloseable {
|
||||
private var openedFiles: MutableMap<Path, FileSystem>? = null
|
||||
|
||||
final class DescriptorLoadingContext implements AutoCloseable {
|
||||
private @Nullable Map<Path, FileSystem> openedFiles;
|
||||
final DescriptorListLoadingContext parentContext;
|
||||
final boolean isBundled;
|
||||
final boolean isEssential;
|
||||
private var zipFsProvider: FileSystemProvider? = null
|
||||
|
||||
/**
|
||||
* parentContext is null only for CoreApplicationEnvironment - it is not valid otherwise because in this case XML is not interned.
|
||||
*/
|
||||
DescriptorLoadingContext(@NotNull DescriptorListLoadingContext parentContext, boolean isBundled, boolean isEssential) {
|
||||
this.parentContext = parentContext;
|
||||
this.isBundled = isBundled;
|
||||
this.isEssential = isEssential;
|
||||
private fun getZipFsProvider(): FileSystemProvider {
|
||||
var result = zipFsProvider
|
||||
if (result == null) {
|
||||
result = findZipFsProvider()
|
||||
zipFsProvider = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@NotNull FileSystem open(@NotNull Path file) {
|
||||
if (openedFiles == null) {
|
||||
openedFiles = new HashMap<>();
|
||||
}
|
||||
return openedFiles.computeIfAbsent(file, it -> {
|
||||
private fun findZipFsProvider(): FileSystemProvider {
|
||||
for (provider in FileSystemProvider.installedProviders()) {
|
||||
try {
|
||||
//noinspection SpellCheckingInspection
|
||||
return parentContext.getZipFsProvider().newFileSystem(it, Collections.singletonMap("zipinfo-time", "false"));
|
||||
if (provider.scheme == "jar") {
|
||||
return provider
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
catch (ignored: UnsupportedOperationException) {
|
||||
}
|
||||
});
|
||||
}
|
||||
throw ProviderNotFoundException("Provider not found")
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (openedFiles != null) {
|
||||
for (FileSystem file : openedFiles.values()) {
|
||||
try {
|
||||
file.close();
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
}
|
||||
fun open(file: Path): FileSystem {
|
||||
if (openedFiles == null) {
|
||||
openedFiles = HashMap()
|
||||
}
|
||||
return openedFiles!!.computeIfAbsent(file) {
|
||||
@Suppress("SpellCheckingInspection")
|
||||
getZipFsProvider().newFileSystem(it, Collections.singletonMap("zipinfo-time", "false"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
for (file in (openedFiles ?: return).values) {
|
||||
try {
|
||||
file.close()
|
||||
}
|
||||
catch (ignore: IOException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 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-2021 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.ide.plugins;
|
||||
|
||||
import com.intellij.core.CoreBundle;
|
||||
@@ -109,7 +109,7 @@ final class PluginLoadingResult {
|
||||
error.register(pluginErrors);
|
||||
}
|
||||
|
||||
void reportCannotLoad(@NotNull Path file, Exception e) {
|
||||
void reportCannotLoad(@NotNull Path file, Throwable e) {
|
||||
DescriptorListLoadingContext.LOG.warn("Cannot load " + file, e);
|
||||
globalErrors.add(() -> CoreBundle.message("plugin.loading.error.text.file.contains.invalid.plugin.descriptor",
|
||||
FileUtil.getLocationRelativeToUserHome(file.toString(), false)));
|
||||
|
||||
@@ -70,16 +70,16 @@ public final class PluginManager {
|
||||
|
||||
public static @Nullable IdeaPluginDescriptorImpl loadDescriptor(@NotNull Path file,
|
||||
@NotNull Set<PluginId> disabledPlugins,
|
||||
boolean bundled,
|
||||
boolean isBundled,
|
||||
@NotNull PathResolver pathResolver) {
|
||||
DescriptorListLoadingContext parentContext = DescriptorListLoadingContext.createSingleDescriptorContext(disabledPlugins);
|
||||
try (DescriptorLoadingContext context = new DescriptorLoadingContext(parentContext, bundled, false)) {
|
||||
return PluginDescriptorLoader.loadDescriptorFromFileOrDir(file,
|
||||
PluginManagerCore.PLUGIN_XML,
|
||||
context,
|
||||
pathResolver,
|
||||
Files.isDirectory(file));
|
||||
}
|
||||
return PluginDescriptorLoader.loadDescriptorFromFileOrDir(file,
|
||||
PluginManagerCore.PLUGIN_XML,
|
||||
parentContext,
|
||||
pathResolver,
|
||||
isBundled,
|
||||
/* isEssential = */false,
|
||||
Files.isDirectory(file));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,6 @@ import java.io.*;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.ref.Reference;
|
||||
import java.net.URL;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -731,7 +730,7 @@ public final class PluginManagerCore {
|
||||
else {
|
||||
effectiveBundledPluginPath = Paths.get(PathManager.getPreInstalledPluginsPath());
|
||||
}
|
||||
PluginDescriptorLoader.loadBundledDescriptorsAndDescriptorsFromDir(context, dir, effectiveBundledPluginPath);
|
||||
PluginDescriptorLoader.loadBundledDescriptorsAndDescriptorsFromDir(context, dir, effectiveBundledPluginPath, isRunningFromSources());
|
||||
|
||||
for (IdeaPluginDescriptorImpl descriptor : loadingResult.idMap.values()) {
|
||||
if (!descriptor.isBundled()) {
|
||||
@@ -777,19 +776,6 @@ public final class PluginManagerCore {
|
||||
prepareLoadingPluginsErrorMessage(pluginErrors, globalErrors, actions);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static @NotNull List<? extends IdeaPluginDescriptor> testLoadDescriptorsFromClassPath(@NotNull ClassLoader loader)
|
||||
throws ExecutionException, InterruptedException {
|
||||
Map<URL, String> urlsFromClassPath = new LinkedHashMap<>();
|
||||
PluginDescriptorLoader.collectPluginFilesInClassPath(loader, urlsFromClassPath);
|
||||
BuildNumber buildNumber = BuildNumber.fromString("2042.42");
|
||||
DescriptorListLoadingContext context = new DescriptorListLoadingContext(0, Collections.emptySet(), new PluginLoadingResult(Collections.emptyMap(), () -> buildNumber, false));
|
||||
PluginDescriptorLoader.loadDescriptorsFromClassPath(urlsFromClassPath, context, null, new ClassPathXmlPathResolver(loader));
|
||||
|
||||
context.result.finishLoading();
|
||||
return context.result.getEnabledPlugins();
|
||||
}
|
||||
|
||||
public static void scheduleDescriptorLoading() {
|
||||
getOrScheduleLoading();
|
||||
}
|
||||
@@ -802,7 +788,7 @@ public final class PluginManagerCore {
|
||||
|
||||
future = CompletableFuture.supplyAsync(() -> {
|
||||
Activity activity = StartUpMeasurer.startActivity("plugin descriptor loading");
|
||||
DescriptorListLoadingContext context = PluginDescriptorLoader.loadDescriptors();
|
||||
DescriptorListLoadingContext context = PluginDescriptorLoader.loadDescriptors(isUnitTestMode, isRunningFromSources());
|
||||
activity.end();
|
||||
return context;
|
||||
}, ForkJoinPool.commonPool());
|
||||
@@ -1350,21 +1336,7 @@ public final class PluginManagerCore {
|
||||
* @param area area which extension points and extensions should be registered
|
||||
*/
|
||||
public static void registerExtensionPointAndExtensions(@NotNull Path pluginRoot, @NotNull String fileName, @NotNull ExtensionsArea area) {
|
||||
IdeaPluginDescriptorImpl descriptor;
|
||||
DescriptorListLoadingContext parentContext =
|
||||
DescriptorListLoadingContext.createSingleDescriptorContext(DisabledPluginsState.disabledPlugins());
|
||||
PathResolver pathResolver = PluginXmlPathResolver.DEFAULT_PATH_RESOLVER;
|
||||
try (DescriptorLoadingContext context = new DescriptorLoadingContext(parentContext, true, true)) {
|
||||
if (Files.isDirectory(pluginRoot)) {
|
||||
descriptor = PluginDescriptorLoader
|
||||
.loadDescriptorFromDir(pluginRoot, META_INF + fileName, null, context.parentContext, context.isEssential, context.isBundled,
|
||||
pathResolver);
|
||||
}
|
||||
else {
|
||||
descriptor = PluginDescriptorLoader.loadDescriptorFromJar(pluginRoot, fileName, pathResolver, context, null);
|
||||
}
|
||||
}
|
||||
|
||||
IdeaPluginDescriptorImpl descriptor = PluginDescriptorLoader.INSTANCE.loadForCoreEnv$intellij_platform_core_impl(pluginRoot, fileName);
|
||||
if (descriptor == null) {
|
||||
getLogger().error("Cannot load " + fileName + " from " + pluginRoot);
|
||||
return;
|
||||
@@ -1387,7 +1359,7 @@ public final class PluginManagerCore {
|
||||
|
||||
try {
|
||||
if (context == null) {
|
||||
context = PluginDescriptorLoader.loadDescriptors();
|
||||
context = PluginDescriptorLoader.loadDescriptors(isUnitTestMode, isRunningFromSources());
|
||||
}
|
||||
Activity activity = StartUpMeasurer.startActivity("plugin initialization");
|
||||
PluginManagerState initResult = initializePlugins(context, coreLoader, !isUnitTestMode);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 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-2021 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.ide.customize;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
@@ -34,7 +34,7 @@ public class PluginGroups {
|
||||
private Runnable myLoadingCallback;
|
||||
|
||||
public PluginGroups() {
|
||||
myAllPlugins = PluginDescriptorLoader.loadUncachedDescriptors();
|
||||
myAllPlugins = PluginDescriptorLoader.loadUncachedDescriptors(PluginManagerCore.isUnitTestMode, PluginManagerCore.isRunningFromSources());
|
||||
SwingWorker<List<PluginNode>, Object> worker = new SwingWorker<>() {
|
||||
@Override
|
||||
protected @NotNull List<PluginNode> doInBackground() {
|
||||
|
||||
@@ -353,10 +353,10 @@ public final class PluginInstaller {
|
||||
return false;
|
||||
}
|
||||
|
||||
IdeaPluginDescriptorImpl targetDescriptor = PluginManager.loadDescriptor(targetFile,
|
||||
DisabledPluginsState.disabledPlugins(),
|
||||
false,
|
||||
PluginXmlPathResolver.DEFAULT_PATH_RESOLVER);
|
||||
IdeaPluginDescriptorImpl targetDescriptor = PluginDescriptorLoader.loadDescriptor(targetFile,
|
||||
DisabledPluginsState.disabledPlugins(),
|
||||
false,
|
||||
PluginXmlPathResolver.DEFAULT_PATH_RESOLVER);
|
||||
if (targetDescriptor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,13 @@ internal fun loadDescriptorInTest(dir: Path, disabledPlugins: Set<PluginId> = em
|
||||
PluginManagerCore.getAndClearPluginLoadingErrors()
|
||||
val buildNumber = BuildNumber.fromString("2042.42")
|
||||
val parentContext = DescriptorListLoadingContext(0, disabledPlugins, PluginLoadingResult(emptyMap(), Supplier { buildNumber }))
|
||||
val result = DescriptorLoadingContext(parentContext, isBundled, /* isEssential = */ true).use { context ->
|
||||
PluginDescriptorLoader.loadDescriptorFromFileOrDir(dir, PluginManagerCore.PLUGIN_XML, context,
|
||||
PluginXmlPathResolver.DEFAULT_PATH_RESOLVER, Files.isDirectory(dir))
|
||||
}
|
||||
val result = PluginDescriptorLoader.loadDescriptorFromFileOrDir(file = dir,
|
||||
pathName = PluginManagerCore.PLUGIN_XML,
|
||||
context = parentContext,
|
||||
pathResolver = PluginXmlPathResolver.DEFAULT_PATH_RESOLVER,
|
||||
isBundled = isBundled,
|
||||
isEssential = true,
|
||||
isDirectory = Files.isDirectory(dir))
|
||||
if (result == null) {
|
||||
@Suppress("USELESS_CAST")
|
||||
assertThat(PluginManagerCore.getAndClearPluginLoadingErrors()).isNotEmpty
|
||||
@@ -44,10 +47,13 @@ fun loadExtensionWithText(
|
||||
}
|
||||
|
||||
internal fun loadPluginWithText(pluginBuilder: PluginBuilder, loader: ClassLoader, fs: FileSystem): Disposable {
|
||||
val directory = if (fs == FileSystems.getDefault())
|
||||
val directory = if (fs == FileSystems.getDefault()) {
|
||||
FileUtil.createTempDirectory("test", "test", true).toPath()
|
||||
else
|
||||
}
|
||||
else {
|
||||
fs.getPath("/").resolve(Ksuid.generate())
|
||||
}
|
||||
|
||||
val pluginDirectory = directory.resolve("plugin")
|
||||
|
||||
pluginBuilder.build(pluginDirectory)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 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-2021 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.
|
||||
@file:Suppress("UsePropertyAccessSyntax")
|
||||
package com.intellij.ide.plugins
|
||||
|
||||
@@ -104,7 +104,7 @@ class PluginDescriptorTest {
|
||||
Paths.get(testDataPath, "duplicate1.jar").toUri().toURL(),
|
||||
Paths.get(testDataPath, "duplicate2.jar").toUri().toURL()
|
||||
)
|
||||
assertThat(PluginManagerCore.testLoadDescriptorsFromClassPath(URLClassLoader(urls, null))).hasSize(1)
|
||||
assertThat(PluginDescriptorLoader.testLoadDescriptorsFromClassPath(URLClassLoader(urls, null))).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -126,7 +126,7 @@ class PluginDescriptorTest {
|
||||
urls.add(path.toUri().toURL())
|
||||
}
|
||||
}
|
||||
val descriptors = PluginManagerCore.testLoadDescriptorsFromClassPath(URLClassLoader(urls.toTypedArray(), null))
|
||||
val descriptors = PluginDescriptorLoader.testLoadDescriptorsFromClassPath(URLClassLoader(urls.toTypedArray(), null))
|
||||
// core and com.intellij.workspace
|
||||
assertThat(descriptors).hasSize(1)
|
||||
}
|
||||
@@ -379,13 +379,13 @@ class PluginDescriptorTest {
|
||||
}
|
||||
|
||||
val loader1 = TestLoader("", "/spaces%20spaces/")
|
||||
TestCase.assertEquals(1, PluginManagerCore.testLoadDescriptorsFromClassPath(loader1).size)
|
||||
TestCase.assertEquals(1, PluginDescriptorLoader.testLoadDescriptorsFromClassPath(loader1).size)
|
||||
val loader2 = TestLoader("", "/spaces spaces/")
|
||||
TestCase.assertEquals(1, PluginManagerCore.testLoadDescriptorsFromClassPath(loader2).size)
|
||||
TestCase.assertEquals(1, PluginDescriptorLoader.testLoadDescriptorsFromClassPath(loader2).size)
|
||||
val loader3 = TestLoader("jar:", "/jar%20spaces.jar!/")
|
||||
TestCase.assertEquals(1, PluginManagerCore.testLoadDescriptorsFromClassPath(loader3).size)
|
||||
TestCase.assertEquals(1, PluginDescriptorLoader.testLoadDescriptorsFromClassPath(loader3).size)
|
||||
val loader4 = TestLoader("jar:", "/jar spaces.jar!/")
|
||||
assertThat(PluginManagerCore.testLoadDescriptorsFromClassPath(loader4)).hasSize(1)
|
||||
assertThat(PluginDescriptorLoader.testLoadDescriptorsFromClassPath(loader4)).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -457,8 +457,8 @@ private fun writeDescriptor(id: String, pluginDir: Path, @Language("xml") data:
|
||||
}
|
||||
|
||||
private val testDataPath: String
|
||||
get() = PlatformTestUtil.getPlatformTestDataPath() + "plugins/pluginDescriptor"
|
||||
get() = "${PlatformTestUtil.getPlatformTestDataPath()}plugins/pluginDescriptor"
|
||||
|
||||
private fun loadDescriptorInTest(dirName: String, disabledPlugins: Set<PluginId> = emptySet()): IdeaPluginDescriptorImpl {
|
||||
return loadDescriptorInTest(Paths.get(testDataPath, dirName), disabledPlugins)
|
||||
return loadDescriptorInTest(Path.of(testDataPath, dirName), disabledPlugins)
|
||||
}
|
||||
@@ -64,12 +64,10 @@ internal fun doLoadApp(setupEventQueue: () -> Unit) {
|
||||
val preloadServiceFuture = preloadServices(plugins, app, activityPrefix = "")
|
||||
app.loadComponents(null)
|
||||
|
||||
preloadServiceFuture
|
||||
.thenRun { ForkJoinTask.invokeAll(callAppInitialized(app)) }
|
||||
.get(40, TimeUnit.SECONDS)
|
||||
preloadServiceFuture.get(40, TimeUnit.SECONDS)
|
||||
ForkJoinTask.invokeAll(callAppInitialized(app))
|
||||
|
||||
(PersistentFS.getInstance() as PersistentFSImpl).cleanPersistedContents()
|
||||
|
||||
}
|
||||
catch (e: TimeoutException) {
|
||||
throw RuntimeException("Cannot preload services in 40 seconds: ${ThreadDumper.dumpThreadsToString()}", e)
|
||||
|
||||
Reference in New Issue
Block a user