Java tutorial
/* * 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.openapi.updateSettings.impl.pluginsAdvertisement; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.ide.plugins.RepositoryHelper; import com.intellij.notification.*; import com.intellij.openapi.application.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.fileTypes.FileTypeFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; import com.intellij.openapi.updateSettings.impl.PluginDownloader; import com.intellij.openapi.updateSettings.impl.UpdateSettings; import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.xmlb.XmlSerializer; import com.intellij.util.xmlb.annotations.MapAnnotation; import com.intellij.util.xmlb.annotations.Tag; import org.jdom.Document; import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.util.*; public class PluginsAdvertiser implements StartupActivity { private static final Logger LOG = Logger.getInstance("#" + PluginsAdvertiser.class.getName()); private static final String FEATURE_IMPLEMENTATIONS_URL = "http://must-be.org/consulo/plugins/feature/getImplementations?"; private static final String CASHED_EXTENSIONS = "extensions.xml"; public static List<PluginId> retrieve(UnknownFeature unknownFeature) { final String featureType = unknownFeature.getFeatureType(); final String implementationName = unknownFeature.getImplementationName(); final String buildNumber = ApplicationInfo.getInstance().getBuild().asString(); final String pluginRepositoryUrl = FEATURE_IMPLEMENTATIONS_URL + "featureType=" + featureType + "&implementationName=" + implementationName.replaceAll("#", "%23") + "&build=" + buildNumber; try { HttpURLConnection connection = HttpConfigurable.getInstance().openHttpConnection(pluginRepositoryUrl); connection.connect(); final InputStreamReader streamReader = new InputStreamReader(connection.getInputStream()); try { final JsonReader jsonReader = new JsonReader(streamReader); jsonReader.setLenient(true); final JsonElement jsonRootElement = new JsonParser().parse(jsonReader); final List<PluginId> result = new ArrayList<PluginId>(); for (JsonElement jsonElement : jsonRootElement.getAsJsonArray()) { final JsonObject jsonObject = jsonElement.getAsJsonObject(); final JsonElement pluginId = jsonObject.get("pluginId"); result.add(PluginId.getId(StringUtil.unquoteString(pluginId.toString()))); } return result; } finally { streamReader.close(); } } catch (IOException e) { LOG.info(e); return null; } } private static Map<String, Set<PluginId>> loadSupportedExtensions() { final String pluginRepositoryUrl = FEATURE_IMPLEMENTATIONS_URL + "featureType=" + FileTypeFactory.FILE_TYPE_FACTORY_EP.getName(); try { HttpURLConnection connection = HttpConfigurable.getInstance().openHttpConnection(pluginRepositoryUrl); connection.connect(); final InputStreamReader streamReader = new InputStreamReader(connection.getInputStream()); try { final JsonReader jsonReader = new JsonReader(streamReader); jsonReader.setLenient(true); final JsonElement jsonRootElement = new JsonParser().parse(jsonReader); final Map<String, Set<PluginId>> result = new HashMap<String, Set<PluginId>>(); for (JsonElement jsonElement : jsonRootElement.getAsJsonArray()) { final JsonObject jsonObject = jsonElement.getAsJsonObject(); final JsonElement ext = jsonObject.get("implementationName"); final String extension = StringUtil.unquoteString(ext.toString()); Set<PluginId> pluginIds = result.get(extension); if (pluginIds == null) { pluginIds = new HashSet<PluginId>(); result.put(extension, pluginIds); } pluginIds.add(PluginId.getId(StringUtil.unquoteString(jsonObject.get("pluginId").toString()))); } saveExtensions(result); return result; } finally { streamReader.close(); } } catch (IOException e) { LOG.info(e); return null; } } public static KnownExtensions loadExtensions() { try { File file = new File(PathManager.getPluginsPath(), CASHED_EXTENSIONS); if (file.isFile()) { final Document document = JDOMUtil.loadDocument(file); return XmlSerializer.deserialize(document, KnownExtensions.class); } } catch (Exception ignore) { } return null; } private static void saveExtensions(Map<String, Set<PluginId>> extensions) throws IOException { File plugins = new File(PathManager.getPluginsPath(), CASHED_EXTENSIONS); if (!plugins.isFile()) { FileUtil.ensureCanCreateFile(plugins); } plugins.deleteOnExit(); JDOMUtil.writeDocument(new Document(XmlSerializer.serialize(new KnownExtensions(extensions))), plugins, "\n"); } @Override public void runActivity(@NotNull final Project project) { if (!UpdateSettings.getInstance().isCheckNeeded()) return; final UnknownFeaturesCollector collectorSuggester = UnknownFeaturesCollector.getInstance(project); final Set<UnknownFeature> unknownFeatures = collectorSuggester.getUnknownFeatures(); final KnownExtensions extensions = loadExtensions(); if (extensions != null && unknownFeatures.isEmpty()) return; final Runnable runnable = new Runnable() { @Override public void run() { final Application application = ApplicationManager.getApplication(); if (application.isUnitTestMode() || application.isHeadlessEnvironment()) return; ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { private final Set<Couple<IdeaPluginDescriptor>> myPlugins = new HashSet<Couple<IdeaPluginDescriptor>>(); private List<IdeaPluginDescriptor> myAllPlugins; @Override public void run() { if (extensions == null) { loadSupportedExtensions(); } final Set<PluginId> ids = new HashSet<PluginId>(); for (UnknownFeature feature : unknownFeatures) { final List<PluginId> pluginId = retrieve(feature); if (pluginId != null) { //do not suggest to download disabled plugins final List<String> disabledPlugins = PluginManagerCore.getDisabledPlugins(); for (PluginId id : pluginId) { if (!disabledPlugins.contains(id.getIdString())) { ids.add(id); } } } } try { myAllPlugins = RepositoryHelper.loadPluginsFromRepository(null); for (IdeaPluginDescriptor loadedPlugin : myAllPlugins) { if (ids.contains(loadedPlugin.getPluginId())) { myPlugins.add(Couple.of(null, loadedPlugin)); } } ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { onSuccess(); } }, ModalityState.NON_MODAL); } catch (Exception ignore) { //no notification to show } } public void onSuccess() { if (!myPlugins.isEmpty()) { final String displayId = "Plugins Suggestion"; new NotificationGroup(displayId, NotificationDisplayType.STICKY_BALLOON, true) .createNotification(displayId, "Features covered by non-bundled plugins are detected.<br>" + "<a href=\"configure\">Configure plugins...</a><br>" + "<a href=\"ignore\">Ignore All</a>", NotificationType.INFORMATION, new NotificationListener() { @Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { if (event .getEventType() == HyperlinkEvent.EventType.ACTIVATED) { final String description = event.getDescription(); if ("ignore".equals(description)) { for (UnknownFeature feature : unknownFeatures) { collectorSuggester.ignoreFeature(feature); } notification.expire(); } else if ("configure".equals(description)) { LOG.assertTrue(myAllPlugins != null); notification.expire(); new PluginsAdvertiserDialog(project, myPlugins, myAllPlugins).show(); } } } }) .notify(project); } } }); } }; SwingUtilities.invokeLater(runnable); } @Tag("exts") public static class KnownExtensions { @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false) public Map<String, PluginSet> myExtensions = new HashMap<String, PluginSet>(); public KnownExtensions() { } public KnownExtensions(Map<String, Set<PluginId>> extensions) { for (String ext : extensions.keySet()) { myExtensions.put(ext, new PluginSet(extensions.get(ext))); } } public Set<String> find(String extension) { final PluginSet pluginSet = myExtensions.get(extension); if (pluginSet != null) { return pluginSet.myPlugins; } return null; } } @Tag("plugins") public static class PluginSet { public Set<String> myPlugins = new HashSet<String>(); public PluginSet() { } public PluginSet(Set<PluginId> plugins) { for (PluginId plugin : plugins) { myPlugins.add(plugin.toString()); } } } }