mirror of https://github.com/apache/lucene.git
Fix for SOLR-4791, sharedLib in solr.xml doesn't work
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1480228 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a039f476c8
commit
dcc27e14b6
|
@ -270,7 +270,7 @@ public class CoreContainer
|
||||||
if (libDir != null) {
|
if (libDir != null) {
|
||||||
File f = FileUtils.resolvePath(new File(dir), libDir);
|
File f = FileUtils.resolvePath(new File(dir), libDir);
|
||||||
log.info("loading shared library: " + f.getAbsolutePath());
|
log.info("loading shared library: " + f.getAbsolutePath());
|
||||||
loader.addToClassLoader(libDir);
|
loader.addToClassLoader(libDir, null, false);
|
||||||
loader.reloadLuceneSPI();
|
loader.reloadLuceneSPI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ package org.apache.solr.core;
|
||||||
|
|
||||||
import org.apache.solr.common.SolrException;
|
import org.apache.solr.common.SolrException;
|
||||||
import org.apache.solr.common.SolrException.ErrorCode;
|
import org.apache.solr.common.SolrException.ErrorCode;
|
||||||
import org.apache.solr.schema.IndexSchema;
|
|
||||||
import org.apache.solr.schema.IndexSchemaFactory;
|
import org.apache.solr.schema.IndexSchemaFactory;
|
||||||
import org.apache.solr.util.DOMUtil;
|
import org.apache.solr.util.DOMUtil;
|
||||||
|
import org.apache.solr.util.FileUtils;
|
||||||
import org.apache.solr.util.RegexFileFilter;
|
import org.apache.solr.util.RegexFileFilter;
|
||||||
import org.apache.solr.handler.component.SearchComponent;
|
import org.apache.solr.handler.component.SearchComponent;
|
||||||
import org.apache.solr.request.SolrRequestHandler;
|
import org.apache.solr.request.SolrRequestHandler;
|
||||||
|
@ -51,6 +51,7 @@ import org.xml.sax.SAXException;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -453,6 +454,7 @@ public class SolrConfig extends Config {
|
||||||
if (nodes == null || nodes.getLength() == 0) return;
|
if (nodes == null || nodes.getLength() == 0) return;
|
||||||
|
|
||||||
log.info("Adding specified lib dirs to ClassLoader");
|
log.info("Adding specified lib dirs to ClassLoader");
|
||||||
|
SolrResourceLoader loader = getResourceLoader();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < nodes.getLength(); i++) {
|
for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
|
@ -464,16 +466,22 @@ public class SolrConfig extends Config {
|
||||||
// :TODO: add support for a simpler 'glob' mutually exclusive of regex
|
// :TODO: add support for a simpler 'glob' mutually exclusive of regex
|
||||||
String regex = DOMUtil.getAttr(node, "regex");
|
String regex = DOMUtil.getAttr(node, "regex");
|
||||||
FileFilter filter = (null == regex) ? null : new RegexFileFilter(regex);
|
FileFilter filter = (null == regex) ? null : new RegexFileFilter(regex);
|
||||||
getResourceLoader().addToClassLoader(baseDir, filter, false);
|
loader.addToClassLoader(baseDir, filter, false);
|
||||||
} else if (null != path) {
|
} else if (null != path) {
|
||||||
getResourceLoader().addToClassLoader(path);
|
final File file = FileUtils.resolvePath(new File(loader.getInstanceDir()), path);
|
||||||
|
loader.addToClassLoader(file.getParent(), new FileFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(File pathname) {
|
||||||
|
return pathname.equals(file);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"lib: missing mandatory attributes: 'dir' or 'path'");
|
"lib: missing mandatory attributes: 'dir' or 'path'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
getResourceLoader().reloadLuceneSPI();
|
loader.reloadLuceneSPI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,9 +152,11 @@ public class SolrResourceLoader implements ResourceLoader
|
||||||
File base = FileUtils.resolvePath(new File(getInstanceDir()), baseDir);
|
File base = FileUtils.resolvePath(new File(getInstanceDir()), baseDir);
|
||||||
if (base != null && base.exists() && base.isDirectory()) {
|
if (base != null && base.exists() && base.isDirectory()) {
|
||||||
File[] files = base.listFiles(filter);
|
File[] files = base.listFiles(filter);
|
||||||
if (!quiet && (files == null || files.length == 0)) {
|
if (files == null || files.length == 0) {
|
||||||
log.warn("No files added to classloader from lib: "
|
if (!quiet) {
|
||||||
+ baseDir + " (resolved as: " + base.getAbsolutePath() + ").");
|
log.warn("No files added to classloader from lib: "
|
||||||
|
+ baseDir + " (resolved as: " + base.getAbsolutePath() + ").");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.classLoader = replaceClassLoader(classLoader, base, filter);
|
this.classLoader = replaceClassLoader(classLoader, base, filter);
|
||||||
}
|
}
|
||||||
|
@ -166,34 +168,9 @@ public class SolrResourceLoader implements ResourceLoader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specific file/dir specified to the ClassLoader used by this
|
|
||||||
* ResourceLoader. This method <b>MUST</b>
|
|
||||||
* only be called prior to using this ResourceLoader to get any resources, otherwise
|
|
||||||
* it's behavior will be non-deterministic. You also have to {link #reloadLuceneSPI()}
|
|
||||||
* before using this ResourceLoader.
|
|
||||||
*
|
|
||||||
* @param path A jar file (or directory of classes) to be added to the classpath,
|
|
||||||
* will be resolved relative the instance dir.
|
|
||||||
*/
|
|
||||||
void addToClassLoader(final String path) {
|
|
||||||
final File file = FileUtils.resolvePath(new File(getInstanceDir()), path);
|
|
||||||
if (file.canRead()) {
|
|
||||||
this.classLoader = replaceClassLoader(classLoader, file.getParentFile(),
|
|
||||||
new FileFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean accept(File pathname) {
|
|
||||||
return pathname.equals(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
log.error("Can't find (or read) file to add to classloader: " + file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads all Lucene SPI implementations using the new classloader.
|
* Reloads all Lucene SPI implementations using the new classloader.
|
||||||
* This method must be called after {@link #addToClassLoader(String)}
|
* This method must be called after {@link #addToClassLoader(String, FileFilter, boolean)}
|
||||||
* and {@link #addToClassLoader(String,FileFilter,boolean)} before using
|
* and {@link #addToClassLoader(String,FileFilter,boolean)} before using
|
||||||
* this ResourceLoader.
|
* this ResourceLoader.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,6 +22,7 @@ import junit.framework.Assert;
|
||||||
import org.apache.lucene.util.LuceneTestCase;
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
import org.apache.lucene.analysis.core.KeywordTokenizerFactory;
|
import org.apache.lucene.analysis.core.KeywordTokenizerFactory;
|
||||||
import org.apache.lucene.analysis.ngram.NGramFilterFactory;
|
import org.apache.lucene.analysis.ngram.NGramFilterFactory;
|
||||||
|
import org.apache.lucene.util._TestUtil;
|
||||||
import org.apache.solr.common.SolrException;
|
import org.apache.solr.common.SolrException;
|
||||||
import org.apache.solr.handler.admin.LukeRequestHandler;
|
import org.apache.solr.handler.admin.LukeRequestHandler;
|
||||||
import org.apache.solr.handler.component.FacetComponent;
|
import org.apache.solr.handler.component.FacetComponent;
|
||||||
|
@ -30,11 +31,15 @@ import org.apache.lucene.analysis.util.ResourceLoaderAware;
|
||||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.CharacterCodingException;
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
|
||||||
public class ResourceLoaderTest extends LuceneTestCase
|
public class ResourceLoaderTest extends LuceneTestCase
|
||||||
{
|
{
|
||||||
|
@ -131,4 +136,50 @@ public class ResourceLoaderTest extends LuceneTestCase
|
||||||
assertTrue(expected.getCause() instanceof CharacterCodingException);
|
assertTrue(expected.getCause() instanceof CharacterCodingException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testClassLoaderLibs() throws Exception {
|
||||||
|
File tmpRoot = _TestUtil.getTempDir("testClassLoaderLibs");
|
||||||
|
|
||||||
|
File lib = new File(tmpRoot, "lib");
|
||||||
|
lib.mkdirs();
|
||||||
|
|
||||||
|
JarOutputStream jar1 = new JarOutputStream(new FileOutputStream(new File(lib, "jar1.jar")));
|
||||||
|
jar1.putNextEntry(new JarEntry("aLibFile"));
|
||||||
|
jar1.closeEntry();
|
||||||
|
jar1.close();
|
||||||
|
|
||||||
|
File otherLib = new File(tmpRoot, "otherLib");
|
||||||
|
otherLib.mkdirs();
|
||||||
|
|
||||||
|
JarOutputStream jar2 = new JarOutputStream(new FileOutputStream(new File(otherLib, "jar2.jar")));
|
||||||
|
jar2.putNextEntry(new JarEntry("explicitFile"));
|
||||||
|
jar2.closeEntry();
|
||||||
|
jar2.close();
|
||||||
|
JarOutputStream jar3 = new JarOutputStream(new FileOutputStream(new File(otherLib, "jar3.jar")));
|
||||||
|
jar3.putNextEntry(new JarEntry("otherFile"));
|
||||||
|
jar3.closeEntry();
|
||||||
|
jar3.close();
|
||||||
|
|
||||||
|
SolrResourceLoader loader = new SolrResourceLoader(tmpRoot.getAbsolutePath());
|
||||||
|
|
||||||
|
// ./lib is accessible by default
|
||||||
|
assertNotNull(loader.getClassLoader().getResource("aLibFile"));
|
||||||
|
|
||||||
|
// file filter works (and doesn't add other files in the same dir)
|
||||||
|
final File explicitFileJar = new File(otherLib, "jar2.jar").getAbsoluteFile();
|
||||||
|
loader.addToClassLoader("otherLib",
|
||||||
|
new FileFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(File pathname) {
|
||||||
|
return pathname.equals(explicitFileJar);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
assertNotNull(loader.getClassLoader().getResource("explicitFile"));
|
||||||
|
assertNull(loader.getClassLoader().getResource("otherFile"));
|
||||||
|
|
||||||
|
|
||||||
|
// null file filter means accept all (making otherFile accessible)
|
||||||
|
loader.addToClassLoader("otherLib", null, false);
|
||||||
|
assertNotNull(loader.getClassLoader().getResource("otherFile"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,14 @@ import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.lucene.util.IOUtils;
|
import org.apache.lucene.util.IOUtils;
|
||||||
|
import org.apache.lucene.util._TestUtil;
|
||||||
import org.apache.solr.SolrTestCaseJ4;
|
import org.apache.solr.SolrTestCaseJ4;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -335,6 +338,55 @@ public class TestCoreContainer extends SolrTestCaseJ4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSharedLib() throws Exception {
|
||||||
|
File tmpRoot = _TestUtil.getTempDir("testSharedLib");
|
||||||
|
|
||||||
|
File lib = new File(tmpRoot, "lib");
|
||||||
|
lib.mkdirs();
|
||||||
|
|
||||||
|
JarOutputStream jar1 = new JarOutputStream(new FileOutputStream(new File(lib, "jar1.jar")));
|
||||||
|
jar1.putNextEntry(new JarEntry("defaultSharedLibFile"));
|
||||||
|
jar1.closeEntry();
|
||||||
|
jar1.close();
|
||||||
|
|
||||||
|
File customLib = new File(tmpRoot, "customLib");
|
||||||
|
customLib.mkdirs();
|
||||||
|
|
||||||
|
JarOutputStream jar2 = new JarOutputStream(new FileOutputStream(new File(customLib, "jar2.jar")));
|
||||||
|
jar2.putNextEntry(new JarEntry("customSharedLibFile"));
|
||||||
|
jar2.closeEntry();
|
||||||
|
jar2.close();
|
||||||
|
|
||||||
|
FileUtils.writeStringToFile(new File(tmpRoot, "default-lib-solr.xml"), "<solr><cores/></solr>", "UTF-8");
|
||||||
|
FileUtils.writeStringToFile(new File(tmpRoot, "explicit-lib-solr.xml"), "<solr sharedLib=\"lib\"><cores/></solr>", "UTF-8");
|
||||||
|
FileUtils.writeStringToFile(new File(tmpRoot, "custom-lib-solr.xml"), "<solr sharedLib=\"customLib\"><cores/></solr>", "UTF-8");
|
||||||
|
|
||||||
|
final CoreContainer cc1 = new CoreContainer(tmpRoot.getAbsolutePath());
|
||||||
|
cc1.load(tmpRoot.getAbsolutePath(), new File(tmpRoot, "default-lib-solr.xml"));
|
||||||
|
try {
|
||||||
|
cc1.loader.openResource("defaultSharedLibFile").close();
|
||||||
|
} finally {
|
||||||
|
cc1.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
final CoreContainer cc2 = new CoreContainer(tmpRoot.getAbsolutePath());
|
||||||
|
cc2.load(tmpRoot.getAbsolutePath(), new File(tmpRoot, "explicit-lib-solr.xml"));
|
||||||
|
try {
|
||||||
|
cc2.loader.openResource("defaultSharedLibFile").close();
|
||||||
|
} finally {
|
||||||
|
cc2.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
final CoreContainer cc3 = new CoreContainer(tmpRoot.getAbsolutePath());
|
||||||
|
cc3.load(tmpRoot.getAbsolutePath(), new File(tmpRoot, "custom-lib-solr.xml"));
|
||||||
|
try {
|
||||||
|
cc3.loader.openResource("customSharedLibFile").close();
|
||||||
|
} finally {
|
||||||
|
cc3.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final String EMPTY_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
|
private static final String EMPTY_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
|
||||||
"<solr persistent=\"false\">\n" +
|
"<solr persistent=\"false\">\n" +
|
||||||
" <cores adminPath=\"/admin/cores\" transientCacheSize=\"32\" >\n" +
|
" <cores adminPath=\"/admin/cores\" transientCacheSize=\"32\" >\n" +
|
||||||
|
|
Loading…
Reference in New Issue