SOLR-5401: SolrResourceLoader logs a warning if a deprecated (factory) class is used in schema or config

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1537119 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2013-10-30 14:56:39 +00:00
parent 47480a8496
commit 33298abc3f
3 changed files with 82 additions and 43 deletions

View File

@ -186,6 +186,9 @@ Other Changes
* SOLR-5321: Remove unnecessary code in Overseer.updateState method which tries to
use router name from message where none is ever sent. (shalin)
* SOLR-5401: SolrResourceLoader logs a warning if a deprecated (factory) class
is used in schema or config. (Uwe Schindler)
================== 4.5.1 ==================
Versions of Major Components

View File

@ -426,56 +426,66 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
}
}
Class<? extends T> clazz = null;
// first try legacy analysis patterns, now replaced by Lucene's Analysis package:
final Matcher m = legacyAnalysisPattern.matcher(cname);
if (m.matches()) {
final String name = m.group(4);
log.trace("Trying to load class from analysis SPI using name='{}'", name);
try {
if (CharFilterFactory.class.isAssignableFrom(expectedType)) {
return clazz = CharFilterFactory.lookupClass(name).asSubclass(expectedType);
} else if (TokenizerFactory.class.isAssignableFrom(expectedType)) {
return clazz = TokenizerFactory.lookupClass(name).asSubclass(expectedType);
} else if (TokenFilterFactory.class.isAssignableFrom(expectedType)) {
return clazz = TokenFilterFactory.lookupClass(name).asSubclass(expectedType);
} else {
log.warn("'{}' looks like an analysis factory, but caller requested different class type: {}", cname, expectedType.getName());
}
} catch (IllegalArgumentException ex) {
// ok, we fall back to legacy loading
}
}
// first try cname == full name
try {
return Class.forName(cname, true, classLoader).asSubclass(expectedType);
} catch (ClassNotFoundException e) {
String newName=cname;
if (newName.startsWith(project)) {
newName = cname.substring(project.length()+1);
}
for (String subpackage : subpackages) {
// first try legacy analysis patterns, now replaced by Lucene's Analysis package:
final Matcher m = legacyAnalysisPattern.matcher(cname);
if (m.matches()) {
final String name = m.group(4);
log.trace("Trying to load class from analysis SPI using name='{}'", name);
try {
String name = base + '.' + subpackage + newName;
log.trace("Trying class name " + name);
return clazz = Class.forName(name,true,classLoader).asSubclass(expectedType);
} catch (ClassNotFoundException e1) {
// ignore... assume first exception is best.
if (CharFilterFactory.class.isAssignableFrom(expectedType)) {
return clazz = CharFilterFactory.lookupClass(name).asSubclass(expectedType);
} else if (TokenizerFactory.class.isAssignableFrom(expectedType)) {
return clazz = TokenizerFactory.lookupClass(name).asSubclass(expectedType);
} else if (TokenFilterFactory.class.isAssignableFrom(expectedType)) {
return clazz = TokenFilterFactory.lookupClass(name).asSubclass(expectedType);
} else {
log.warn("'{}' looks like an analysis factory, but caller requested different class type: {}", cname, expectedType.getName());
}
} catch (IllegalArgumentException ex) {
// ok, we fall back to legacy loading
}
}
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "Error loading class '" + cname + "'", e);
}finally{
//cache the shortname vs FQN if it is loaded by the webapp classloader and it is loaded
// using a shortname
if ( clazz != null &&
clazz.getClassLoader() == SolrResourceLoader.class.getClassLoader() &&
// first try cname == full name
try {
return clazz = Class.forName(cname, true, classLoader).asSubclass(expectedType);
} catch (ClassNotFoundException e) {
String newName=cname;
if (newName.startsWith(project)) {
newName = cname.substring(project.length()+1);
}
for (String subpackage : subpackages) {
try {
String name = base + '.' + subpackage + newName;
log.trace("Trying class name " + name);
return clazz = Class.forName(name,true,classLoader).asSubclass(expectedType);
} catch (ClassNotFoundException e1) {
// ignore... assume first exception is best.
}
}
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "Error loading class '" + cname + "'", e);
}
} finally {
if (clazz != null) {
//cache the shortname vs FQN if it is loaded by the webapp classloader and it is loaded
// using a shortname
if (clazz.getClassLoader() == SolrResourceLoader.class.getClassLoader() &&
!cname.equals(clazz.getName()) &&
(subpackages.length == 0 || subpackages == packages)) {
//store in the cache
classNameCache.put(cname, clazz.getName());
//store in the cache
classNameCache.put(cname, clazz.getName());
}
// print warning if class is deprecated
if (clazz.isAnnotationPresent(Deprecated.class)) {
log.warn("Solr loaded a deprecated plugin/analysis class [{}]. Please consult documentation how to replace it accordingly.",
cname);
}
}
}
}

View File

@ -19,6 +19,7 @@ package org.apache.solr.core;
import junit.framework.Assert;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.KeywordTokenizerFactory;
import org.apache.lucene.analysis.ngram.NGramFilterFactory;
import org.apache.lucene.util._TestUtil;
@ -28,6 +29,7 @@ import org.apache.solr.handler.admin.LukeRequestHandler;
import org.apache.solr.handler.component.FacetComponent;
import org.apache.solr.response.JSONResponseWriter;
import org.apache.lucene.analysis.util.ResourceLoaderAware;
import org.apache.lucene.analysis.util.TokenFilterFactory;
import org.apache.solr.util.plugin.SolrCoreAware;
import java.io.File;
@ -39,6 +41,7 @@ import java.nio.charset.CharacterCodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@ -212,4 +215,27 @@ public class ResourceLoaderTest extends SolrTestCaseJ4
assertNotNull(loader.getClassLoader().getResource("otherFile"));
loader.close();
}
@Deprecated
public static final class DeprecatedTokenFilterFactory extends TokenFilterFactory {
public DeprecatedTokenFilterFactory(Map<String,String> args) {
super(args);
}
@Override
public TokenStream create(TokenStream input) {
return null;
}
}
public void testLoadDeprecatedFactory() throws Exception {
SolrResourceLoader loader = new SolrResourceLoader("solr/collection1");
// ensure we get our exception
loader.newInstance(DeprecatedTokenFilterFactory.class.getName(), TokenFilterFactory.class, null,
new Class[] { Map.class }, new Object[] { new HashMap<String,String>() });
// TODO: How to check that a warning was printed to log file?
loader.close();
}
}