diff --git a/docs/reference/cluster/nodes-info.asciidoc b/docs/reference/cluster/nodes-info.asciidoc index e6550ea740b..61d8c1a5a6a 100644 --- a/docs/reference/cluster/nodes-info.asciidoc +++ b/docs/reference/cluster/nodes-info.asciidoc @@ -40,7 +40,6 @@ plugins per node: * `site`: `true` if the plugin is a site plugin * `jvm`: `true` if the plugin is a plugin running in the JVM * `url`: URL if the plugin is a site plugin -* `isolation`: whether the plugin is loaded in isolation (`true`) or not (`false`) The result will look similar to: diff --git a/docs/reference/modules/plugins.asciidoc b/docs/reference/modules/plugins.asciidoc index 029cc627a90..4f3f6764247 100644 --- a/docs/reference/modules/plugins.asciidoc +++ b/docs/reference/modules/plugins.asciidoc @@ -142,20 +142,6 @@ bin/plugin --install mobz/elasticsearch-head --timeout 1m bin/plugin --install mobz/elasticsearch-head --timeout 0 ----------------------------------- -added[1.1.0] -[float] -==== Plugins isolation - -Since Elasticsearch 1.1, by default, each plugin is loaded in _isolation_ (in its dedicated `ClassLoader`) to avoid class clashes between the various plugins and their associated libraries. The default can be changed through the `plugins.isolation` property in `elasticsearch.yml`, by setting it to `false`: - -[source,js] --------------------------------------------------- -plugins.isolation: false --------------------------------------------------- - -Do note that each plugin can specify its _mandatory_ isolation through the `isolation` property in its `es-plugin.properties` configuration. In this (rare) case, the plugin setting is used, overwriting whatever default used by Elasticsearch. - - [float] [[known-plugins]] === Known Plugins diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/info/PluginInfo.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/info/PluginInfo.java index 9dc6e243082..b1b2fc2d572 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/info/PluginInfo.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/info/PluginInfo.java @@ -41,7 +41,6 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { static final XContentBuilderString JVM = new XContentBuilderString("jvm"); static final XContentBuilderString SITE = new XContentBuilderString("site"); static final XContentBuilderString VERSION = new XContentBuilderString("version"); - static final XContentBuilderString ISOLATION = new XContentBuilderString("isolation"); } private String name; @@ -49,7 +48,6 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { private boolean site; private boolean jvm; private String version; - private boolean isolation; public PluginInfo() { } @@ -62,9 +60,8 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { * @param site true if it's a site plugin * @param jvm true if it's a jvm plugin * @param version Version number is applicable (NA otherwise) - * @param isolation true if it's an isolated plugin */ - public PluginInfo(String name, String description, boolean site, boolean jvm, String version, boolean isolation) { + public PluginInfo(String name, String description, boolean site, boolean jvm, String version) { this.name = name; this.description = description; this.site = site; @@ -74,7 +71,6 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { } else { this.version = VERSION_NOT_AVAILABLE; } - this.isolation = isolation; } /** @@ -125,13 +121,6 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { return version; } - /** - * @return Plugin isolation - */ - public boolean isIsolation() { - return isolation; - } - public static PluginInfo readPluginInfo(StreamInput in) throws IOException { PluginInfo info = new PluginInfo(); info.readFrom(in); @@ -149,11 +138,6 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { } else { this.version = VERSION_NOT_AVAILABLE; } - if (in.getVersion().onOrAfter(Version.V_1_1_0)) { - this.isolation = in.readBoolean(); - } else { - this.isolation = false; - } } @Override @@ -165,9 +149,6 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { if (out.getVersion().onOrAfter(Version.V_1_0_0_RC2)) { out.writeString(version); } - if (out.getVersion().onOrAfter(Version.V_1_1_0)) { - out.writeBoolean(isolation); - } } @Override @@ -181,7 +162,6 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { } builder.field(Fields.JVM, jvm); builder.field(Fields.SITE, site); - builder.field(Fields.ISOLATION, isolation); builder.endObject(); return builder; @@ -207,13 +187,12 @@ public class PluginInfo implements Streamable, Serializable, ToXContent { @Override public String toString() { - final StringBuilder sb = new StringBuilder("PluginInfo{"); + final StringBuffer sb = new StringBuffer("PluginInfo{"); sb.append("name='").append(name).append('\''); sb.append(", description='").append(description).append('\''); sb.append(", site=").append(site); sb.append(", jvm=").append(jvm); sb.append(", version='").append(version).append('\''); - sb.append(", isolation=").append(isolation); sb.append('}'); return sb.toString(); } diff --git a/src/main/java/org/elasticsearch/plugins/PluginClassLoader.java b/src/main/java/org/elasticsearch/plugins/PluginClassLoader.java deleted file mode 100644 index 3846d28eeb3..00000000000 --- a/src/main/java/org/elasticsearch/plugins/PluginClassLoader.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.plugins; - -import com.google.common.collect.Lists; - -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.*; - -public class PluginClassLoader extends URLClassLoader { - - private final ClassLoader system; - private final URL url; - - PluginClassLoader(URL[] urls, ClassLoader parent) throws IOException { - super(urls, parent); - url = (urls != null && urls.length > 0 ? urls[0] : null); - - ClassLoader sys = getSystemClassLoader(); - while (sys.getParent() != null) { - sys = sys.getParent(); - } - - system = sys; - } - - // load first from system class loader then fall back to this one - @Override - protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class c = findLoadedClass(name); - if (c == null) { - // check system class loader (jvm & bootclasspath) - if (system != null) { - try { - c = system.loadClass(name); - } catch (ClassNotFoundException ignored) { - } - } - if (c == null) { - try { - // check plugin classloader - c = findClass(name); - } catch (ClassNotFoundException e) { - // fall back to parent - c = super.loadClass(name, resolve); - } - } - } - if (resolve) { - resolveClass(c); - } - return c; - } - - @Override - public URL getResource(String name) { - // apply same rules frmo loadClass - URL url = null; - if (system != null) { - url = system.getResource(name); - } - if (url == null) { - url = findResource(name); - if (url == null) { - url = super.getResource(name); - } - } - return url; - } - - @Override - public Enumeration getResources(String name) throws IOException { - List urls = Lists.newArrayList(); - if (system != null) { - urls.addAll(Collections.list(system.getResources(name))); - } - urls.addAll(Collections.list(findResources(name))); - - ClassLoader parent = getParent(); - if (parent != null) { - urls.addAll(Collections.list(parent.getResources(name))); - } - - return Collections.enumeration(urls); - } - - @Override - public String toString() { - return String.format(Locale.US, "PluginClassLoader for url [%s], classpath [%s], systemCL [%s]", url, Arrays.toString(getURLs()), system); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/plugins/PluginUtils.java b/src/main/java/org/elasticsearch/plugins/PluginUtils.java deleted file mode 100644 index 67ac0329cca..00000000000 --- a/src/main/java/org/elasticsearch/plugins/PluginUtils.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.plugins; - -import com.google.common.collect.Lists; -import org.apache.lucene.util.IOUtils; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.common.Booleans; -import org.elasticsearch.common.settings.Settings; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Collections; -import java.util.List; -import java.util.Properties; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -public final class PluginUtils { - - private PluginUtils() {} - - @SuppressWarnings("unchecked") - static Plugin loadPlugin(String className, Settings settings, ClassLoader classLoader) { - try { - Class pluginClass = (Class) classLoader.loadClass(className); - try { - return pluginClass.getConstructor(Settings.class).newInstance(settings); - } catch (NoSuchMethodException e) { - try { - return pluginClass.newInstance(); - } catch (Exception e1) { - throw new ElasticsearchException("No constructor for [" + pluginClass + "]. A plugin class must " + - "have either an empty default constructor or a single argument constructor accepting a " + - "Settings instance"); - } - } - - } catch (Exception e) { - throw new ElasticsearchException("Failed to load plugin class [" + className + "]", e); - } - } - - static List pluginClassPathAsFiles(File pluginFolder) throws IOException { - List cpFiles = Lists.newArrayList(); - cpFiles.add(pluginFolder); - - List libFiles = Lists.newArrayList(); - File[] files = pluginFolder.listFiles(); - if (files != null) { - Collections.addAll(libFiles, files); - } - File libLocation = new File(pluginFolder, "lib"); - if (libLocation.exists() && libLocation.isDirectory()) { - files = libLocation.listFiles(); - if (files != null) { - Collections.addAll(libFiles, files); - } - } - - // if there are jars in it, add it as well - for (File libFile : libFiles) { - if (libFile.getName().endsWith(".jar") || libFile.getName().endsWith(".zip")) { - cpFiles.add(libFile); - } - } - - return cpFiles; - } - - static boolean lookupIsolation(List pluginProperties, boolean defaultIsolation) throws IOException { - Properties props = new Properties(); - InputStream is = null; - for (URL prop : pluginProperties) { - try { - props.load(prop.openStream()); - return Booleans.parseBoolean(props.getProperty("isolation"), defaultIsolation); - } finally { - IOUtils.closeWhileHandlingException(is); - } - } - return defaultIsolation; - } - - static List lookupPluginProperties(List pluginClassPath) throws Exception { - if (pluginClassPath.isEmpty()) { - return Collections.emptyList(); - } - - List found = Lists.newArrayList(); - - for (File file : pluginClassPath) { - String toString = file.getName(); - if (toString.endsWith(".jar") || toString.endsWith(".zip")) { - JarFile jar = new JarFile(file); - try { - JarEntry jarEntry = jar.getJarEntry("es-plugin.properties"); - if (jarEntry != null) { - found.add(new URL("jar:" + file.toURI().toString() + "!/es-plugin.properties")); - } - } finally { - IOUtils.closeWhileHandlingException(jar); - } - } - else { - File props = new File(file, "es-plugin.properties"); - if (props.exists() && props.canRead()) { - found.add(props.toURI().toURL()); - } - } - } - - return found; - } - - static URL[] convertFileToUrl(List pluginClassPath) throws IOException { - URL[] urls = new URL[pluginClassPath.size()]; - for (int i = 0; i < urls.length; i++) { - urls[i] = pluginClassPath.get(i).toURI().toURL(); - } - return urls; - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/plugins/PluginsService.java b/src/main/java/org/elasticsearch/plugins/PluginsService.java index 41ab24dffd2..a1b8c30de3f 100644 --- a/src/main/java/org/elasticsearch/plugins/PluginsService.java +++ b/src/main/java/org/elasticsearch/plugins/PluginsService.java @@ -38,6 +38,7 @@ import org.elasticsearch.index.CloseableIndexComponent; import java.io.File; import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.net.URL; @@ -88,8 +89,8 @@ public class PluginsService extends AbstractComponent { // first we load all the default plugins from the settings String[] defaultPluginsClasses = settings.getAsArray("plugin.types"); for (String pluginClass : defaultPluginsClasses) { - Plugin plugin = PluginUtils.loadPlugin(pluginClass, settings, settings.getClassLoader()); - PluginInfo pluginInfo = new PluginInfo(plugin.name(), plugin.description(), hasSite(plugin.name()), true, PluginInfo.VERSION_NOT_AVAILABLE, false); + Plugin plugin = loadPlugin(pluginClass, settings); + PluginInfo pluginInfo = new PluginInfo(plugin.name(), plugin.description(), hasSite(plugin.name()), true, PluginInfo.VERSION_NOT_AVAILABLE); if (logger.isTraceEnabled()) { logger.trace("plugin loaded from settings [{}]", pluginInfo); } @@ -97,7 +98,8 @@ public class PluginsService extends AbstractComponent { } // now, find all the ones that are in the classpath - tupleBuilder.addAll(loadPlugins()); + loadPluginsIntoClassLoader(); + tupleBuilder.addAll(loadPluginsFromClasspath(settings)); this.plugins = tupleBuilder.build(); // We need to build a List of jvm and site plugins for checking mandatory plugins @@ -315,110 +317,103 @@ public class PluginsService extends AbstractComponent { return cachedPluginsInfo; } - private List> loadPlugins() { - File pluginsFile = environment.pluginsFile(); - if (!isAccessibleDirectory(pluginsFile, logger)) { - return Collections.emptyList(); + private void loadPluginsIntoClassLoader() { + File pluginsDirectory = environment.pluginsFile(); + if (!isAccessibleDirectory(pluginsDirectory, logger)) { + return; } - List> pluginData = Lists.newArrayList(); - - boolean defaultIsolation = settings.getAsBoolean("plugins.isolation", Boolean.FALSE); - ClassLoader esClassLoader = settings.getClassLoader(); + ClassLoader classLoader = settings.getClassLoader(); + Class classLoaderClass = classLoader.getClass(); Method addURL = null; - boolean discoveredAddUrl = false; - - File[] pluginsFiles = pluginsFile.listFiles(); - - if (pluginsFiles != null) { - for (File pluginRoot : pluginsFiles) { - if (isAccessibleDirectory(pluginRoot, logger)) { - try { - logger.trace("--- adding plugin [" + pluginRoot.getAbsolutePath() + "]"); - // check isolation - List pluginClassPath = PluginUtils.pluginClassPathAsFiles(pluginRoot); - List pluginProperties = PluginUtils.lookupPluginProperties(pluginClassPath); - boolean isolated = PluginUtils.lookupIsolation(pluginProperties, defaultIsolation); - - if (isolated) { - logger.trace("--- creating isolated space for plugin [" + pluginRoot.getAbsolutePath() + "]"); - PluginClassLoader pcl = new PluginClassLoader(PluginUtils.convertFileToUrl(pluginClassPath), esClassLoader); - pluginData.addAll(loadPlugin(pluginClassPath, pluginProperties, pcl, true)); - } else { - if (!discoveredAddUrl) { - discoveredAddUrl = true; - Class esClassLoaderClass = esClassLoader.getClass(); - - while (!esClassLoaderClass.equals(Object.class)) { - try { - addURL = esClassLoaderClass.getDeclaredMethod("addURL", URL.class); - addURL.setAccessible(true); - break; - } catch (NoSuchMethodException e) { - // no method, try the parent - esClassLoaderClass = esClassLoaderClass.getSuperclass(); - } - } - } - - if (addURL == null) { - logger.debug("failed to find addURL method on classLoader [" + esClassLoader + "] to add methods"); - } - else { - for (File file : pluginClassPath) { - addURL.invoke(esClassLoader, file.toURI().toURL()); - } - pluginData.addAll(loadPlugin(pluginClassPath, pluginProperties, esClassLoader, false)); - } - } - } catch (Throwable e) { - logger.warn("failed to add plugin [" + pluginRoot.getAbsolutePath() + "]", e); - } - } + while (!classLoaderClass.equals(Object.class)) { + try { + addURL = classLoaderClass.getDeclaredMethod("addURL", URL.class); + addURL.setAccessible(true); + break; + } catch (NoSuchMethodException e) { + // no method, try the parent + classLoaderClass = classLoaderClass.getSuperclass(); } - } else { - logger.debug("failed to list plugins from {}. Check your right access.", pluginsFile.getAbsolutePath()); + } + if (addURL == null) { + logger.debug("failed to find addURL method on classLoader [" + classLoader + "] to add methods"); + return; } - return pluginData; + for (File plugin : pluginsDirectory.listFiles()) { + // We check that subdirs are directories and readable + if (!isAccessibleDirectory(plugin, logger)) { + continue; + } + + logger.trace("--- adding plugin [{}]", plugin.getAbsolutePath()); + + try { + // add the root + addURL.invoke(classLoader, plugin.toURI().toURL()); + // gather files to add + List libFiles = Lists.newArrayList(); + if (plugin.listFiles() != null) { + libFiles.addAll(Arrays.asList(plugin.listFiles())); + } + File libLocation = new File(plugin, "lib"); + if (libLocation.exists() && libLocation.isDirectory() && libLocation.listFiles() != null) { + libFiles.addAll(Arrays.asList(libLocation.listFiles())); + } + + // if there are jars in it, add it as well + for (File libFile : libFiles) { + if (!(libFile.getName().endsWith(".jar") || libFile.getName().endsWith(".zip"))) { + continue; + } + addURL.invoke(classLoader, libFile.toURI().toURL()); + } + } catch (Throwable e) { + logger.warn("failed to add plugin [" + plugin + "]", e); + } + } } - private Collection> loadPlugin(List pluginClassPath, List properties, ClassLoader classLoader, boolean isolation) throws Exception { - List> plugins = Lists.newArrayList(); + private ImmutableList> loadPluginsFromClasspath(Settings settings) { + ImmutableList.Builder> plugins = ImmutableList.builder(); - Enumeration entries = Collections.enumeration(properties); - while (entries.hasMoreElements()) { - URL pluginUrl = entries.nextElement(); - Properties pluginProps = new Properties(); - InputStream is = null; - try { - is = pluginUrl.openStream(); - pluginProps.load(is); - String pluginClassName = pluginProps.getProperty("plugin"); - if (pluginClassName == null) { - throw new IllegalArgumentException("No plugin class specified"); + // Trying JVM plugins: looking for es-plugin.properties files + try { + Enumeration pluginUrls = settings.getClassLoader().getResources(ES_PLUGIN_PROPERTIES); + while (pluginUrls.hasMoreElements()) { + URL pluginUrl = pluginUrls.nextElement(); + Properties pluginProps = new Properties(); + InputStream is = null; + try { + is = pluginUrl.openStream(); + pluginProps.load(is); + String pluginClassName = pluginProps.getProperty("plugin"); + String pluginVersion = pluginProps.getProperty("version", PluginInfo.VERSION_NOT_AVAILABLE); + Plugin plugin = loadPlugin(pluginClassName, settings); + + // Is it a site plugin as well? Does it have also an embedded _site structure + File siteFile = new File(new File(environment.pluginsFile(), plugin.name()), "_site"); + boolean isSite = isAccessibleDirectory(siteFile, logger); + if (logger.isTraceEnabled()) { + logger.trace("found a jvm plugin [{}], [{}]{}", + plugin.name(), plugin.description(), isSite ? ": with _site structure" : ""); + } + + PluginInfo pluginInfo = new PluginInfo(plugin.name(), plugin.description(), isSite, true, pluginVersion); + + plugins.add(new Tuple<>(pluginInfo, plugin)); + } catch (Throwable e) { + logger.warn("failed to load plugin from [" + pluginUrl + "]", e); + } finally { + IOUtils.closeWhileHandlingException(is); } - String pluginVersion = pluginProps.getProperty("version", PluginInfo.VERSION_NOT_AVAILABLE); - Plugin plugin = PluginUtils.loadPlugin(pluginClassName, settings, classLoader); - - // Is it a site plugin as well? Does it have also an embedded _site structure - File siteFile = new File(new File(environment.pluginsFile(), plugin.name()), "_site"); - boolean isSite = isAccessibleDirectory(siteFile, logger); - if (logger.isTraceEnabled()) { - logger.trace("found a jvm plugin [{}], [{}]{}", - plugin.name(), plugin.description(), isSite ? ": with _site structure" : ""); - } - - PluginInfo pluginInfo = new PluginInfo(plugin.name(), plugin.description(), isSite, true, pluginVersion, isolation); - plugins.add(new Tuple<>(pluginInfo, plugin)); - } catch (Throwable e) { - logger.warn("failed to load plugin from [" + pluginUrl + "]", e); - } finally { - IOUtils.closeWhileHandlingException(is); } + } catch (IOException e) { + logger.warn("failed to find jvm plugins from classpath", e); } - return plugins; + return plugins.build(); } private ImmutableList> loadSitePlugins() { @@ -471,7 +466,7 @@ public class PluginsService extends AbstractComponent { logger.trace("found a site plugin name [{}], version [{}], description [{}]", name, version, description); } - sitePlugins.add(new Tuple(new PluginInfo(name, description, true, false, version, false), null)); + sitePlugins.add(new Tuple(new PluginInfo(name, description, true, false, version), null)); } } } @@ -494,4 +489,27 @@ public class PluginsService extends AbstractComponent { File sitePluginDir = new File(pluginsFile, name + "/_site"); return isAccessibleDirectory(sitePluginDir, logger); } -} \ No newline at end of file + + private Plugin loadPlugin(String className, Settings settings) { + try { + Class pluginClass = (Class) settings.getClassLoader().loadClass(className); + Plugin plugin; + try { + plugin = pluginClass.getConstructor(Settings.class).newInstance(settings); + } catch (NoSuchMethodException e) { + try { + plugin = pluginClass.getConstructor().newInstance(); + } catch (NoSuchMethodException e1) { + throw new ElasticsearchException("No constructor for [" + pluginClass + "]. A plugin class must " + + "have either an empty default constructor or a single argument constructor accepting a " + + "Settings instance"); + } + } + + return plugin; + + } catch (Throwable e) { + throw new ElasticsearchException("Failed to load plugin class [" + className + "]", e); + } + } +} diff --git a/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java b/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java index cdf8efffbe7..5695adda8bf 100644 --- a/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java +++ b/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java @@ -84,7 +84,6 @@ public class RestPluginsAction extends AbstractCatAction { table.addCell("component", "alias:c;desc:component"); table.addCell("version", "alias:v;desc:component version"); table.addCell("type", "alias:t;desc:type (j for JVM, s for Site)"); - table.addCell("isolation", "alias:i;desc:isolation"); table.addCell("url", "alias:u;desc:url for site plugins"); table.addCell("description", "alias:d;default:false;desc:plugin details"); table.endHeaders(); @@ -118,7 +117,6 @@ public class RestPluginsAction extends AbstractCatAction { } } table.addCell(type); - table.addCell(pluginInfo.isIsolation() ? "x" : ""); table.addCell(pluginInfo.getUrl()); table.addCell(pluginInfo.getDescription()); table.endRow(); diff --git a/src/test/java/org/elasticsearch/nodesinfo/SimpleNodesInfoTests.java b/src/test/java/org/elasticsearch/nodesinfo/SimpleNodesInfoTests.java index 01ddd7e53f3..a17fa9313a4 100644 --- a/src/test/java/org/elasticsearch/nodesinfo/SimpleNodesInfoTests.java +++ b/src/test/java/org/elasticsearch/nodesinfo/SimpleNodesInfoTests.java @@ -132,43 +132,37 @@ public class SimpleNodesInfoTests extends ElasticsearchIntegrationTest { logger.info("--> full json answer, status " + response.toString()); assertNodeContainsPlugins(response, server1NodeId, - Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST,// No JVM Plugin - Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST);// No Site Plugin + Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, // No JVM Plugin + Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST);// No Site Plugin assertNodeContainsPlugins(response, server2NodeId, - Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, // No JVM Plugin + Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, // No JVM Plugin Lists.newArrayList(Fields.SITE_PLUGIN), // Site Plugin Lists.newArrayList(Fields.SITE_PLUGIN_DESCRIPTION), - Lists.newArrayList(Fields.SITE_PLUGIN_VERSION), - Lists.newArrayList(Boolean.FALSE)); + Lists.newArrayList(Fields.SITE_PLUGIN_VERSION)); assertNodeContainsPlugins(response, server3NodeId, Lists.newArrayList(TestPlugin.Fields.NAME), // JVM Plugin Lists.newArrayList(TestPlugin.Fields.DESCRIPTION), Lists.newArrayList(PluginInfo.VERSION_NOT_AVAILABLE), - Lists.newArrayList(Boolean.FALSE), - Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST);// No site Plugin + Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_LIST);// No site Plugin assertNodeContainsPlugins(response, server4NodeId, Lists.newArrayList(TestNoVersionPlugin.Fields.NAME), // JVM Plugin Lists.newArrayList(TestNoVersionPlugin.Fields.DESCRIPTION), Lists.newArrayList(PluginInfo.VERSION_NOT_AVAILABLE), - Lists.newArrayList(Boolean.FALSE), Lists.newArrayList(Fields.SITE_PLUGIN, TestNoVersionPlugin.Fields.NAME),// Site Plugin Lists.newArrayList(PluginInfo.DESCRIPTION_NOT_AVAILABLE), - Lists.newArrayList(PluginInfo.VERSION_NOT_AVAILABLE), - Lists.newArrayList(Boolean.FALSE)); + Lists.newArrayList(PluginInfo.VERSION_NOT_AVAILABLE)); } private void assertNodeContainsPlugins(NodesInfoResponse response, String nodeId, List expectedJvmPluginNames, List expectedJvmPluginDescriptions, List expectedJvmVersions, - List expectedJvmIsolations, List expectedSitePluginNames, List expectedSitePluginDescriptions, - List expectedSiteVersions, - List expectedSiteIsolations) { + List expectedSiteVersions) { assertThat(response.getNodesMap().get(nodeId), notNullValue()); @@ -190,11 +184,6 @@ public class SimpleNodesInfoTests extends ElasticsearchIntegrationTest { assertThat(jvmPluginVersions, hasItem(pluginVersion)); } - List jvmPluginIsolations = FluentIterable.from(plugins.getInfos()).filter(jvmPluginPredicate).transform(isolationFunction).toList(); - for (Boolean pluginIsolation : expectedJvmIsolations) { - assertThat(jvmPluginIsolations, hasItem(pluginIsolation)); - } - FluentIterable jvmUrls = FluentIterable.from(plugins.getInfos()) .filter(and(jvmPluginPredicate, Predicates.not(sitePluginPredicate))) .filter(isNull()) @@ -219,11 +208,6 @@ public class SimpleNodesInfoTests extends ElasticsearchIntegrationTest { for (String pluginVersion : expectedSiteVersions) { assertThat(sitePluginVersions, hasItem(pluginVersion)); } - - List sitePluginIsolations = FluentIterable.from(plugins.getInfos()).filter(sitePluginPredicate).transform(isolationFunction).toList(); - for (Boolean pluginIsolation : expectedSiteIsolations) { - assertThat(sitePluginIsolations, hasItem(pluginIsolation)); - } } private String startNodeWithPlugins(int nodeId, String ... pluginClassNames) throws URISyntaxException { @@ -283,10 +267,4 @@ public class SimpleNodesInfoTests extends ElasticsearchIntegrationTest { return pluginInfo.getVersion(); } }; - - private Function isolationFunction = new Function() { - public Boolean apply(PluginInfo pluginInfo) { - return pluginInfo.isIsolation(); - } - }; } diff --git a/src/test/java/org/elasticsearch/plugins/IsolatedPluginTests.java b/src/test/java/org/elasticsearch/plugins/IsolatedPluginTests.java deleted file mode 100644 index f8fa82a062d..00000000000 --- a/src/test/java/org/elasticsearch/plugins/IsolatedPluginTests.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.plugins; - -import com.google.common.io.Files; -import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.io.FileSystemUtils; -import org.elasticsearch.common.io.Streams; -import org.elasticsearch.common.settings.ImmutableSettings; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.test.ElasticsearchIntegrationTest; -import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Properties; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; - -// NB: the tests uses System Properties to pass the information from different plugins (loaded in separate CLs) to the test. -// hence the use of try/finally blocks to clean these up after the test has been executed as otherwise the test framework will trigger a failure -@ClusterScope(scope = ElasticsearchIntegrationTest.Scope.TEST, numNodes = 0) -public class IsolatedPluginTests extends ElasticsearchIntegrationTest { - - private static final Settings SETTINGS; - private static final File PLUGIN_DIR; - private Properties props; - - static { - PLUGIN_DIR = Files.createTempDir(); - - SETTINGS = ImmutableSettings.settingsBuilder() - .put("discovery.zen.ping.multicast.enabled", false) - .put("force.http.enabled", true) - .put("plugins.isolation", true) - .put("path.plugins", PLUGIN_DIR.getAbsolutePath()) - .build(); - } - - @Before - public void beforeTest() throws Exception { - props = new Properties(); - props.putAll(System.getProperties()); - - logger.info("Installing plugins into folder {}", PLUGIN_DIR); - FileSystemUtils.mkdirs(PLUGIN_DIR); - - // copy plugin - copyPlugin(new File(PLUGIN_DIR, "plugin-v1")); - copyPlugin(new File(PLUGIN_DIR, "plugin-v2")); - } - - private void copyPlugin(File p1) throws IOException { - FileSystemUtils.mkdirs(p1); - // copy plugin - File dir = new File(p1, "org/elasticsearch/plugins/isolation/"); - FileSystemUtils.mkdirs(dir); - copyFile(getClass().getResourceAsStream("isolation/DummyClass.class"), new File(dir, "DummyClass.class")); - copyFile(getClass().getResourceAsStream("isolation/IsolatedPlugin.class"), new File(dir, "IsolatedPlugin.class")); - copyFile(getClass().getResourceAsStream("isolation/es-plugin.properties"), new File(p1, "es-plugin.properties")); - } - - private void copyFile(InputStream source, File out) throws IOException { - out.createNewFile(); - Streams.copy(source, new FileOutputStream(out)); - } - - @After - public void afterTest() throws Exception { - FileSystemUtils.deleteRecursively(PLUGIN_DIR); - } - - protected Settings nodeSettings(int nodeOrdinal) { - return SETTINGS; - } - - @Test - public void testPluginNumberOfIsolatedInstances() throws Exception { - try { - NodesInfoResponse nodesInfoResponse = client().admin().cluster().prepareNodesInfo().clear().setPlugins(true).get(); - assertThat(nodesInfoResponse.getNodes().length, equalTo(1)); - assertThat(nodesInfoResponse.getNodes()[0].getPlugins().getInfos(), notNullValue()); - assertThat(nodesInfoResponse.getNodes()[0].getPlugins().getInfos().size(), equalTo(2)); - } finally { - System.setProperties(props); - } - } - - @Test - public void testIsolatedPluginProperties() throws Exception { - try { - String prop = "es.test.isolated.plugin.count"; - int count = Integer.getInteger(prop, 0); - client(); - // do a >= comparison in case there are multiple tests running in the same JVM (build server) - assertThat(Integer.getInteger(prop), greaterThanOrEqualTo(count + 2)); - Properties p = System.getProperties(); - prop = p.getProperty("es.test.isolated.plugin.instantiated.hashes"); - String[] hashes = Strings.delimitedListToStringArray(prop, " "); - // 2 plugins plus trailing space - assertThat(hashes.length, greaterThanOrEqualTo(count + 2)); - Arrays.sort(hashes); - assertThat(Arrays.binarySearch(hashes, p.getProperty("es.test.isolated.plugin.instantiated")), greaterThanOrEqualTo(0)); - } finally { - System.setProperties(props); - } - } -} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/plugins/PluginClassLoaderTest.java b/src/test/java/org/elasticsearch/plugins/PluginClassLoaderTest.java deleted file mode 100644 index e871006039b..00000000000 --- a/src/test/java/org/elasticsearch/plugins/PluginClassLoaderTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.plugins; - -import org.junit.Before; -import org.junit.Test; - -import java.net.URL; -import java.util.Properties; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.*; - - -public class PluginClassLoaderTest { - - private static final String NAME = "es.test.isolated.plugin.name"; - private static final String INSTANCE = "es.test.isolated.plugin.instantiated"; - private static final String READ = "es.test.isolated.plugin.read.name"; - - private URL root; - private String clazz = getClass().getName().replace('.', '/').concat(".class"); - private ClassLoader parent; - - @Before - public void before() throws Exception { - System.getProperties().setProperty(READ, ""); - System.getProperties().setProperty(NAME, ""); - System.getProperties().setProperty(INSTANCE, ""); - - parent = getClass().getClassLoader(); - URL url = parent.getResource(clazz); - root = new URL(url.toString().substring(0, url.toString().indexOf(clazz))); - } - - @Test - public void testClassSpaceIsolationEvenWhenPointingToSameClass() throws Exception { - - PluginClassLoader space1 = new PluginClassLoader(new URL[] { root }, null); - Properties props = System.getProperties(); - assertThat(props.getProperty(READ), is("")); - props.setProperty(NAME, "one"); - Class class1 = Class.forName("org.elasticsearch.plugins.isolation.DummyClass", true, space1); - assertThat(props.getProperty(READ), is("one")); - - String instance1 = props.getProperty(INSTANCE); - - PluginClassLoader space2 = new PluginClassLoader(new URL[] { root }, null); - props.setProperty(NAME, "two"); - Class class2 = Class.forName("org.elasticsearch.plugins.isolation.DummyClass", true, space2); - assertThat(props.getProperty(READ), is("two")); - - String instance2 = props.getProperty(INSTANCE); - assertThat(instance1, not(instance2)); - assertNotSame(class1, class2); - } - - @Test - public void testDelegateToParentIfResourcesNotFoundLocally() throws Exception { - - PluginClassLoader space1 = new PluginClassLoader(new URL[] {}, null); - assertNull(space1.getResource(clazz)); - - PluginClassLoader space2 = new PluginClassLoader(new URL[] {}, parent); - assertNotNull(parent.getResource(clazz)); - assertNotNull(space2.getResource(clazz)); - } - - @Test - public void testIgnoreClassesInParentIfFoundLocally() throws Exception { - ClassLoader parent = getClass().getClassLoader(); - - PluginClassLoader space1 = new PluginClassLoader(new URL[] { root }, parent); - - Properties props = System.getProperties(); - assertThat(props.getProperty(READ), is("")); - props.setProperty(NAME, "one"); - - String before = props.getProperty(NAME); - Class parentClass = Class.forName("org.elasticsearch.plugins.isolation.DummyClass", true, parent); - props.setProperty(NAME, "one"); - Class class1 = Class.forName("org.elasticsearch.plugins.isolation.DummyClass", true, space1); - assertThat(props.getProperty(READ), is(before)); - assertThat(class1, is(not(parentClass))); - } -} diff --git a/src/test/java/org/elasticsearch/plugins/isolation/DummyClass.java b/src/test/java/org/elasticsearch/plugins/isolation/DummyClass.java deleted file mode 100644 index a3b9060d21c..00000000000 --- a/src/test/java/org/elasticsearch/plugins/isolation/DummyClass.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.plugins.isolation; - -import java.util.Properties; - -public class DummyClass { - - static final String name; - - static { - Properties sysProps = System.getProperties(); - // make sure to get a string even when dealing with null - name = "" + sysProps.getProperty("es.test.isolated.plugin.name"); - sysProps.setProperty("es.test.isolated.plugin.instantiated", "" + DummyClass.class.hashCode()); - Integer count = Integer.getInteger("es.test.isolated.plugin.count"); - if (count == null) { - count = Integer.valueOf(0); - } - - count = count + 1; - - sysProps.setProperty("es.test.isolated.plugin.count", count.toString()); - - String prop = sysProps.getProperty("es.test.isolated.plugin.instantiated.hashes"); - if (prop == null) { - prop = ""; - } - - prop = prop + DummyClass.class.hashCode() + " "; - sysProps.setProperty("es.test.isolated.plugin.instantiated.hashes", prop); - sysProps.setProperty("es.test.isolated.plugin.read.name", name); - } - -} diff --git a/src/test/java/org/elasticsearch/plugins/isolation/IsolatedPlugin.java b/src/test/java/org/elasticsearch/plugins/isolation/IsolatedPlugin.java deleted file mode 100644 index 648d31ecd1a..00000000000 --- a/src/test/java/org/elasticsearch/plugins/isolation/IsolatedPlugin.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.plugins.isolation; - -import org.elasticsearch.plugins.AbstractPlugin; - -public class IsolatedPlugin extends AbstractPlugin { - - private final DummyClass dummy; - - public IsolatedPlugin() { - dummy = new DummyClass(); - } - - @Override - public String name() { - return dummy.name; - } - - @Override - public String description() { - return "IsolatedPlugin " + hashCode(); - } -} diff --git a/src/test/resources/org/elasticsearch/plugins/isolation/es-plugin.properties b/src/test/resources/org/elasticsearch/plugins/isolation/es-plugin.properties deleted file mode 100644 index 8b0c1759661..00000000000 --- a/src/test/resources/org/elasticsearch/plugins/isolation/es-plugin.properties +++ /dev/null @@ -1 +0,0 @@ -plugin=org.elasticsearch.plugins.isolation.IsolatedPlugin \ No newline at end of file