Merge branch 'fix/plugins-loading'

This commit is contained in:
tlrx 2014-12-08 17:15:06 +01:00
commit 31a77185a6
6 changed files with 188 additions and 7 deletions

View File

@ -21,7 +21,6 @@ package org.elasticsearch.plugins;
import com.google.common.base.Charsets;
import com.google.common.collect.*;
import com.google.common.primitives.Chars;
import org.apache.lucene.util.Constants;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.ElasticsearchException;
@ -42,13 +41,13 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.env.Environment;
import java.io.*;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.*;
import java.util.*;
import static org.elasticsearch.common.io.FileSystemUtils.isAccessibleDirectory;
@ -61,6 +60,9 @@ public class PluginsService extends AbstractComponent {
public static final String ES_PLUGIN_PROPERTIES = "es-plugin.properties";
public static final String LOAD_PLUGIN_FROM_CLASSPATH = "load_classpath_plugins";
private static final PathMatcher PLUGIN_LIB_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**.{jar,zip}");
private final Environment environment;
/**
@ -368,6 +370,7 @@ public class PluginsService extends AbstractComponent {
return;
}
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pluginsDirectory)) {
for (Path plugin : stream) {
// We check that subdirs are directories and readable
if (!isAccessibleDirectory(plugin, logger)) {
@ -389,7 +392,7 @@ public class PluginsService extends AbstractComponent {
// if there are jars in it, add it as well
for (Path libFile : libFiles) {
if (!(libFile.getFileName().endsWith(".jar") || libFile.getFileName().endsWith(".zip"))) {
if (!hasLibExtension(libFile)) {
continue;
}
addURL.invoke(classLoader, libFile.toUri().toURL());
@ -401,6 +404,10 @@ public class PluginsService extends AbstractComponent {
}
}
protected static boolean hasLibExtension(Path lib) {
return PLUGIN_LIB_MATCHER.matches(lib);
}
private Path[] files(Path from) throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(from)) {
return Iterators.toArray(stream.iterator(), Path.class);

View File

@ -0,0 +1,120 @@
/*
* 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.ImmutableList;
import org.elasticsearch.action.admin.cluster.node.info.PluginInfo;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.nodesinfo.SimpleNodesInfoTests;
import org.elasticsearch.plugins.loading.classpath.InClassPathPlugin;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.junit.Test;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.instanceOf;
@ClusterScope(scope= ElasticsearchIntegrationTest.Scope.TEST, numDataNodes=0, numClientNodes = 1, transportClientRatio = 0)
public class PluginServiceTests extends ElasticsearchIntegrationTest {
@Test
public void testPluginLoadingFromClassName() throws URISyntaxException {
Settings settings = settingsBuilder()
// Defines a plugin in classpath
.put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, true)
.put("plugins." + PluginsService.ES_PLUGIN_PROPERTIES_FILE_KEY, "es-plugin-test.properties")
// Defines a plugin in settings
.put("plugin.types", InSettingsPlugin.class.getName())
.build();
SimpleNodesInfoTests.startNodeWithPlugins(settings, "/org/elasticsearch/plugins/loading/");
Plugin plugin = getPlugin("in-settings-plugin");
assertNotNull("InSettingsPlugin (defined below in this class) must be loaded", plugin);
assertThat(plugin, instanceOf(InSettingsPlugin.class));
plugin = getPlugin("in-classpath-plugin");
assertNotNull("InClassPathPlugin (defined in package ) must be loaded", plugin);
assertThat(plugin, instanceOf(InClassPathPlugin.class));
plugin = getPlugin("in-jar-plugin");
assertNotNull("InJarPlugin (packaged as a JAR file in a plugins directory) must be loaded", plugin);
assertThat(plugin.getClass().getName(), endsWith("InJarPlugin"));
plugin = getPlugin("in-zip-plugin");
assertNotNull("InZipPlugin (packaged as a Zipped file in a plugins directory) must be loaded", plugin);
assertThat(plugin.getClass().getName(), endsWith("InZipPlugin"));
}
@Test
public void testHasLibExtension() {
Path p = Paths.get("path", "to", "plugin.jar");
assertTrue(PluginsService.hasLibExtension(p));
p = Paths.get("path", "to", "plugin.zip");
assertTrue(PluginsService.hasLibExtension(p));
p = Paths.get("path", "to", "plugin.tar.gz");
assertFalse(PluginsService.hasLibExtension(p));
p = Paths.get("path", "to", "plugin");
assertFalse(PluginsService.hasLibExtension(p));
}
private Plugin getPlugin(String pluginName) {
assertNotNull("cannot check plugin existence with a null plugin's name", pluginName);
PluginsService pluginsService = internalCluster().getInstance(PluginsService.class);
ImmutableList<Tuple<PluginInfo, Plugin>> plugins = pluginsService.plugins();
if ((plugins != null) && (!plugins.isEmpty())) {
for (Tuple<PluginInfo, Plugin> plugin:plugins) {
if (pluginName.equals(plugin.v1().getName())) {
return plugin.v2();
}
}
}
return null;
}
static class InSettingsPlugin extends AbstractPlugin {
private final Settings settings;
public InSettingsPlugin(Settings settings) {
this.settings = settings;
}
@Override
public String name() {
return "in-settings-plugin";
}
@Override
public String description() {
return "A plugin defined in settings";
}
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.loading.classpath;
import org.elasticsearch.plugins.AbstractPlugin;
public class InClassPathPlugin extends AbstractPlugin {
@Override
public String name() {
return "in-classpath-plugin";
}
@Override
public String description() {
return "A plugin defined in class path";
}
}

View File

@ -0,0 +1,19 @@
################################################################
# 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.
################################################################
plugin=org.elasticsearch.plugins.loading.classpath.InClassPathPlugin