Java tutorial
/* * Copyright (c) 2018 OBiBa. All rights reserved. * * This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.obiba.mica.micaConfig.service; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.io.Files; import org.obiba.core.util.FileUtil; import org.obiba.mica.core.upgrade.RuntimeVersionProvider; import org.obiba.mica.spi.search.ConfigurationProvider; import org.obiba.mica.spi.search.SearchEngineService; import org.obiba.mica.spi.search.SearchEngineServiceLoader; import org.obiba.plugins.PluginRepositoryCache; import org.obiba.plugins.PluginRepositoryException; import org.obiba.plugins.PluginResources; import org.obiba.plugins.PluginsManagerHelper; import org.obiba.plugins.spi.ServicePlugin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.inject.Inject; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.stream.Collectors; @Component public class PluginsService implements EnvironmentAware { private static final Logger log = LoggerFactory.getLogger(PluginsService.class); private static final String PLUGINS_PATH = "${MICA_HOME}/plugins"; private static final String DEFAULT_PLUGINS_UPDATE_SITE = "https://plugins.obiba.org/stable"; private static final String[] ES_CONFIGURATION = new String[] { "dataNode", "clusterName", "shards", "replicas", "settings", "maxConcurrentJoinQueries", "concurrentJoinQueriesWaitTimeout", "transportClient", "transportAddress", "transportSniff" }; @Inject private ConfigurationProvider configurationProvider; @Inject private RuntimeVersionProvider runtimeVersionProvider; private File pluginsDir; private File archiveDir; private Collection<PluginResources> registeredPlugins; private List<ServicePlugin> servicePlugins = Lists.newArrayList(); private RelaxedPropertyResolver esPropertyResolver; private RelaxedPropertyResolver pluginsPropertyResolver; private PluginRepositoryCache pluginRepositoryCache; @Override public void setEnvironment(Environment environment) { esPropertyResolver = new RelaxedPropertyResolver(environment, "elasticsearch."); pluginsPropertyResolver = new RelaxedPropertyResolver(environment, "plugins."); } public SearchEngineService getSearchEngineService() { return (SearchEngineService) getServicePlugins(SearchEngineService.class).iterator().next(); } // // Private methods // private Collection<ServicePlugin> getServicePlugins(Class clazz) { //init(); return servicePlugins.stream().filter(s -> clazz.isAssignableFrom(s.getClass())) .collect(Collectors.toList()); } @PostConstruct public void init() { if (pluginsDir != null) return; pluginsDir = new File(PLUGINS_PATH.replace("${MICA_HOME}", System.getProperty("MICA_HOME"))); if (!pluginsDir.exists() && !pluginsDir.mkdirs()) { log.warn("Cannot create directory: {}", pluginsDir.getAbsolutePath()); } archiveDir = new File(pluginsDir, ".archive"); initPlugins(); } /** * Initialize plugin resources. */ private void initPlugins() { Collection<PluginResources> plugins = getPlugins(true); // ensure there is a mica-search plugin installed if (plugins.stream().noneMatch(p -> "mica-search".equals(p.getType()))) { installPlugin("mica-search-es", null); // rescan plugins plugins = getPlugins(true); } boolean micaSearchFound = false; // mica-search plugin is a singleton for (PluginResources plugin : plugins) { if ("mica-search".equals(plugin.getType()) && !micaSearchFound) { initSearchEngineServicePlugin(plugin); micaSearchFound = true; } } } private void initSearchEngineServicePlugin(PluginResources plugin) { SearchEngineService service = SearchEngineServiceLoader.get(plugin.getURLClassLoader(false)).iterator() .next(); Properties properties = plugin.getProperties(); for (String key : ES_CONFIGURATION) { if (esPropertyResolver.containsProperty(key)) properties.setProperty(key, esPropertyResolver.getProperty(key)); } service.configure(properties); service.setConfigurationProvider(configurationProvider); service.start(); servicePlugins.add(service); } private synchronized Collection<PluginResources> getPlugins(boolean extract) { Map<String, PluginResources> pluginsMap = Maps.newLinkedHashMap(); // make sure plugins directory exists // read it to enhance classpath if (!pluginsDir.exists() || !pluginsDir.isDirectory() || !pluginsDir.canRead()) return pluginsMap.values(); if (extract) PluginsManagerHelper.preparePlugins(pluginsDir, archiveDir); processPlugins(pluginsMap, pluginsDir); registeredPlugins = pluginsMap.values(); return registeredPlugins; } /** * Discover valid and most recent version plugins and archive plugins prepared for uninstallation. * * @param pluginsMap * @param pluginsDir */ private void processPlugins(Map<String, PluginResources> pluginsMap, File pluginsDir) { File[] children = pluginsDir .listFiles(pathname -> pathname.isDirectory() && !pathname.getName().startsWith(".")); if (children == null || children.length == 0) return; for (File child : children) { PluginResources plugin = new MicaPlugin(child); PluginsManagerHelper.processPlugin(pluginsMap, plugin, archiveDir); } } private void installPlugin(String name, String version) { String pVersion = version; if (Strings.isNullOrEmpty(version)) { // no version specified: get the latest pVersion = getPluginRepositoryCache().getPluginLatestVersion(name); } try { File tmpDir = Files.createTempDir(); installPlugin(getPluginRepositoryCache().downloadPlugin(name, pVersion, tmpDir), true); FileUtil.delete(tmpDir); } catch (IOException e) { throw new PluginRepositoryException( "Failed to install plugin " + name + ":" + version + " : " + e.getMessage(), e); } } private void installPlugin(File pluginFile, boolean rmAfterInstall) { try { if (!pluginsDir.exists()) pluginsDir.mkdirs(); FileUtil.copyFile(pluginFile, pluginsDir); if (rmAfterInstall) pluginFile.delete(); } catch (IOException e) { throw new PluginRepositoryException("Plugin installation failed: " + e.getMessage(), e); } } private PluginRepositoryCache getPluginRepositoryCache() { if (pluginRepositoryCache == null) pluginRepositoryCache = new PluginRepositoryCache(runtimeVersionProvider, pluginsPropertyResolver.getProperty("updateSite", DEFAULT_PLUGINS_UPDATE_SITE)); return pluginRepositoryCache; } }