LUCENE-4713: The SPI components used to load custom codecs or analysis components were fixed to also scan the Lucene ClassLoader in addition to the context ClassLoader, so Lucene is always able to find its own codecs. The special case of a null context ClassLoader is now also supported.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1455860 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2013-03-13 10:10:33 +00:00
parent 651a15492b
commit bd1a1e5ffc
4 changed files with 31 additions and 4 deletions

View File

@ -74,6 +74,12 @@ Bug Fixes
* LUCENE-4826: PostingsHighlighter was not returning the top N best
scoring passages. (Robert Muir, Mike McCandless)
* LUCENE-4713: The SPI components used to load custom codecs or analysis
components were fixed to also scan the Lucene ClassLoader in addition
to the context ClassLoader, so Lucene is always able to find its own
codecs. The special case of a null context ClassLoader is now also
supported. (Christian Kohlschütter, Uwe Schindler)
======================= Lucene 4.2.0 =======================
Changes in backwards compatibility policy

View File

@ -52,6 +52,11 @@ final class AnalysisSPILoader<S extends AbstractAnalysisFactory> {
public AnalysisSPILoader(Class<S> clazz, String[] suffixes, ClassLoader classloader) {
this.clazz = clazz;
this.suffixes = suffixes;
// if clazz' classloader is not a parent of the given one, we scan clazz's classloader, too:
final ClassLoader clazzClassloader = clazz.getClassLoader();
if (clazzClassloader != null && !SPIClassIterator.isParentClassLoader(clazzClassloader, classloader)) {
reload(clazzClassloader);
}
reload(classloader);
}

View File

@ -39,6 +39,11 @@ public final class NamedSPILoader<S extends NamedSPILoader.NamedSPI> implements
public NamedSPILoader(Class<S> clazz, ClassLoader classloader) {
this.clazz = clazz;
// if clazz' classloader is not a parent of the given one, we scan clazz's classloader, too:
final ClassLoader clazzClassloader = clazz.getClassLoader();
if (clazzClassloader != null && !SPIClassIterator.isParentClassLoader(clazzClassloader, classloader)) {
reload(clazzClassloader);
}
reload(classloader);
}

View File

@ -54,16 +54,27 @@ public final class SPIClassIterator<S> implements Iterator<Class<? extends S>> {
return new SPIClassIterator<S>(clazz, loader);
}
/** Utility method to check if some class loader is a (grand-)parent of or the same as another one.
* This means the child will be able to load all classes from the parent, too. */
public static boolean isParentClassLoader(final ClassLoader parent, ClassLoader child) {
while (child != null) {
if (child == parent) {
return true;
}
child = child.getParent();
}
return false;
}
private SPIClassIterator(Class<S> clazz, ClassLoader loader) {
if (loader == null)
throw new IllegalArgumentException("You must provide a ClassLoader.");
this.clazz = clazz;
this.loader = loader;
try {
this.profilesEnum = loader.getResources(META_INF_SERVICES + clazz.getName());
final String fullName = META_INF_SERVICES + clazz.getName();
this.profilesEnum = (loader == null) ? ClassLoader.getSystemResources(fullName) : loader.getResources(fullName);
} catch (IOException ioe) {
throw new ServiceConfigurationError("Error loading SPI profiles for type " + clazz.getName() + " from classpath", ioe);
}
this.loader = (loader == null) ? ClassLoader.getSystemClassLoader() : loader;
this.linesIterator = Collections.<String>emptySet().iterator();
}