You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dw...@apache.org on 2021/03/10 09:45:55 UTC

[lucene] 14/21: fixed SolrCOreAware and ResourceLoaderAware bugs

This is an automated email from the ASF dual-hosted git repository.

dweiss pushed a commit to branch jira/solr14155
in repository https://gitbox.apache.org/repos/asf/lucene.git

commit e501ef59ec0f1a21193eead845c773d6307d3409
Author: noble <no...@apache.org>
AuthorDate: Sat Dec 28 01:16:31 2019 +1100

    fixed SolrCOreAware and ResourceLoaderAware bugs
---
 .../src/java/org/apache/solr/core/PluginInfo.java  | 18 ++--
 .../java/org/apache/solr/core/SolrClassLoader.java |  7 +-
 .../org/apache/solr/core/SolrResourceLoader.java   | 24 +++++-
 .../org/apache/solr/handler/SchemaHandler.java     |  6 +-
 .../java/org/apache/solr/pkg/PackageLoader.java    | 14 ++++
 .../org/apache/solr/pkg/PackagePluginHolder.java   |  4 +
 .../java/org/apache/solr/schema/IndexSchema.java   | 97 ++++++++++++++--------
 7 files changed, 117 insertions(+), 53 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/core/PluginInfo.java b/solr/core/src/java/org/apache/solr/core/PluginInfo.java
