diff options
Diffstat (limited to 'platform/core-impl/src/com/intellij/ide')
3 files changed, 154 insertions, 26 deletions
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java index 3094304a02cb..a6b957c0c508 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java @@ -15,7 +15,6 @@ */ package com.intellij.ide.plugins; -import com.intellij.ide.IdeBundle; import com.intellij.openapi.extensions.PluginId; import com.intellij.util.containers.HashMap; import gnu.trove.TObjectIntHashMap; @@ -32,7 +31,7 @@ public class PluginDescriptorComparator implements Comparator<IdeaPluginDescript private final TObjectIntHashMap<PluginId> myIdToNumberMap = new TObjectIntHashMap<PluginId>(); private int myAvailableNumber = 1; - public PluginDescriptorComparator(IdeaPluginDescriptor[] descriptors) throws Exception{ + public PluginDescriptorComparator(IdeaPluginDescriptor[] descriptors){ final Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap = new HashMap<PluginId, IdeaPluginDescriptor>(); for (final IdeaPluginDescriptor descriptor : descriptors) { idToDescriptorMap.put(descriptor.getPluginId(), descriptor); @@ -46,18 +45,20 @@ public class PluginDescriptorComparator implements Comparator<IdeaPluginDescript } } - private void assignNumbers(PluginId id, Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap, Stack<PluginId> visited) throws Exception { + private void assignNumbers(PluginId id, Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap, Stack<PluginId> visited){ visited.push(id); try { final IdeaPluginDescriptor ideaPluginDescriptor = idToDescriptorMap.get(id); - if (ideaPluginDescriptor == null) { - // missing optional dependency + if (ideaPluginDescriptor == null || !ideaPluginDescriptor.isEnabled()) { + // missing optional dependency or already disabled due to cycles return; } final PluginId[] parentIds = ideaPluginDescriptor.getDependentPluginIds(); for (final PluginId parentId : parentIds) { if (visited.contains(parentId)) { - throw new Exception(IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + id + "->" + parentId + "->...->" + id); + //disable plugins in the cycle + ideaPluginDescriptor.setEnabled(false); + break; } } for (PluginId parentId1 : parentIds) { diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java index cf2d45ad4945..8f4fd771ebdd 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java @@ -25,10 +25,7 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ExtensionAreas; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.*; -import com.intellij.openapi.util.BuildNumber; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.io.ZipFileCache; @@ -479,8 +476,10 @@ public class PluginManagerCore { } static void prepareLoadingPluginsErrorMessage(final String errorMessage) { - if (errorMessage != null) { - if (!ApplicationManager.getApplication().isHeadlessEnvironment() && !ApplicationManager.getApplication().isUnitTestMode()) { + if (!StringUtil.isEmptyOrSpaces(errorMessage)) { + if (ApplicationManager.getApplication() != null + && !ApplicationManager.getApplication().isHeadlessEnvironment() + && !ApplicationManager.getApplication().isUnitTestMode()) { if (myPluginError == null) { myPluginError = errorMessage; } @@ -499,6 +498,7 @@ public class PluginManagerCore { } } + @Deprecated static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) { final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap); final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph); @@ -549,6 +549,7 @@ public class PluginManagerCore { })); } + @Deprecated static IdeaPluginDescriptorImpl[] findCorePlugin(IdeaPluginDescriptorImpl[] pluginDescriptors) { for (IdeaPluginDescriptorImpl descriptor : pluginDescriptors) { if (CORE_PLUGIN_ID.equals(descriptor.getPluginId().getIdString())) { @@ -820,7 +821,7 @@ public class PluginManagerCore { message.insert(0, IdeBundle.message("error.problems.found.loading.plugins")); return message.toString(); } - return null; + return ""; } static void loadDescriptorsFromClassPath(@NotNull List<IdeaPluginDescriptorImpl> result, @Nullable StartupProgress progress) { @@ -900,14 +901,7 @@ public class PluginManagerCore { loadDescriptorsFromClassPath(result, fromSources ? progress : null); IdeaPluginDescriptorImpl[] pluginDescriptors = result.toArray(new IdeaPluginDescriptorImpl[result.size()]); - try { - Arrays.sort(pluginDescriptors, new PluginDescriptorComparator(pluginDescriptors)); - } - catch (Exception e) { - prepareLoadingPluginsErrorMessage(IdeBundle.message("error.plugins.were.not.loaded", e.getMessage())); - getLogger().info(e); - return findCorePlugin(pluginDescriptors); - } + Arrays.sort(pluginDescriptors, new PluginDescriptorComparator(pluginDescriptors)); return pluginDescriptors; } @@ -1090,12 +1084,13 @@ public class PluginManagerCore { String errorMessage = filterBadPlugins(result, disabledPluginNames); if (!brokenPluginsList.isEmpty()) { - errorMessage = "Following plugins are incompatible with current IDE build: " + StringUtil.join(brokenPluginsList, ", ") - + "<br>\n" + StringUtil.notNullize(errorMessage); + if (!StringUtil.isEmptyOrSpaces(errorMessage)) { + errorMessage += "<br>"; + } + errorMessage += "Following plugins are incompatible with current IDE build: " + StringUtil.join(brokenPluginsList, ", ") + + "<br>\n" + StringUtil.notNullize(errorMessage); } - prepareLoadingPluginsErrorMessage(errorMessage); - final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap = new HashMap<PluginId, IdeaPluginDescriptorImpl>(); for (final IdeaPluginDescriptorImpl descriptor : result) { idToDescriptorMap.put(descriptor.getPluginId(), descriptor); @@ -1112,8 +1107,28 @@ public class PluginManagerCore { mergeOptionalConfigs(idToDescriptorMap); addModulesAsDependents(idToDescriptorMap); + final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap); + final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph); + if (!builder.isAcyclic()) { + final Couple<PluginId> circularDependency = builder.getCircularDependency(); + final PluginId id = circularDependency.getFirst(); + final PluginId parentId = circularDependency.getSecond(); + if (!StringUtil.isEmptyOrSpaces(errorMessage)) { + errorMessage += "<br>"; + } + errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + id + "->" + parentId + "->...->" + id; + } + + prepareLoadingPluginsErrorMessage(errorMessage); + + final Comparator<PluginId> idComparator = builder.comparator(); // sort descriptors according to plugin dependencies - Collections.sort(result, getPluginDescriptorComparator(idToDescriptorMap)); + Collections.sort(result, new Comparator<IdeaPluginDescriptor>() { + @Override + public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) { + return idComparator.compare(o1.getPluginId(), o2.getPluginId()); + } + }); for (int i = 0; i < result.size(); i++) { ourId2Index.put(result.get(i).getPluginId(), i); diff --git a/platform/core-impl/src/com/intellij/ide/util/PropertiesComponentImpl.java b/platform/core-impl/src/com/intellij/ide/util/PropertiesComponentImpl.java new file mode 100644 index 000000000000..a743569b1798 --- /dev/null +++ b/platform/core-impl/src/com/intellij/ide/util/PropertiesComponentImpl.java @@ -0,0 +1,112 @@ +/* + * Copyright 2000-2013 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. + */ +package com.intellij.ide.util; + +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.util.text.StringUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class PropertiesComponentImpl extends PropertiesComponent implements PersistentStateComponent<Element> { + private final Map<String, String> myMap = new LinkedHashMap<String, String>(); + @NonNls private static final String ELEMENT_PROPERTY = "property"; + @NonNls private static final String ATTRIBUTE_NAME = "name"; + @NonNls private static final String ATTRIBUTE_VALUE = "value"; + + @NotNull + public String getComponentName() { + return "PropertiesComponent"; + } + + PropertiesComponentImpl() { + } + + @Override + public Element getState() { + Element parentNode = new Element("state"); + for (final String key : myMap.keySet()) { + String value = myMap.get(key); + if (value != null) { + Element element = new Element(ELEMENT_PROPERTY); + element.setAttribute(ATTRIBUTE_NAME, key); + element.setAttribute(ATTRIBUTE_VALUE, value); + parentNode.addContent(element); + } + } + return parentNode; + } + + @Override + public void loadState(final Element parentNode) { + myMap.clear(); + for (Element e : parentNode.getChildren(ELEMENT_PROPERTY)) { + String name = e.getAttributeValue(ATTRIBUTE_NAME); + if (name != null) { + myMap.put(name, e.getAttributeValue(ATTRIBUTE_VALUE)); + } + } + } + + @Override + public String getValue(String name) { + return myMap.get(name); + } + + @Override + public void setValue(String name, String value) { + myMap.put(name, value); + } + + @Override + public void setValue(@NotNull String name, @NotNull String value, @NotNull String defaultValue) { + if (value.equals(defaultValue)) { + myMap.remove(name); + } + else { + myMap.put(name, value); + } + } + + @Override + public void unsetValue(String name) { + myMap.remove(name); + } + + @Override + public boolean isValueSet(String name) { + return myMap.containsKey(name); + } + + @Override + public String[] getValues(@NonNls String name) { + final String value = getValue(name); + return value != null ? value.split("\n") : null; + } + + @Override + public void setValues(@NonNls String name, String[] values) { + if (values == null) { + setValue(name, null); + } + else { + setValue(name, StringUtil.join(values, "\n")); + } + } +}
\ No newline at end of file |