You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2012/07/24 20:44:41 UTC

svn commit: r1365215 - in /lucene/dev/branches/lucene2510: lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/ lucene/analysis/common/src/java/org/apache/lucene/analysis/util/ solr/core/src/java/org/apache/solr/analysis/ solr/core/src/j...

Author: uschindler
Date: Tue Jul 24 18:44:40 2012
New Revision: 1365215

URL: http://svn.apache.org/viewvc?rev=1365215&view=rev
Log:
LUCENE-2510: Make the SOLR backwards layer be implemented directly inside SolrResourceLoader (sorry for the generics and still needed suppress warnings... - maybe somebody has an idea for the map inside map)

Removed:
    lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/analysis/AnalysisPluginLoader.java
Modified:
    lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilterFactory.java
    lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java
    lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/CharFilterFactory.java
    lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenFilterFactory.java
    lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenizerFactory.java
    lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
    lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java

Modified: lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilterFactory.java?rev=1365215&r1=1365214&r2=1365215&view=diff
==============================================================================
--- lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilterFactory.java (original)
+++ lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilterFactory.java Tue Jul 24 18:44:40 2012
@@ -152,7 +152,6 @@ public class SynonymFilterFactory extend
     return parser.build();
   }
   
-  // nocommit: spi-hack solr.xxx and o.a.solr.analysis.xxx via a delegator
   // (there are no tests for this functionality)
   private TokenizerFactory loadTokenizerFactory(ResourceLoader loader, String cname){
     TokenizerFactory tokFactory = loader.newInstance(cname, TokenizerFactory.class);

Modified: lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java?rev=1365215&r1=1365214&r2=1365215&view=diff
==============================================================================
--- lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java (original)
+++ lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AnalysisSPILoader.java Tue Jul 24 18:44:40 2012
@@ -28,7 +28,7 @@ import org.apache.lucene.util.SPIClassIt
  * Helper class for loading named SPIs from classpath (e.g. Tokenizers, TokenStreams).
  * @lucene.internal
  */
-final class AnalysisSPILoader<S extends AbstractAnalysisFactory> {
+public final class AnalysisSPILoader<S extends AbstractAnalysisFactory> {
 
   private final Map<String,Class<? extends S>> services;
   private final Class<S> clazz;
@@ -37,9 +37,17 @@ final class AnalysisSPILoader<S extends 
     this(clazz, new String[] { clazz.getSimpleName() });
   }
 
+  public AnalysisSPILoader(Class<S> clazz, ClassLoader loader) {
+    this(clazz, new String[] { clazz.getSimpleName() }, loader);
+  }
+
   public AnalysisSPILoader(Class<S> clazz, String[] suffixes) {
+    this(clazz, suffixes, Thread.currentThread().getContextClassLoader());
+  }
+  
+  public AnalysisSPILoader(Class<S> clazz, String[] suffixes, ClassLoader classloader) {
     this.clazz = clazz;
-    final SPIClassIterator<S> loader = SPIClassIterator.get(clazz);
+    final SPIClassIterator<S> loader = SPIClassIterator.get(clazz, classloader);
     final LinkedHashMap<String,Class<? extends S>> services = new LinkedHashMap<String,Class<? extends S>>();
     while (loader.hasNext()) {
       final Class<? extends S> service = loader.next();

Modified: lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/CharFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/CharFilterFactory.java?rev=1365215&r1=1365214&r2=1365215&view=diff
==============================================================================
--- lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/CharFilterFactory.java (original)
+++ lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/CharFilterFactory.java Tue Jul 24 18:44:40 2012
@@ -29,13 +29,23 @@ import org.apache.lucene.analysis.CharFi
 public abstract class CharFilterFactory extends AbstractAnalysisFactory {
 
   private static final AnalysisSPILoader<CharFilterFactory> loader =
-      new AnalysisSPILoader<CharFilterFactory>(CharFilterFactory.class);
+      getSPILoader(Thread.currentThread().getContextClassLoader());
   
-  /** looks up a charfilter by name */
+  /**
+   * Used by e.g. Apache Solr to get a correctly configured instance
+   * of {@link AnalysisSPILoader} from Solr's classpath.
+   * @lucene.internal
+   */
+  public static AnalysisSPILoader<CharFilterFactory> getSPILoader(ClassLoader classloader) {
+    return new AnalysisSPILoader<CharFilterFactory>(CharFilterFactory.class, classloader);
+  }
+  
+  /** looks up a charfilter by name from context classpath */
   public static CharFilterFactory forName(String name) {
     return loader.newInstance(name);
   }
   
+  /** looks up a charfilter class by name from context classpath */
   public static Class<? extends CharFilterFactory> lookupClass(String name) {
     return loader.lookupClass(name);
   }

Modified: lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenFilterFactory.java?rev=1365215&r1=1365214&r2=1365215&view=diff
==============================================================================
--- lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenFilterFactory.java (original)
+++ lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenFilterFactory.java Tue Jul 24 18:44:40 2012
@@ -28,19 +28,29 @@ import org.apache.lucene.analysis.TokenS
 public abstract class TokenFilterFactory extends AbstractAnalysisFactory {
 
   private static final AnalysisSPILoader<TokenFilterFactory> loader =
-      new AnalysisSPILoader<TokenFilterFactory>(TokenFilterFactory.class, 
-          new String[] { "TokenFilterFactory", "FilterFactory" });
+      getSPILoader(Thread.currentThread().getContextClassLoader());
   
-  /** looks up a tokenfilter by name */
+  /**
+   * Used by e.g. Apache Solr to get a correctly configured instance
+   * of {@link AnalysisSPILoader} from Solr's classpath.
+   * @lucene.internal
+   */
+  public static AnalysisSPILoader<TokenFilterFactory> getSPILoader(ClassLoader classloader) {
+    return new AnalysisSPILoader<TokenFilterFactory>(TokenFilterFactory.class,
+      new String[] { "TokenFilterFactory", "FilterFactory" }, classloader);
+  }
+  
+  /** looks up a tokenfilter by name from context classpath */
   public static TokenFilterFactory forName(String name) {
     return loader.newInstance(name);
   }
   
+  /** looks up a tokenfilter class by name from context classpath */
   public static Class<? extends TokenFilterFactory> lookupClass(String name) {
     return loader.lookupClass(name);
   }
   
-  /** returns a list of all available tokenfilter names */
+  /** returns a list of all available tokenfilter names from context classpath */
   public static Set<String> availableTokenFilters() {
     return loader.availableServices();
   }

Modified: lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenizerFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenizerFactory.java?rev=1365215&r1=1365214&r2=1365215&view=diff
==============================================================================
--- lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenizerFactory.java (original)
+++ lucene/dev/branches/lucene2510/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/TokenizerFactory.java Tue Jul 24 18:44:40 2012
@@ -29,18 +29,28 @@ import java.util.Set;
 public abstract class TokenizerFactory extends AbstractAnalysisFactory {
 
   private static final AnalysisSPILoader<TokenizerFactory> loader =
-      new AnalysisSPILoader<TokenizerFactory>(TokenizerFactory.class);
+      getSPILoader(Thread.currentThread().getContextClassLoader());
   
-  /** looks up a tokenizer by name */
+  /**
+   * Used by e.g. Apache Solr to get a correctly configured instance
+   * of {@link AnalysisSPILoader} from Solr's classpath.
+   * @lucene.internal
+   */
+  public static AnalysisSPILoader<TokenizerFactory> getSPILoader(ClassLoader classloader) {
+    return new AnalysisSPILoader<TokenizerFactory>(TokenizerFactory.class, classloader);
+  }
+  
+  /** looks up a tokenizer by name from context classpath */
   public static TokenizerFactory forName(String name) {
     return loader.newInstance(name);
   }
   
+  /** looks up a tokenizer class by name from context classpath */
   public static Class<? extends TokenizerFactory> lookupClass(String name) {
     return loader.lookupClass(name);
   }
   
-  /** returns a list of all available tokenizer names */
+  /** returns a list of all available tokenizer names from context classpath */
   public static Set<String> availableTokenizers() {
     return loader.availableServices();
   }

Modified: lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java?rev=1365215&r1=1365214&r2=1365215&view=diff
==============================================================================
--- lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java (original)
+++ lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java Tue Jul 24 18:44:40 2012
@@ -29,11 +29,16 @@ import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
+import org.apache.lucene.analysis.util.AbstractAnalysisFactory;
 import org.apache.lucene.analysis.util.CharFilterFactory;
 import org.apache.lucene.analysis.util.ResourceLoaderAware;
 import org.apache.lucene.analysis.util.TokenFilterFactory;
 import org.apache.lucene.analysis.util.TokenizerFactory;
+import org.apache.lucene.analysis.util.AnalysisSPILoader;
+import org.apache.lucene.util.WeakIdentityMap;
 import org.apache.solr.common.ResourceLoader;
 import org.apache.solr.handler.admin.CoreAdminHandler;
 import org.apache.solr.handler.component.ShardHandlerFactory;
@@ -366,8 +371,15 @@ public class SolrResourceLoader implemen
   /*
    * A static map of short class name to fully qualified class name 
    */
-  private static Map<String, String> classNameCache = new ConcurrentHashMap<String, String>();
+  private static final Map<String, String> classNameCache = new ConcurrentHashMap<String, String>();
 
+  // A static map of AnalysisSPILoaders, keyed by ClassLoader used (because it can change during Solr lifetime) and expected base class:
+  private static final WeakIdentityMap<ClassLoader, Map<Class<?>,AnalysisSPILoader<?>>> expectedTypesSPILoaders = WeakIdentityMap.newConcurrentHashMap();
+
+  // Using this pattern, legacy analysis components from previous Solr versions are identified and delegated to SPI loader:
+  private static final Pattern legacyAnalysisPattern = 
+      Pattern.compile("((\\Q"+base+".analysis.\\E)|(\\Q"+project+".\\E))([\\p{L}_$][\\p{L}\\p{N}_$]+?)(TokenFilter|Filter|Tokenizer|CharFilter)Factory");
+      
   /**
    * This method loads a class either with it's FQN or a short-name (solr.class-simplename or class-simplename).
    * It tries to load the class with the name that is given first and if it fails, it tries all the known
@@ -394,6 +406,33 @@ public class SolrResourceLoader implemen
       }
     }
     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()) {
+      log.trace("Trying to load class from analysis SPI");
+      // retrieve the map of classLoader -> expectedType -> SPI from cache / regenerate cache
+      Map<Class<?>,AnalysisSPILoader<?>> spiLoaders = expectedTypesSPILoaders.get(classLoader);
+      if (spiLoaders == null) {
+        spiLoaders = new IdentityHashMap<Class<?>,AnalysisSPILoader<?>>();
+        spiLoaders.put(CharFilterFactory.class, CharFilterFactory.getSPILoader(classLoader));
+        spiLoaders.put(TokenizerFactory.class, TokenizerFactory.getSPILoader(classLoader));
+        spiLoaders.put(TokenFilterFactory.class, TokenFilterFactory.getSPILoader(classLoader));
+        expectedTypesSPILoaders.put(classLoader, spiLoaders);
+      }
+      AnalysisSPILoader<? extends AbstractAnalysisFactory> loader = spiLoaders.get(expectedType);
+      if (loader != null) {
+        // it's a correct expected type for analysis! Let's go on!
+        try {
+          @SuppressWarnings("unchecked")
+          final Class<? extends T> cl = (Class<? extends T>) loader.lookupClass(m.group(4));
+          return clazz = cl;
+        } catch (IllegalArgumentException ex) { 
+          // ok, we fall back to legacy loading
+        }
+      }
+    }
+    
     // first try cname == full name
     try {
       return Class.forName(cname, true, classLoader).asSubclass(expectedType);

Modified: lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java?rev=1365215&r1=1365214&r2=1365215&view=diff
==============================================================================
--- lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java (original)
+++ lucene/dev/branches/lucene2510/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java Tue Jul 24 18:44:40 2012
@@ -22,7 +22,6 @@ import org.apache.lucene.analysis.core.K
 import org.apache.lucene.analysis.core.KeywordTokenizerFactory;
 import org.apache.lucene.analysis.util.*;
 import org.apache.lucene.util.Version;
-import org.apache.solr.analysis.AnalysisPluginLoader;
 import org.apache.solr.analysis.TokenizerChain;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.util.DOMUtil;
@@ -263,16 +262,11 @@ public final class FieldTypePluginLoader
 
     final ArrayList<CharFilterFactory> charFilters 
       = new ArrayList<CharFilterFactory>();
-    AnalysisPluginLoader<CharFilterFactory> charFilterLoader =
-      new AnalysisPluginLoader<CharFilterFactory>
+    AbstractPluginLoader<CharFilterFactory> charFilterLoader =
+      new AbstractPluginLoader<CharFilterFactory>
       ("[schema.xml] analyzer/charFilter", CharFilterFactory.class, false, false) {
 
       @Override
-      protected Class<? extends CharFilterFactory> lookupSPI(String name) {
-        return CharFilterFactory.lookupClass(name);
-      }
-
-      @Override
       protected void init(CharFilterFactory plugin, Node node) throws Exception {
         if( plugin != null ) {
           final Map<String,String> params = DOMUtil.toMapExcept(node.getAttributes(),"class");
@@ -301,15 +295,9 @@ public final class FieldTypePluginLoader
 
     final ArrayList<TokenizerFactory> tokenizers 
       = new ArrayList<TokenizerFactory>(1);
-    AnalysisPluginLoader<TokenizerFactory> tokenizerLoader =
-      new AnalysisPluginLoader<TokenizerFactory>
+    AbstractPluginLoader<TokenizerFactory> tokenizerLoader =
+      new AbstractPluginLoader<TokenizerFactory>
       ("[schema.xml] analyzer/tokenizer", TokenizerFactory.class, false, false) {
-      
-      @Override
-      protected Class<? extends TokenizerFactory> lookupSPI(String name) {
-        return TokenizerFactory.lookupClass(name);
-      }
-
       @Override
       protected void init(TokenizerFactory plugin, Node node) throws Exception {
         if( !tokenizers.isEmpty() ) {
@@ -344,15 +332,9 @@ public final class FieldTypePluginLoader
     final ArrayList<TokenFilterFactory> filters 
       = new ArrayList<TokenFilterFactory>();
 
-    AnalysisPluginLoader<TokenFilterFactory> filterLoader = 
-      new AnalysisPluginLoader<TokenFilterFactory>("[schema.xml] analyzer/filter", TokenFilterFactory.class, false, false)
+    AbstractPluginLoader<TokenFilterFactory> filterLoader = 
+      new AbstractPluginLoader<TokenFilterFactory>("[schema.xml] analyzer/filter", TokenFilterFactory.class, false, false)
     {
-      
-      @Override
-      protected Class<? extends TokenFilterFactory> lookupSPI(String name) {
-        return TokenFilterFactory.lookupClass(name);
-      }
-
       @Override
       protected void init(TokenFilterFactory plugin, Node node) throws Exception {
         if( plugin != null ) {