When enabling a disabled plugin, reload its descriptor with XInclude resolving to check if it can be enabled on the fly

GitOrigin-RevId: fed8b940fb6e5023ef3852732c012bacf5a904f2
This commit is contained in:
Dmitry Jemerov
2019-08-12 16:06:12 +03:00
committed by intellij-monorepo-bot
parent c25b336043
commit fa367b5b8b
4 changed files with 42 additions and 20 deletions
@@ -135,21 +135,32 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor {
public void readExternal(@NotNull Element element,
@NotNull URL url,
@NotNull JDOMXIncluder.PathResolver pathResolver,
@Nullable Interner<String> stringInterner) throws InvalidDataException, MalformedURLException {
@Nullable Interner<String> stringInterner,
boolean ignoreDisabled) throws InvalidDataException, MalformedURLException {
Application app = ApplicationManager.getApplication();
readExternal(element, url, app != null && app.isUnitTestMode(), pathResolver, stringInterner);
readExternal(element, url, app != null && app.isUnitTestMode(), pathResolver, stringInterner, ignoreDisabled);
}
public void loadFromFile(@NotNull File file, @Nullable SafeJdomFactory factory, boolean ignoreMissingInclude) throws IOException, JDOMException {
public void loadFromFile(@NotNull File file,
@Nullable SafeJdomFactory factory,
boolean ignoreMissingInclude) throws IOException, JDOMException {
loadFromFile(file, factory, ignoreMissingInclude, false);
}
public void loadFromFile(@NotNull File file,
@Nullable SafeJdomFactory factory,
boolean ignoreMissingInclude,
boolean ignoreDisabledPlugins) throws IOException, JDOMException {
readExternal(JDOMUtil.load(file, factory), file.toURI().toURL(), ignoreMissingInclude,
JDOMXIncluder.DEFAULT_PATH_RESOLVER, factory == null ? null : factory.stringInterner());
JDOMXIncluder.DEFAULT_PATH_RESOLVER, factory == null ? null : factory.stringInterner(), ignoreDisabledPlugins);
}
private void readExternal(@NotNull Element element,
@NotNull URL url,
boolean ignoreMissingInclude,
@NotNull JDOMXIncluder.PathResolver pathResolver,
@Nullable Interner<String> stringInterner) throws InvalidDataException, MalformedURLException {
@Nullable Interner<String> stringInterner,
boolean ignoreDisabledPlugins) throws InvalidDataException, MalformedURLException {
// root element always `!isIncludeElement` and it means that result always is a singleton list
// (also, plugin xml describes one plugin, this descriptor is not able to represent several plugins)
if (JDOMUtil.isEmpty(element)) {
@@ -158,7 +169,7 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor {
String pluginId = element.getChildTextTrim("id");
if (pluginId == null) pluginId = element.getChildTextTrim("name");
if (pluginId == null || !PluginManagerCore.disabledPlugins().contains(pluginId)) {
if (pluginId == null || !PluginManagerCore.disabledPlugins().contains(pluginId) || ignoreDisabledPlugins) {
JDOMXIncluder.resolveNonXIncludeElement(element, url, ignoreMissingInclude, pathResolver);
}
else if (LOG.isDebugEnabled()) {
@@ -761,7 +761,7 @@ public class PluginManagerCore {
try {
IdeaPluginDescriptorImpl descriptor = new IdeaPluginDescriptorImpl(notNull(pluginPath, file), loadingContext.isBundled);
descriptor.loadFromFile(descriptorFile, loadingContext.getXmlFactory(), isUnitTestMode);
descriptor.loadFromFile(descriptorFile, loadingContext.getXmlFactory(), isUnitTestMode, loadingContext.ignoreDisabled);
return descriptor;
}
catch (SerializationException | JDOMException | IOException e) {
@@ -792,7 +792,7 @@ public class PluginManagerCore {
IdeaPluginDescriptorImpl descriptor = new IdeaPluginDescriptorImpl(notNull(pluginPath, file), context.isBundled);
SafeJdomFactory factory = context.getXmlFactory();
Interner<String> interner = factory == null ? null : factory.stringInterner();
descriptor.readExternal(JDOMUtil.load(zipFile.getInputStream(entry), factory), jarURL, pathResolver, interner);
descriptor.readExternal(JDOMUtil.load(zipFile.getInputStream(entry), factory), jarURL, pathResolver, interner, context.ignoreDisabled);
context.lastZipWithDescriptor = file;
return descriptor;
}
@@ -812,7 +812,12 @@ public class PluginManagerCore {
@Nullable
public static IdeaPluginDescriptorImpl loadDescriptor(@NotNull File file, @NotNull String fileName) {
return loadDescriptor(file, fileName, false, false, null);
return loadDescriptor(file, fileName, false);
}
@Nullable
public static IdeaPluginDescriptorImpl loadDescriptor(@NotNull File file, @NotNull String fileName, boolean ignoreDisabled) {
return loadDescriptor(file, fileName, false, false, ignoreDisabled, null);
}
@Nullable
@@ -820,8 +825,9 @@ public class PluginManagerCore {
@NotNull String fileName,
boolean bundled,
boolean essential,
boolean ignoreDisabled,
@Nullable LoadDescriptorsContext parentContext) {
try (LoadingContext context = new LoadingContext(parentContext, bundled, essential)) {
try (LoadingContext context = new LoadingContext(parentContext, bundled, essential, ignoreDisabled)) {
return loadDescriptor(file, fileName, context);
}
}
@@ -831,15 +837,17 @@ public class PluginManagerCore {
final @Nullable LoadDescriptorsContext parentContext;
final boolean isBundled;
final boolean isEssential;
final boolean ignoreDisabled;
File lastZipWithDescriptor;
/**
* parentContext is null only for CoreApplicationEnvironment - it is not valid otherwise because in this case XML is not interned.
*/
LoadingContext(@Nullable LoadDescriptorsContext parentContext, boolean isBundled, boolean isEssential) {
LoadingContext(@Nullable LoadDescriptorsContext parentContext, boolean isBundled, boolean isEssential, boolean ignoreDisabled) {
this.parentContext = parentContext;
this.isBundled = isBundled;
this.isEssential = isEssential;
this.ignoreDisabled = ignoreDisabled;
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
@@ -945,7 +953,7 @@ public class PluginManagerCore {
// Note that this code is meant for IDE development / testing purposes
URL resource = PluginManagerCore.class.getClassLoader().getResource(META_INF + optPathName);
if (resource != null) {
optionalDescriptor = loadDescriptorFromResource(resource, optPathName, context.isBundled, false, context.parentContext);
optionalDescriptor = loadDescriptorFromResource(resource, optPathName, context.isBundled, false, context.ignoreDisabled, context.parentContext);
}
}
return optionalDescriptor;
@@ -1048,7 +1056,7 @@ public class PluginManagerCore {
Set<IdeaPluginDescriptorImpl> existingResults = new THashSet<>(result);
List<Future<IdeaPluginDescriptorImpl>> tasks = new ArrayList<>(files.length);
for (File file : files) {
tasks.add(context.getExecutorService().submit(() -> loadDescriptor(file, PLUGIN_XML, bundled, false, context)));
tasks.add(context.getExecutorService().submit(() -> loadDescriptor(file, PLUGIN_XML, bundled, false, false, context)));
}
for (Future<IdeaPluginDescriptorImpl> task : tasks) {
@@ -1178,7 +1186,7 @@ public class PluginManagerCore {
List<Future<IdeaPluginDescriptorImpl>> tasks = new ArrayList<>(urls.size());
for (Map.Entry<URL, String> entry : urls.entrySet()) {
URL url = entry.getKey();
tasks.add(context.getExecutorService().submit(() -> loadDescriptorFromResource(url, entry.getValue(), true, url.equals(platformPluginURL), context)));
tasks.add(context.getExecutorService().submit(() -> loadDescriptorFromResource(url, entry.getValue(), true, url.equals(platformPluginURL), false, context)));
}
// plugin projects may have the same plugins in plugin path (sandbox or SDK) and on the classpath; latter should be ignored
@@ -1223,18 +1231,19 @@ public class PluginManagerCore {
@NotNull String pathName,
boolean bundled,
boolean essential,
boolean ignoreDisabled,
@Nullable LoadDescriptorsContext parentContext) {
try {
if (URLUtil.FILE_PROTOCOL.equals(resource.getProtocol())) {
File descriptorFile = urlToFile(resource);
String pathname = StringUtil.trimEnd(FileUtil.toSystemIndependentName(descriptorFile.getPath()), pathName);
File pluginDir = new File(pathname).getParentFile();
return loadDescriptor(pluginDir, pathName, bundled, essential, parentContext);
return loadDescriptor(pluginDir, pathName, bundled, essential, ignoreDisabled, parentContext);
}
else if (URLUtil.JAR_PROTOCOL.equals(resource.getProtocol())) {
String path = resource.getFile();
File pluginJar = urlToFile(new URL(path.substring(0, path.indexOf(URLUtil.JAR_SEPARATOR))));
return loadDescriptor(pluginJar, pathName, bundled, essential, parentContext);
return loadDescriptor(pluginJar, pathName, bundled, essential, ignoreDisabled, parentContext);
}
}
catch (Throwable e) {
@@ -1265,7 +1274,7 @@ public class PluginManagerCore {
for (StringTokenizer t = new StringTokenizer(pathProperty, File.pathSeparator + ","); t.hasMoreTokens();) {
String s = t.nextToken();
IdeaPluginDescriptorImpl ideaPluginDescriptor = loadDescriptor(new File(s), PLUGIN_XML, false, false, context);
IdeaPluginDescriptorImpl ideaPluginDescriptor = loadDescriptor(new File(s), PLUGIN_XML, false, false, false, context);
if (ideaPluginDescriptor != null) {
result.add(ideaPluginDescriptor);
}
@@ -1659,7 +1668,7 @@ public class PluginManagerCore {
*/
public static void registerExtensionPointAndExtensions(@NotNull File pluginRoot, @NotNull String fileName, @NotNull ExtensionsArea area) {
IdeaPluginDescriptorImpl descriptor;
try (LoadingContext context = new LoadingContext(null, true, true)) {
try (LoadingContext context = new LoadingContext(null, true, true, false)) {
if (pluginRoot.isDirectory()) {
descriptor = loadDescriptorFromDir(pluginRoot, fileName, null, context);
}
@@ -1451,7 +1451,9 @@ public class PluginManagerConfigurableNewLayout
pluginDescriptorsToDisable.add(descriptor);
}
else {
pluginDescriptorsToEnable.add(descriptor);
// For disabled plugins, we do not resolve XInclude references and potentially do not load other parts of plugin.xml.
// To check if a plugin can be loaded without restart, we need to read the complete descriptor.
pluginDescriptorsToEnable.add(PluginManagerCore.loadDescriptor(descriptor.getPath(), PluginManagerCore.PLUGIN_XML, true));
}
}
descriptor.setEnabled(enabled);
@@ -45,7 +45,7 @@ public class UpdatePluginsFromCustomRepositoryTest extends BareTestFixtureTestCa
String path = PlatformTestUtil.getPlatformTestDataPath() + "updates/customRepositories/" + getTestName(true);
File descriptorFile = new File(path, filePath);
IdeaPluginDescriptorImpl descriptor = new IdeaPluginDescriptorImpl(descriptorFile.getParentFile(), false);
descriptor.loadFromFile(descriptorFile, null, true);
descriptor.loadFromFile(descriptorFile, null, true, true);
return descriptor;
}
}