public void registerExtension( final PluginDescriptor pluginDescriptor, final Element extensionElement) { final PluginId pluginId = pluginDescriptor.getPluginId(); String epName = extractEPName(extensionElement); ExtensionComponentAdapter adapter; final PicoContainer container = getPluginContainer(pluginId.getIdString()); final ExtensionPoint extensionPoint = getExtensionPoint(epName); if (extensionPoint.getKind() == ExtensionPoint.Kind.INTERFACE) { String implClass = extensionElement.getAttributeValue("implementation"); if (implClass == null) { throw new RuntimeException( "'implementation' attribute not specified for '" + epName + "' extension in '" + pluginId.getIdString() + "' plugin"); } adapter = new ExtensionComponentAdapter( implClass, extensionElement, container, pluginDescriptor, shouldDeserializeInstance(extensionElement)); } else { adapter = new ExtensionComponentAdapter( extensionPoint.getClassName(), extensionElement, container, pluginDescriptor, true); } myExtensionElement2extension.put(extensionElement, adapter); internalGetPluginContainer().registerComponent(adapter); getExtensionPoint(epName).registerExtensionAdapter(adapter); }
private List<String> getNonOptionalDependencies(final String id) { List<String> result = new ArrayList<String>(); IdeaPluginDescriptor descriptor = findPlugin(id); if (descriptor != null) { for (PluginId pluginId : descriptor.getDependentPluginIds()) { if (pluginId.getIdString().equals("com.intellij")) continue; if (!ArrayUtil.contains(pluginId, descriptor.getOptionalDependentPluginIds())) { result.add(pluginId.getIdString()); } } } return result; }
public static boolean hasNewerVersion(PluginId descr) { return !wasUpdated(descr) && (NewVersions2Plugins.containsKey(descr) || PluginManagerUISettings.getInstance() .myOutdatedPlugins .contains(descr.getIdString())); }
private static void updateExistingPluginInfo( IdeaPluginDescriptor descr, IdeaPluginDescriptor existing) { int state = StringUtil.compareVersionNumbers(descr.getVersion(), existing.getVersion()); final PluginId pluginId = existing.getPluginId(); final String idString = pluginId.getIdString(); final JDOMExternalizableStringList installedPlugins = PluginManagerUISettings.getInstance().getInstalledPlugins(); if (!installedPlugins.contains(idString) && !((IdeaPluginDescriptorImpl) existing).isDeleted()) { installedPlugins.add(idString); } final PluginManagerUISettings updateSettings = PluginManagerUISettings.getInstance(); if (state > 0 && !PluginManager.isIncompatible(descr) && !updatedPlugins.contains(descr.getPluginId())) { NewVersions2Plugins.put(pluginId, 1); if (!updateSettings.myOutdatedPlugins.contains(idString)) { updateSettings.myOutdatedPlugins.add(idString); } final IdeaPluginDescriptorImpl plugin = (IdeaPluginDescriptorImpl) existing; plugin.setDownloadsCount(descr.getDownloads()); plugin.setVendor(descr.getVendor()); plugin.setVendorEmail(descr.getVendorEmail()); plugin.setVendorUrl(descr.getVendorUrl()); plugin.setUrl(descr.getUrl()); } else { updateSettings.myOutdatedPlugins.remove(idString); if (NewVersions2Plugins.remove(pluginId) != null) { updatedPlugins.add(pluginId); } } }
@Override public boolean isBundled() { if (PluginManagerCore.CORE_PLUGIN_ID.equals(myId.getIdString())) { return true; } String path; try { // to avoid paths like this /home/kb/IDEA/bin/../config/plugins/APlugin path = getPath().getCanonicalPath(); } catch (IOException e) { path = getPath().getAbsolutePath(); } Application app = ApplicationManager.getApplication(); if (app != null && app.isInternal()) { if (path.startsWith( PathManager.getHomePath() + File.separator + "out" + File.separator + "classes")) { return true; } if (app.isUnitTestMode() && !path.startsWith(PathManager.getPluginsPath() + File.separatorChar)) { return true; } } return path.startsWith(PathManager.getPreInstalledPluginsPath()); }
private static boolean checkDependants( final IdeaPluginDescriptor pluginDescriptor, final Function<PluginId, IdeaPluginDescriptor> pluginId2Descriptor, final Condition<PluginId> check, final Set<PluginId> processed) { processed.add(pluginDescriptor.getPluginId()); final PluginId[] dependentPluginIds = pluginDescriptor.getDependentPluginIds(); final Set<PluginId> optionalDependencies = new HashSet<PluginId>(Arrays.asList(pluginDescriptor.getOptionalDependentPluginIds())); for (final PluginId dependentPluginId : dependentPluginIds) { if (processed.contains(dependentPluginId)) continue; // TODO[yole] should this condition be a parameter? if (isModuleDependency(dependentPluginId) && (ourAvailableModules.isEmpty() || ourAvailableModules.contains(dependentPluginId.getIdString()))) { continue; } if (!optionalDependencies.contains(dependentPluginId)) { if (!check.value(dependentPluginId)) { return false; } final IdeaPluginDescriptor dependantPluginDescriptor = pluginId2Descriptor.fun(dependentPluginId); if (dependantPluginDescriptor != null && !checkDependants(dependantPluginDescriptor, pluginId2Descriptor, check, processed)) { return false; } } } return true; }
public static void handleComponentError( Throwable t, @Nullable String componentClassName, @Nullable ComponentConfig config) { if (t instanceof StartupAbortedException) { throw (StartupAbortedException) t; } PluginId pluginId = null; if (config != null) { pluginId = config.getPluginId(); } if (pluginId == null || CORE_PLUGIN_ID.equals(pluginId.getIdString())) { if (componentClassName != null) { pluginId = getPluginByClassName(componentClassName); } } if (pluginId == null || CORE_PLUGIN_ID.equals(pluginId.getIdString())) { if (t instanceof PicoPluginExtensionInitializationException) { pluginId = ((PicoPluginExtensionInitializationException) t).getPluginId(); } } if (pluginId != null && !CORE_PLUGIN_ID.equals(pluginId.getIdString())) { getLogger().warn(t); disablePlugin(pluginId.getIdString()); StringWriter message = new StringWriter(); message .append("Plugin '") .append(pluginId.getIdString()) .append("' failed to initialize and will be disabled. "); message .append(" Please restart ") .append(ApplicationNamesInfo.getInstance().getFullProductName()) .append('.'); message.append("\n\n"); t.printStackTrace(new PrintWriter(message)); Main.showMessage("Plugin Error", message.toString(), false); throw new StartupAbortedException(t).exitCode(Main.PLUGIN_ERROR).logError(false); } else { throw new StartupAbortedException("Fatal error initializing '" + componentClassName + "'", t); } }
@Override protected void handleInitComponentError( final Throwable ex, final boolean fatal, final String componentClassName) { if (PluginManager.isPluginClass(componentClassName)) { LOG.error(ex); PluginId pluginId = PluginManager.getPluginByClassName(componentClassName); @NonNls final String errorMessage = "Plugin " + pluginId.getIdString() + " failed to initialize and will be disabled:\n" + ex.getMessage() + "\nPlease restart " + ApplicationNamesInfo.getInstance().getFullProductName() + "."; PluginManager.disablePlugin(pluginId.getIdString()); if (!myHeadlessMode) { JOptionPane.showMessageDialog(null, errorMessage); } else { //noinspection UseOfSystemOutOrSystemErr System.out.println(errorMessage); System.exit(1); } return; // do not call super } if (fatal) { LOG.error(ex); @NonNls final String errorMessage = "Fatal error initializing class " + componentClassName + ":\n" + ex.toString() + "\nComplete error stacktrace was written to idea.log"; if (!myHeadlessMode) { JOptionPane.showMessageDialog(null, errorMessage); } else { //noinspection UseOfSystemOutOrSystemErr System.out.println(errorMessage); } } super.handleInitComponentError(ex, fatal, componentClassName); }
@Nullable IdeaPluginDescriptor findPlugin(String id) { for (IdeaPluginDescriptor pluginDescriptor : myAllPlugins) { PluginId pluginId = pluginDescriptor.getPluginId(); if (pluginId != null && StringUtil.equals(pluginId.getIdString(), id)) { return pluginDescriptor; } } return null; }
/** Should be called whenever a new plugin is installed or an existing one is updated. */ public void onPluginInstall(@NotNull IdeaPluginDescriptor descriptor) { PluginId id = descriptor.getPluginId(); boolean existing = PluginManager.isPluginInstalled(id); synchronized (myLock) { myOutdatedPlugins.remove(id.getIdString()); if (existing) { myUpdatedPlugins.put(id, descriptor); } else { myInstalledPlugins.put(id, descriptor); } } }
/** * Should be called whenever a list of plugins is loaded from a repository to check if there is an * updated version. */ public void onDescriptorDownload(@NotNull IdeaPluginDescriptor descriptor) { PluginId id = descriptor.getPluginId(); IdeaPluginDescriptor existing = PluginManager.getPlugin(id); if (existing == null || (existing.isBundled() && !existing.allowBundledUpdate()) || wasUpdated(id)) { return; } boolean supersedes = !PluginManagerCore.isIncompatible(descriptor) && (PluginDownloader.compareVersionsSkipBroken(existing, descriptor.getVersion()) > 0 || PluginManagerCore.isIncompatible(existing)); String idString = id.getIdString(); synchronized (myLock) { if (supersedes) { myOutdatedPlugins.add(idString); } else { myOutdatedPlugins.remove(idString); } } }
public static boolean isModuleDependency(final PluginId dependentPluginId) { return dependentPluginId.getIdString().startsWith(MODULE_DEPENDENCY_PREFIX); }
@Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final Component orig = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (myPluginDescriptor != null) { myNameLabel.setText(myPluginDescriptor.getName()); final PluginId pluginId = myPluginDescriptor.getPluginId(); final String idString = pluginId.getIdString(); if (myPluginDescriptor.isBundled()) { myBundledLabel.setText("Bundled"); } else { final String host = myPlugin2host.get(idString); if (host != null) { String presentableUrl = VfsUtil.urlToPath(host); final int idx = presentableUrl.indexOf('/'); if (idx > -1) { presentableUrl = presentableUrl.substring(0, idx); } myBundledLabel.setText("From " + presentableUrl); } else { if (PluginManagerUISettings.getInstance().getInstalledPlugins().contains(idString)) { myBundledLabel.setText("From repository"); } else { myBundledLabel.setText("Custom"); } } } if (myPluginDescriptor instanceof IdeaPluginDescriptorImpl && ((IdeaPluginDescriptorImpl) myPluginDescriptor).isDeleted()) { myNameLabel.setIcon(AllIcons.Actions.Clean); } else if (hasNewerVersion(pluginId)) { myNameLabel.setIcon(AllIcons.Nodes.Pluginobsolete); myPanel.setToolTipText("Newer version of the plugin is available"); } else { myNameLabel.setIcon(AllIcons.Nodes.Plugin); } final Color fg = orig.getForeground(); final Color bg = orig.getBackground(); final Color grayedFg = isSelected ? fg : Color.GRAY; myPanel.setBackground(bg); myNameLabel.setBackground(bg); myBundledLabel.setBackground(bg); myNameLabel.setForeground(fg); final boolean wasUpdated = wasUpdated(pluginId); if (wasUpdated || PluginManager.getPlugin(pluginId) == null) { if (!isSelected) { myNameLabel.setForeground(FileStatus.COLOR_ADDED); } if (wasUpdated) { myPanel.setToolTipText( "Plugin was updated to the newest version. Changes will be available after restart"); } else { myPanel.setToolTipText("Plugin will be activated after restart."); } } myBundledLabel.setForeground(grayedFg); final Set<PluginId> required = myDependentToRequiredListMap.get(pluginId); if (required != null && required.size() > 0) { myNameLabel.setForeground(Color.RED); final StringBuilder s = new StringBuilder(); if (myEnabled.get(pluginId) == null) { s.append("Plugin was not loaded.\n"); } if (required.contains(PluginId.getId("com.intellij.modules.ultimate"))) { s.append("The plugin requires IntelliJ IDEA Ultimate"); } else { s.append("Required plugin").append(required.size() == 1 ? " \"" : "s \""); s.append( StringUtil.join( required, new Function<PluginId, String>() { @Override public String fun(final PluginId id) { final IdeaPluginDescriptor plugin = PluginManager.getPlugin(id); return plugin == null ? id.getIdString() : plugin.getName(); } }, ",")); s.append(required.size() == 1 ? "\" is not enabled!" : "\" are not enabled!"); } myPanel.setToolTipText(s.toString()); } if (PluginManager.isIncompatible(myPluginDescriptor)) { myPanel.setToolTipText( IdeBundle.message( "plugin.manager.incompatible.tooltip.warning", ApplicationNamesInfo.getInstance().getFullProductName())); myNameLabel.setForeground(Color.red); } } return myPanel; }
private static boolean prepareToInstall( final PluginNode pluginNode, final List<PluginId> pluginIds, List<IdeaPluginDescriptor> allPlugins) throws IOException { // check for dependent plugins at first. if (pluginNode.getDepends() != null && pluginNode.getDepends().size() > 0) { // prepare plugins list for install final PluginId[] optionalDependentPluginIds = pluginNode.getOptionalDependentPluginIds(); final List<PluginNode> depends = new ArrayList<PluginNode>(); final List<PluginNode> optionalDeps = new ArrayList<PluginNode>(); for (int i = 0; i < pluginNode.getDepends().size(); i++) { PluginId depPluginId = pluginNode.getDepends().get(i); if (PluginManager.isPluginInstalled(depPluginId) || PluginManager.isModuleDependency(depPluginId) || (pluginIds != null && pluginIds.contains(depPluginId))) { // ignore installed or installing plugins continue; } PluginNode depPlugin = new PluginNode(depPluginId); depPlugin.setSize("-1"); depPlugin.setName(depPluginId.getIdString()); // prevent from exceptions if (optionalDependentPluginIds != null && ArrayUtil.indexOf(optionalDependentPluginIds, depPluginId) != -1) { if (isPluginInRepo(depPluginId, allPlugins)) { optionalDeps.add(depPlugin); } } else { depends.add(depPlugin); } } if (depends.size() > 0) { // has something to install prior installing the plugin final boolean[] proceed = new boolean[1]; final StringBuffer buf = new StringBuffer(); for (PluginNode depend : depends) { buf.append(depend.getName()).append(","); } try { GuiUtils.runOrInvokeAndWait( new Runnable() { public void run() { proceed[0] = Messages.showYesNoDialog( IdeBundle.message( "plugin.manager.dependencies.detected.message", depends.size(), buf.substring(0, buf.length() - 1)), IdeBundle.message("plugin.manager.dependencies.detected.title"), Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE; } }); } catch (Exception e) { return false; } if (proceed[0]) { if (!prepareToInstall(depends, allPlugins)) { return false; } } else { return false; } } if (optionalDeps.size() > 0) { final StringBuffer buf = new StringBuffer(); for (PluginNode depend : optionalDeps) { buf.append(depend.getName()).append(","); } final boolean[] proceed = new boolean[1]; try { GuiUtils.runOrInvokeAndWait( new Runnable() { public void run() { proceed[0] = Messages.showYesNoDialog( IdeBundle.message( "plugin.manager.optional.dependencies.detected.message", optionalDeps.size(), buf.substring(0, buf.length() - 1)), IdeBundle.message("plugin.manager.dependencies.detected.title"), Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE; } }); } catch (Exception e) { return false; } if (proceed[0]) { if (!prepareToInstall(optionalDeps, allPlugins)) { return false; } } } } synchronized (PluginManager.lock) { final PluginDownloader downloader = PluginDownloader.createDownloader(pluginNode); if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) { downloader.install(); pluginNode.setStatus(PluginNode.STATUS_DOWNLOADED); } else { return false; } } return true; }
public boolean hasNewerVersion(@NotNull PluginId id) { synchronized (myLock) { return !wasUpdated(id) && myOutdatedPlugins.contains(id.getIdString()); } }
@Nullable static String filterBadPlugins( List<? extends IdeaPluginDescriptor> result, final Map<String, String> disabledPluginNames) { final Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap = new HashMap<PluginId, IdeaPluginDescriptor>(); final StringBuffer message = new StringBuffer(); boolean pluginsWithoutIdFound = false; for (Iterator<? extends IdeaPluginDescriptor> it = result.iterator(); it.hasNext(); ) { final IdeaPluginDescriptor descriptor = it.next(); final PluginId id = descriptor.getPluginId(); if (id == null) { pluginsWithoutIdFound = true; } if (idToDescriptorMap.containsKey(id)) { message.append("<br>"); message.append(IdeBundle.message("message.duplicate.plugin.id")); message.append(id); it.remove(); } else if (descriptor.isEnabled()) { idToDescriptorMap.put(id, descriptor); } } addModulesAsDependents(idToDescriptorMap); final List<String> disabledPluginIds = new ArrayList<String>(); final LinkedHashSet<String> faultyDescriptors = new LinkedHashSet<String>(); for (final Iterator<? extends IdeaPluginDescriptor> it = result.iterator(); it.hasNext(); ) { final IdeaPluginDescriptor pluginDescriptor = it.next(); checkDependants( pluginDescriptor, new Function<PluginId, IdeaPluginDescriptor>() { @Override public IdeaPluginDescriptor fun(final PluginId pluginId) { return idToDescriptorMap.get(pluginId); } }, new Condition<PluginId>() { @Override public boolean value(final PluginId pluginId) { if (!idToDescriptorMap.containsKey(pluginId)) { pluginDescriptor.setEnabled(false); if (!pluginId.getIdString().startsWith(MODULE_DEPENDENCY_PREFIX)) { faultyDescriptors.add(pluginId.getIdString()); disabledPluginIds.add(pluginDescriptor.getPluginId().getIdString()); message.append("<br>"); final String name = pluginDescriptor.getName(); final IdeaPluginDescriptor descriptor = idToDescriptorMap.get(pluginId); String pluginName; if (descriptor == null) { pluginName = pluginId.getIdString(); if (disabledPluginNames.containsKey(pluginName)) { pluginName = disabledPluginNames.get(pluginName); } } else { pluginName = descriptor.getName(); } message.append( getDisabledPlugins().contains(pluginId.getIdString()) ? IdeBundle.message("error.required.plugin.disabled", name, pluginName) : IdeBundle.message( "error.required.plugin.not.installed", name, pluginName)); } it.remove(); return false; } return true; } }); } if (!disabledPluginIds.isEmpty()) { myPlugins2Disable = disabledPluginIds; myPlugins2Enable = faultyDescriptors; message.append("<br>"); message.append("<br>").append("<a href=\"" + DISABLE + "\">Disable "); if (disabledPluginIds.size() == 1) { final PluginId pluginId2Disable = PluginId.getId(disabledPluginIds.iterator().next()); message.append( idToDescriptorMap.containsKey(pluginId2Disable) ? idToDescriptorMap.get(pluginId2Disable).getName() : pluginId2Disable.getIdString()); } else { message.append("not loaded plugins"); } message.append("</a>"); boolean possibleToEnable = true; for (String descriptor : faultyDescriptors) { if (disabledPluginNames.get(descriptor) == null) { possibleToEnable = false; break; } } if (possibleToEnable) { message .append("<br>") .append("<a href=\"" + ENABLE + "\">Enable ") .append( faultyDescriptors.size() == 1 ? disabledPluginNames.get(faultyDescriptors.iterator().next()) : " all necessary plugins") .append("</a>"); } message.append("<br>").append("<a href=\"" + EDIT + "\">Open plugin manager</a>"); } if (pluginsWithoutIdFound) { message.append("<br>"); message.append(IdeBundle.message("error.plugins.without.id.found")); } if (message.length() > 0) { message.insert(0, IdeBundle.message("error.problems.found.loading.plugins")); return message.toString(); } return null; }
/** * @deprecated if more settings are needed for this plugin, you should create a {@link * com.intellij.openapi.components.PersistentStateComponent} and store all the settings in a * separate file without the prefix on the property name. */ @Deprecated private static String getSettingsPrefix() { PluginId pluginId = PluginManager.getPluginByClassName(MTTheme.class.getName()); return pluginId == null ? "com.chrisrm.idea.MaterialThemeUI" : pluginId.getIdString(); }