Index: lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java =================================================================== --- lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java (revision 1455724) +++ lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java (working copy) @@ -52,6 +52,11 @@ public AnalysisSPILoader(Class 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); } Index: lucene/core/src/java/org/apache/lucene/util/NamedSPILoader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/NamedSPILoader.java (revision 1455724) +++ lucene/core/src/java/org/apache/lucene/util/NamedSPILoader.java (working copy) @@ -39,6 +39,11 @@ public NamedSPILoader(Class 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); } Index: lucene/core/src/java/org/apache/lucene/util/SPIClassIterator.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/SPIClassIterator.java (revision 1455724) +++ lucene/core/src/java/org/apache/lucene/util/SPIClassIterator.java (working copy) @@ -54,16 +54,27 @@ return new SPIClassIterator(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 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.emptySet().iterator(); }