From 97ec8f94aee6309390d3ba41fe5c3da598fade94 Mon Sep 17 00:00:00 2001 From: tlrx Date: Mon, 8 Dec 2014 17:13:39 +0100 Subject: [PATCH] Plugins: Plugin failed to load since #8666 The method Path.endsWith(String s) doesn't work exactly the same way as String.endsWith() (see http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#endsWith(java.nio.file.Path)). This blocks the loading of plugins. --- .../elasticsearch/plugins/PluginsService.java | 21 ++- .../plugins/PluginServiceTests.java | 120 ++++++++++++++++++ .../loading/classpath/InClassPathPlugin.java | 35 +++++ .../classpath/es-plugin-test.properties | 19 +++ .../plugins/loading/jar/in-jar-plugin.jar | Bin 0 -> 2039 bytes .../plugins/loading/zip/in-zip-plugin.jar | Bin 0 -> 2042 bytes 6 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 src/test/java/org/elasticsearch/plugins/PluginServiceTests.java create mode 100644 src/test/java/org/elasticsearch/plugins/loading/classpath/InClassPathPlugin.java create mode 100644 src/test/java/org/elasticsearch/plugins/loading/classpath/es-plugin-test.properties create mode 100644 src/test/resources/org/elasticsearch/plugins/loading/jar/in-jar-plugin.jar create mode 100644 src/test/resources/org/elasticsearch/plugins/loading/zip/in-zip-plugin.jar diff --git a/src/main/java/org/elasticsearch/plugins/PluginsService.java b/src/main/java/org/elasticsearch/plugins/PluginsService.java index 9a7e3c2ce57..a4e6d735410 100644 --- a/src/main/java/org/elasticsearch/plugins/PluginsService.java +++ b/src/main/java/org/elasticsearch/plugins/PluginsService.java @@ -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 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 stream = Files.newDirectoryStream(from)) { return Iterators.toArray(stream.iterator(), Path.class); diff --git a/src/test/java/org/elasticsearch/plugins/PluginServiceTests.java b/src/test/java/org/elasticsearch/plugins/PluginServiceTests.java new file mode 100644 index 00000000000..50328f93d43 --- /dev/null +++ b/src/test/java/org/elasticsearch/plugins/PluginServiceTests.java @@ -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> plugins = pluginsService.plugins(); + + if ((plugins != null) && (!plugins.isEmpty())) { + for (Tuple 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"; + } + } +} diff --git a/src/test/java/org/elasticsearch/plugins/loading/classpath/InClassPathPlugin.java b/src/test/java/org/elasticsearch/plugins/loading/classpath/InClassPathPlugin.java new file mode 100644 index 00000000000..cf4959e62d1 --- /dev/null +++ b/src/test/java/org/elasticsearch/plugins/loading/classpath/InClassPathPlugin.java @@ -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"; + } +} diff --git a/src/test/java/org/elasticsearch/plugins/loading/classpath/es-plugin-test.properties b/src/test/java/org/elasticsearch/plugins/loading/classpath/es-plugin-test.properties new file mode 100644 index 00000000000..f57bea58cf2 --- /dev/null +++ b/src/test/java/org/elasticsearch/plugins/loading/classpath/es-plugin-test.properties @@ -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 \ No newline at end of file diff --git a/src/test/resources/org/elasticsearch/plugins/loading/jar/in-jar-plugin.jar b/src/test/resources/org/elasticsearch/plugins/loading/jar/in-jar-plugin.jar new file mode 100644 index 0000000000000000000000000000000000000000..6b854823f143c7bdd70d89922b98b63beb1331da GIT binary patch literal 2039 zcmWIWW@h1H00FV&4p%S(O0WRw{GxRI0Guj>pej;x5{pYRlZ#Umi;^?&sF%X3z96SG zJu|Nuk3J>5`f~CUQ!?`q?&JXbME~aUr%sFv3>Hib48}z1_ssK3ED8WSMlTuYqvEL( ze7z4l2(;bL{grB;vo^j$VDa*>j)R+(L>xD;2x{;3pS<<%EVb0hzjl97srbPDWAPEs zpe0kP3ivm_KeO-rnGNyx<>xb;+ZgZ2xYlUf=^L7f+gofKA1&nysZmYXV$Iz6r}Twq zW7}e;O7r=AOY4>_JU?}s@UAEP9;;R2MLvIwaAn#i{A!|ZZCBD$w@F*9x26B9S<-ak zoAaj-gH8F(axZ^xsW_P65d5tCmTbC{e#-A7)9TjTJh?v9-)&vk=7`otho$o8wrb~x z7;W5n<++Yyw#Firfbd3B#oW|n*1lb7YG);Po;R5^@8qmAao-Qtcv(mOzZJRQ@Am!H zJxRWKb0Q0SZ2lJ)@pPov_NAW7*~fan^>TTKxtL{6fzGm{%pn%njF?xgIk2nmENhN# z!s4mbv5x%H10IX#u5s)Q{gR@4%O^J49+q?_}u^e>Nb$)%M8CE;-5B8#`}J zQaf4v`TOE0B_FmWml|q(ocR9Z#n)d?pIdEur^xqKF!R9!>)hpcd}~?vF5wEVrNOKN z77{(mD|-3*`jZX(Cj9MT$&tP2U{%2?D%jGuK!gA1RX)Ev!X|IhrX>s7*M)@Eev+DKt4!)kTVVBL?do?}}7|%0ZRXgw^GjR62tWAy_+`A8c z>)EB|@hfP)x2Wok_MKcak{vvctFWKRoXM_nOC{V-yy@?TyMC9K7)%U3w)J*;>Fwy5 z*@18GaXoC=aoM&~|L`x%O_Mq0&o_kqxKbf9&DQVY-ju*i5ga~#%hulRZP;ts%6a#` z+}VBlCp({|HuZ3CT@W70TDi69eB{({=^f|!&7a<7e7E_poi^XkbxlS5;i-jljEX7Ozc&|+n|G)Qxu2SrWml+ssl+}|9&~NVd7K?izTU_n*R7tpYi$9|Ks11Pyd>1u_R+>Z&uxhRpt`m5l??< z?|T38lQ}G9FffRt6+8UEl;P_d;;8HC=cb>VSeBZHR5G9|*2Gi{EVA@a3M4(u0tVd} zBT|fkrddOvvly8~m~j`LKtq8*fZ?wrh=vrUxOIREQwRX*z+U9xvk_FdBJ>9VnIIcc zLP8%A61d#~vKazE?&tzCahroEdST{aFMMGpZfQJ4lzA9MF~Z~6ixPwdvB2^kXTgFn z279`L7$d;&|9?5K_QObpFi&D?2BkxU<|UY#@uf=K#)8r%!r0fO7>krjS=m5la01~n KVBlD@f_MPqy{F~? literal 0 HcmV?d00001 diff --git a/src/test/resources/org/elasticsearch/plugins/loading/zip/in-zip-plugin.jar b/src/test/resources/org/elasticsearch/plugins/loading/zip/in-zip-plugin.jar new file mode 100644 index 0000000000000000000000000000000000000000..6b35430f34d284078c90432f6633d772047f75ce GIT binary patch literal 2042 zcmWIWW@h1H0D(^_9j;&olwbkU`9!sCKsnB7A0rkQ7?s6eL+rX zdS+fR9(_u9_2uLzrex+J+{ppX0&Vwmf2G>ztPTCB;O3vJ$acOffW?tRDWvMdHs5O{rgvL>Umc8Js(!H9{(!uy z-z24_SDLG5)TV!{O>6u6>)#KSg08(%UN1s6#=35An#)xtdFpx4$tO(*Uwl2zbM*8D zVIEy~twQ7ZzAgJ6Pj1kXRWGSDcowzn=b{LoWkzWm<_7%U#!)fH!(1$8cd#|rvwa~O zWn1n{KDB-Q)xAA=n;%IwcAf8d|LxZ~<@#r32TmG!nOMHu`mXcFRU@yI6%tvC3)aOJ zs$TAVyVOoy^Ol38Xxp-oYu!C-YIF`iyl`fzWa0PD--nDnizg?1R(zfEH#@!U-u-_M zRs2lKC*SE(7I``Ua&p7c*MVz-(k`EUp~rjg;5`qK4UQYFCyy)? z&UkU-aLOJ3j3s8*Oxew(suOg@nU8VEY<-b+ZS9w>>Bn=$S+dl8&z0v~tuN6p`4eMP zD(0DPe9kE-yy;Am>iq6kyfxF4Hr}-UDi(LVv{99 zOHd|E=78$9cZ?H5Siy3w>kXaZlX* zr{R5Zq1v`J6#@^g@7Zya;pCbng0@lOq8z?`%}b&V-nXqv61eX2$m3?vQQmMR-|foV zSl0gZ^*e66@d?|vi~jmN*^!-%&QWUmC(?HvnKS*L{WkgNYw|}GT~FtRd~OckdvM1g zt?TwT>b$4d!;=PP$-@s!8osU}j=G+HZu+^2WvO|13I|P0#lTWa52Z}fBV5K9kzx!q z(Ha7s#mFSWjJx~<8VUpg41XO#G^8}etpik^LI6ky_EHa@jiB-sp+5-71lfoZ68eac z!0ir@%@6=`M;DNZ+Z;sc3o{RU`3o~~OXDe`%)=;+5gx~0mLM#M2NwA_OBRGN*wY=v z7y*X=|Equ%AVw;Lc@k4IC>