From be366c729fabc0589053df3900ff2bf3b6ef36c6 Mon Sep 17 00:00:00 2001 From: Robert Muir Date: Fri, 21 Aug 2015 20:12:30 -0400 Subject: [PATCH] Lucene SPI support for plugins. When we create a plugin's classloader, we should allow it to register things in the lucene SPI (registry of Tokenizers, TokenFilters, CharFilters, Codec, PostingsFormat, DocValuesFormat). Plugins should be able to do this so they can extend Lucene. --- .../elasticsearch/plugins/PluginsService.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/elasticsearch/plugins/PluginsService.java b/core/src/main/java/org/elasticsearch/plugins/PluginsService.java index e036b92436014..8b3488ef4da3f 100644 --- a/core/src/main/java/org/elasticsearch/plugins/PluginsService.java +++ b/core/src/main/java/org/elasticsearch/plugins/PluginsService.java @@ -22,9 +22,14 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import org.apache.lucene.analysis.util.CharFilterFactory; +import org.apache.lucene.analysis.util.TokenFilterFactory; +import org.apache.lucene.analysis.util.TokenizerFactory; +import org.apache.lucene.codecs.Codec; +import org.apache.lucene.codecs.DocValuesFormat; +import org.apache.lucene.codecs.PostingsFormat; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.admin.cluster.node.info.PluginsInfo; -import org.elasticsearch.bootstrap.Bootstrap; import org.elasticsearch.bootstrap.JarHell; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.MapBuilder; @@ -348,6 +353,8 @@ private List> loadBundles(List bundles) { for (PluginInfo pluginInfo : bundle.plugins) { final Plugin plugin; if (pluginInfo.isJvm()) { + // reload lucene SPI with any new services from the plugin + reloadLuceneSPI(loader); plugin = loadPlugin(pluginInfo.getClassname(), settings, loader); } else { plugin = new SitePlugin(pluginInfo.getName(), pluginInfo.getDescription()); @@ -359,6 +366,24 @@ private List> loadBundles(List bundles) { return plugins.build(); } + /** + * Reloads all Lucene SPI implementations using the new classloader. + * This method must be called after the new classloader has been created to + * register the services for use. + */ + static void reloadLuceneSPI(ClassLoader loader) { + // do NOT change the order of these method calls! + + // Codecs: + PostingsFormat.reloadPostingsFormats(loader); + DocValuesFormat.reloadDocValuesFormats(loader); + Codec.reloadCodecs(loader); + // Analysis: + CharFilterFactory.reloadCharFilters(loader); + TokenFilterFactory.reloadTokenFilters(loader); + TokenizerFactory.reloadTokenizers(loader); + } + private Plugin loadPlugin(String className, Settings settings, ClassLoader loader) { try { Class pluginClass = loader.loadClass(className).asSubclass(Plugin.class);