index cfef933..021fcea 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginInfo.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginInfo.java
@@ -41,7 +41,7 @@ import static org.apache.solr.schema.FieldType.CLASS_NAME;
  */
 public class PluginInfo implements MapSerializable {
   public final String name, className, type, pkgName;
-  public final ClassName cName;
+  public final ParsedClassName cName;
   public final NamedList initArgs;
   public final Map<String, String> attributes;
   public final List<PluginInfo> children;
@@ -52,7 +52,7 @@ public class PluginInfo implements MapSerializable {
   public PluginInfo(String type, Map<String, String> attrs, NamedList initArgs, List<PluginInfo> children) {
     this.type = type;
     this.name = attrs.get(NAME);
-    cName = new ClassName(attrs.get(CLASS_NAME));
+    cName = new ParsedClassName(attrs.get(CLASS_NAME));
     this.className = cName.klas;
     this.pkgName = cName.pkg;
     this.initArgs = initArgs;
@@ -65,13 +65,13 @@ public class PluginInfo implements MapSerializable {
    * This checks if it is a package name prefixed classname.
    */
 
-  public static class ClassName {
+  public static class ParsedClassName {
     public final String pkg;
     public final String klas;
-    private final String actual;
+    public final String original;
 
-    public ClassName(String name) {
-      this.actual = name;
+    public ParsedClassName(String name) {
+      this.original = name;
       String pkgName = null;
       String className = name;
       if (name != null) {
@@ -88,7 +88,7 @@ public class PluginInfo implements MapSerializable {
 
     @Override
     public String toString() {
-      return actual;
+      return original;
     }
   }
 
@@ -96,7 +96,7 @@ public class PluginInfo implements MapSerializable {
   public PluginInfo(Node node, String err, boolean requireName, boolean requireClass) {
     type = node.getNodeName();
     name = DOMUtil.getAttr(node, NAME, requireName ? err : null);
-    cName = new ClassName(DOMUtil.getAttr(node, CLASS_NAME, requireClass ? err : null));
+    cName = new ParsedClassName(DOMUtil.getAttr(node, CLASS_NAME, requireClass ? err : null));
     className = cName.klas;
     pkgName = cName.pkg;
     initArgs = DOMUtil.childNodesToNamedList(node);
@@ -128,7 +128,7 @@ public class PluginInfo implements MapSerializable {
     }
     this.type = type;
     this.name = (String) m.get(NAME);
-    cName = new ClassName((String) m.get(CLASS_NAME));
+    cName = new ParsedClassName((String) m.get(CLASS_NAME));
     this.className = cName.klas;
     this.pkgName = cName.pkg;
     attributes = unmodifiableMap(m);
diff --git a/solr/core/src/java/org/apache/solr/core/SolrClassLoader.java b/solr/core/src/java/org/apache/solr/core/SolrClassLoader.java
index b260e07..8995c80 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrClassLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrClassLoader.java
@@ -19,10 +19,13 @@ package org.apache.solr.core;
 
 import java.io.Closeable;
 
-/**A generic interface to load classes
+import org.apache.lucene.analysis.util.ResourceLoader;
+
+/**
+ * A generic interface to load classes and resources. This helps us to avoid using {@link SolrResourceLoader} directly
  *
  */
-public interface SolrClassLoader extends Closeable {
+public interface SolrClassLoader extends Closeable, ResourceLoader {
 
   <T> T newInstance(String cname, Class<T> expectedType, String... subpackages);
 
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index 2ad001b..3927911 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -82,7 +82,7 @@ import org.slf4j.LoggerFactory;
 /**
  * @since solr 1.3
  */
-public class SolrResourceLoader implements ResourceLoader, SolrClassLoader {
+public class SolrResourceLoader implements SolrClassLoader {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   static final String project = "solr";
@@ -698,6 +698,12 @@ public class SolrResourceLoader implements ResourceLoader, SolrClassLoader {
           "Error instantiating class: '" + clazz.getName() + "'", e);
     }
 
+    registerForCallbacks(obj);
+
+    return obj;
+  }
+
+  protected <T> void registerForCallbacks(T obj) {
     if (!live) {
       if (obj instanceof SolrCoreAware) {
         assertAwareCompatibility(SolrCoreAware.class, obj);
@@ -712,8 +718,6 @@ public class SolrResourceLoader implements ResourceLoader, SolrClassLoader {
         infoMBeans.add((SolrInfoBean) obj);
       }
     }
-
-    return obj;
   }
 
 
@@ -742,6 +746,18 @@ public class SolrResourceLoader implements ResourceLoader, SolrClassLoader {
     live = true;
   }
 
+  public void registerSolrCoreAware(SolrCoreAware obj) {
+    assertAwareCompatibility(SolrCoreAware.class, obj);
+    if (live) {
+      //this core is already live
+      if (this.core != null) {
+        obj.inform(this.core);
+      }
+    } else {
+      waitingForCore.add(obj);
+    }
+  }
+
   /**
    * Tell all {@link ResourceLoaderAware} instances about the loader
    */
@@ -924,7 +940,7 @@ public class SolrResourceLoader implements ResourceLoader, SolrClassLoader {
   /**
    * Utility function to throw an exception if the class is invalid
    */
-  static void assertAwareCompatibility(Class aware, Object obj) {
+  public static void assertAwareCompatibility(Class aware, Object obj) {
     Class[] valid = awareCompatibility.get(aware);
     if (valid == null) {
       throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
diff --git a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
index f6a7c95..b33629b 100644
--- a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
@@ -226,12 +226,12 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
       Object v = nl.get("class");
       if (v instanceof String) {
         String klas = (String) v;
-        PluginInfo.ClassName className = new PluginInfo.ClassName(klas);
-        if (className.pkg != null) {
+        PluginInfo.ParsedClassName parsedClassName = new PluginInfo.ParsedClassName(klas);
+        if (parsedClassName.pkg != null) {
           req.getCore().getPackageListeners().forEachListener(listener -> {
             PluginInfo pluginInfo = listener.pluginInfo();
             if (pluginInfo == null) return;
-            if (Objects.equals(pluginInfo.cName.toString(), className.toString())) {
+            if (Objects.equals(pluginInfo.cName.toString(), parsedClassName.toString())) {
               nl.add("_packageinfo_", listener.getPackageVersion());
             }
           });
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackageLoader.java b/solr/core/src/java/org/apache/solr/pkg/PackageLoader.java
index c9ef000..178d3a5 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackageLoader.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackageLoader.java
@@ -34,6 +34,7 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import org.apache.lucene.analysis.util.ResourceLoaderAware;
 import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.core.CoreContainer;
@@ -269,6 +270,19 @@ public class PackageLoader implements Closeable {
             protected void initSPI() {
               //no op
             }
+
+            @Override
+            protected <T> void registerForCallbacks(T obj) {
+              if (obj instanceof ResourceLoaderAware) {
+                assertAwareCompatibility(ResourceLoaderAware.class, obj);
+                try {
+                  ((ResourceLoaderAware) obj).inform(this);
+                } catch (IOException e) {
+                  throw new RuntimeException(e);
+                }
+
+              }
+            }
           };
         } catch (MalformedURLException e) {
           log.error("Could not load classloader ", e);
diff --git a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
index b15c524..1cdd104 100644
--- a/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
+++ b/solr/core/src/java/org/apache/solr/pkg/PackagePluginHolder.java
@@ -24,6 +24,7 @@ import org.apache.solr.core.PluginInfo;
 import org.apache.solr.core.RequestParams;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrCore;
+import org.apache.solr.util.plugin.SolrCoreAware;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -120,6 +121,9 @@ public class PackagePluginHolder<T> extends PluginBag.PluginHolder<T> {
     Object instance = SolrCore.createInstance(pluginInfo.className,
         pluginMeta.clazz, pluginMeta.getCleanTag(), core, newest.getLoader());
     PluginBag.initInstance(instance, pluginInfo);
+    if (instance instanceof SolrCoreAware) {
+      core.getResourceLoader().registerSolrCoreAware((SolrCoreAware) instance);
+    }
     T old = inst;
     inst = (T) instance;
     if (old instanceof AutoCloseable) {
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
index ab8d49b..8650b6d 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -21,6 +21,7 @@ import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpressionException;
 import java.io.Closeable;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Writer;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
@@ -228,52 +229,38 @@ public class IndexSchema implements Closeable {
     }
 
     @Override
+    public InputStream openResource(String resource) throws IOException {
+      return loader.openResource(resource);
+    }
+
+    @Override
+    public <T> T newInstance(String cname, Class<T> expectedType) {
+      return loadWithRightPackageLoader(cname, expectedType,
+          (pkgloader, name) -> pkgloader.newInstance(name, expectedType));
+    }
+
+    @Override
     public <T> T newInstance(String cname, Class<T> expectedType, String... subpackages) {
       return loadWithRightPackageLoader(cname, expectedType,
           (pkgloader, name) -> pkgloader.newInstance(name, expectedType, subpackages));
     }
 
     private <T> T loadWithRightPackageLoader(String cname, Class expectedType, BiFunction<SolrClassLoader, String, T> fun) {
-      PluginInfo.ClassName className = new PluginInfo.ClassName(cname);
-      if (className.pkg == null) {
-        return  fun.apply(loader, className.klas);
+      PluginInfo.ParsedClassName parsedClassName = new PluginInfo.ParsedClassName(cname);
+      if (parsedClassName.pkg == null) {
+        return  fun.apply(loader, parsedClassName.klas);
       } else {
-        PackageLoader.Package pkg = core.getCoreContainer().getPackageLoader().getPackage(className.pkg);
+        PackageLoader.Package pkg = core.getCoreContainer().getPackageLoader().getPackage(parsedClassName.pkg);
         PackageLoader.Package.Version ver = PackagePluginHolder.getRightVersion(pkg, core);
-        T inst = fun.apply(ver.getLoader(),className.klas);
+        T result = fun.apply(ver.getLoader(), parsedClassName.klas);
+        if (result instanceof SolrCoreAware) {
+          loader.registerSolrCoreAware((SolrCoreAware) result);
+        }
         classNameVsPkg.put(cname, ver.getVersionInfo());
-        PackageListeners.Listener listener = new PackageListeners.Listener() {
-
-          PluginInfo info = new PluginInfo(expectedType.getSimpleName(), singletonMap("class", cname));
-
-          @Override
-          public String packageName() {
-            return className.pkg;
-          }
-
-          @Override
-          public PluginInfo pluginInfo() {
-            return info;
-          }
-
-          @Override
-          public void changed(PackageLoader.Package pkg, PackageListeners.Ctx ctx) {
-            PackageLoader.Package.Version rightVersion = PackagePluginHolder.getRightVersion(pkg, core);
-            if (rightVersion == null ) return;
-            PackageAPI.PkgVersion v = classNameVsPkg.get(className.toString());
-            if(Objects.equals(v.version ,rightVersion.getVersionInfo().version)) return; //nothing has changed no need to reload
-            Runnable old = ctx.getPostProcessor(PackageAwarePluginLoader.class.getName());// just want to do one refresh for every package laod
-            if (old == null) ctx.addPostProcessor(PackageAwarePluginLoader.class.getName(), reloadSchemaRunnable);
-          }
-
-          @Override
-          public PackageAPI.PkgVersion getPackageVersion() {
-            return classNameVsPkg.get(cname);
-          }
-        };
+        PackageListeners.Listener listener = new SchemaPluginPackageListener(expectedType, cname, parsedClassName);
         listeners.add(listener);
         core.getPackageListeners().addListener(listener);
-        return inst;
+        return result;
       }
     }
 
@@ -296,6 +283,46 @@ public class IndexSchema implements Closeable {
       }
 
     }
+
+    private class SchemaPluginPackageListener implements PackageListeners.Listener {
+
+      private final Class expectedType;
+      private final String cname;
+      private final PluginInfo.ParsedClassName parsedClassName;
+      PluginInfo info;
+
+      public SchemaPluginPackageListener(Class expectedType, String cname, PluginInfo.ParsedClassName parsedClassName) {
+        this.expectedType = expectedType;
+        this.cname = cname;
+        this.parsedClassName = parsedClassName;
+        info = new PluginInfo(expectedType.getSimpleName(), singletonMap("class", cname));
+      }
+
+      @Override
+      public String packageName() {
+        return parsedClassName.pkg;
+      }
+
+      @Override
+      public PluginInfo pluginInfo() {
+        return info;
+      }
+
+      @Override
+      public void changed(PackageLoader.Package pkg, PackageListeners.Ctx ctx) {
+        PackageLoader.Package.Version rightVersion = PackagePluginHolder.getRightVersion(pkg, core);
+        if (rightVersion == null ) return;
+        PackageAPI.PkgVersion v = classNameVsPkg.get(parsedClassName.toString());
+        if(Objects.equals(v.version ,rightVersion.getVersionInfo().version)) return; //nothing has changed no need to reload
+        Runnable old = ctx.getPostProcessor(PackageAwarePluginLoader.class.getName());// just want to do one refresh for every package laod
+        if (old == null) ctx.addPostProcessor(PackageAwarePluginLoader.class.getName(), reloadSchemaRunnable);
+      }
+
+      @Override
+      public PackageAPI.PkgVersion getPackageVersion() {
+        return classNameVsPkg.get(cname);
+      }
+    }
   }
 
   /**