/* * Copyright 2010-2015 Institut Pasteur. * * This file is part of Icy. * * Icy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Icy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Icy. If not, see <http://www.gnu.org/licenses/>. */ package plugins.kernel.searchprovider; import icy.gui.plugin.PluginDetailPanel; import icy.main.Icy; import icy.network.NetworkUtil; import icy.plugin.PluginDescriptor; import icy.plugin.PluginInstaller; import icy.plugin.PluginLauncher; import icy.plugin.PluginLoader; import icy.plugin.PluginRepositoryLoader; import icy.search.OnlineSearchResultProducer; import icy.search.SearchEngine; import icy.search.SearchResult; import icy.search.SearchResultConsumer; import icy.search.SearchResultProducer; import icy.system.thread.ThreadUtil; import icy.util.XMLUtil; import java.util.ArrayList; import java.util.List; import org.w3c.dom.Document; import org.w3c.dom.Element; import plugins.kernel.searchprovider.LocalPluginSearchResultProducer.LocalPluginResult; /** * This class is used to provide online plugin elements to the search engine. * * @author Stephane */ public class OnlinePluginSearchResultProducer extends OnlineSearchResultProducer { /** * @author Stephane */ public static class OnlinePluginResult extends PluginSearchResult { public OnlinePluginResult(SearchResultProducer provider, PluginDescriptor plugin, String text, String searchWords[], int priority) { super(provider, plugin, text, searchWords, priority); } @Override public String getTooltip() { return "Left click: Install and Run - Right click: Online documentation"; } @Override public void execute() { // can take sometime, better to execute it in background ThreadUtil.bgRun(new Runnable() { @Override public void run() { // plugin locally installed ? (result transfer to local plugin provider) if (PluginLoader.isLoaded(plugin.getClassName())) { if (plugin.isActionable()) PluginLauncher.start(plugin); else { ThreadUtil.invokeLater(new Runnable() { @Override public void run() { new PluginDetailPanel(plugin); } }); } } else { // install and run the plugin (if user ok with install) PluginInstaller.install(plugin, true); // wait for installation complete PluginInstaller.waitInstall(); // find the new installed plugin final PluginDescriptor localPlugin = PluginLoader.getPlugin(plugin.getClassName()); // plugin found ? if (localPlugin != null) { // launch it if actionable if (localPlugin.isActionable()) PluginLauncher.start(localPlugin); else { // just display info ThreadUtil.invokeLater(new Runnable() { @Override public void run() { new PluginDetailPanel(localPlugin); } }); } } } } }); } } private static final String ID_SEARCH_RESULT = "searchresult"; private static final String ID_PLUGIN = "plugin"; private static final String ID_CLASSNAME = "classname"; // private static final String ID_NAME = "name"; private static final String ID_TEXT = "string"; @Override public int getOrder() { // should be right after local plugin return 6; } @Override public String getName() { return "Online plugins"; } @Override public String getTooltipText() { return "Result(s) from online plugin"; } @Override public void doSearch(Document doc, String[] words, SearchResultConsumer consumer) { // Online plugin loader failed --> exit if (!ensureOnlineLoaderLoaded()) return; // no need to spent more time here... if (hasWaitingSearch()) return; // get online plugins final List<PluginDescriptor> onlinePlugins = PluginRepositoryLoader.getPlugins(); // get online result node final Element resultElement = XMLUtil.getElement(doc.getDocumentElement(), ID_SEARCH_RESULT); if (resultElement == null) return; // get the local plugin search provider from search engine final SearchEngine se = Icy.getMainInterface().getSearchEngine(); LocalPluginSearchResultProducer lpsrp = null; if (se != null) { for (SearchResultProducer srp : se.getSearchResultProducers()) if (srp instanceof LocalPluginSearchResultProducer) lpsrp = (LocalPluginSearchResultProducer) srp; } final List<SearchResult> tmpResults = new ArrayList<SearchResult>(); for (Element plugin : XMLUtil.getElements(resultElement, ID_PLUGIN)) { // abort if (hasWaitingSearch()) return; final SearchResult result = getResult(consumer, onlinePlugins, plugin, words, lpsrp); if (result != null) tmpResults.add(result); } // use a copy to avoid future concurrent accesses results = new ArrayList<SearchResult>(tmpResults); consumer.resultsChanged(this); // load descriptions for (SearchResult result : tmpResults) { // abort if (hasWaitingSearch()) return; ((OnlinePluginResult) result).getPlugin().loadDescriptor(); consumer.resultChanged(this, result); } // load images for (SearchResult result : tmpResults) { // abort if (hasWaitingSearch()) return; ((OnlinePluginResult) result).getPlugin().loadImages(); consumer.resultChanged(this, result); } } private static boolean ensureOnlineLoaderLoaded() { PluginRepositoryLoader.waitLoaded(); // repository loader failed --> retry once if (PluginRepositoryLoader.failed() && NetworkUtil.hasInternetAccess()) { PluginRepositoryLoader.reload(); PluginRepositoryLoader.waitLoaded(); } return !PluginRepositoryLoader.failed(); } private OnlinePluginResult getResult(SearchResultConsumer consumer, List<PluginDescriptor> onlinePlugins, Element pluginNode, String words[], LocalPluginSearchResultProducer lpsrp) { final String className = XMLUtil.getElementValue(pluginNode, ID_CLASSNAME, ""); final String text = XMLUtil.getElementValue(pluginNode, ID_TEXT, ""); final boolean shortSearch = PluginSearchResultProducerHelper.getShortSearch(words); int priority; final PluginDescriptor localPlugin = PluginLoader.getPlugin(className); // exists in local ? if (localPlugin != null) { // if we have the local search provider, we try to add result if not already existing if (lpsrp != null) { final List<SearchResult> localResults = lpsrp.getResults(); boolean alreadyExists = false; synchronized (localResults) { for (SearchResult result : localResults) { if (((LocalPluginResult) result).getPlugin() == localPlugin) { alreadyExists = true; break; } } } // not already present in local result --> add it if (!alreadyExists) { priority = PluginSearchResultProducerHelper.searchInPlugin(localPlugin, words, shortSearch); // not found in local description --> assume low priority if (priority == 0) priority = 1; lpsrp.addResult(new LocalPluginResult(lpsrp, localPlugin, text, words, priority), consumer); } } // don't return it for online result return null; } final PluginDescriptor onlinePlugin = PluginDescriptor.getPlugin(onlinePlugins, className); // cannot be found in online ? --> no result if (onlinePlugin == null) return null; // try to get priority on result onlinePlugin.loadDescriptor(); priority = PluginSearchResultProducerHelper.searchInPlugin(onlinePlugin, words, shortSearch); // only keep high priority info from local data if (priority <= 5) priority = 1; return new OnlinePluginResult(this, onlinePlugin, text, words, priority); } }