You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2016/10/20 14:04:09 UTC

svn commit: r1765820 - in /uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource: ResourceManager.java impl/ResourceManager_impl.java

Author: schor
Date: Thu Oct 20 14:04:08 2016
New Revision: 1765820

URL: http://svn.apache.org/viewvc?rev=1765820&view=rev
Log:
[UIMA-5038] [UIMA-2977] backporting from uima V3, support for common code to load resources, and new destroy method on ResourceManager

Modified:
    uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java
    uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java

Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java?rev=1765820&r1=1765819&r2=1765820&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java Thu Oct 20 14:04:08 2016
@@ -315,4 +315,27 @@ public interface ResourceManager {
    */
   @Deprecated
   public Map<String,XMLizable> getImportCache();
+  
+  /**
+   * Loads a user class using either the UIMA extension class loader (if specified) or 
+   * the loader the UIMA framework is running in.
+   * @param name the class to load
+   * @return the class
+   * @throws ClassNotFoundException -
+   */
+  public Class<?> loadUserClass(String name) throws ClassNotFoundException;
+  
+  /**
+   * Frees all resources held by this ResourceManager, and marks the ResourceManager as having been destroyed.
+   * A destroyed ResourceManager will throw an exception if an attempt is made to continue using it.
+   * 
+   * Resources managed by a ResourceManager include all of the external shared Resources and a CAS Pool.
+   * The Resources managed by this manager will have their destroy() methods called, as part of the
+   * execution of this API.
+   * 
+   * The framework does not call this method; it is up to the containing application to decide if and when
+   * a ResourceManager instance should be destroyed.  This is because the containing application is the only
+   * knowledgeable source; for example a single ResourceManager might be used for multiple UIMA Pipelines.
+   */
+  public void destroy();
 }

Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java?rev=1765820&r1=1765819&r2=1765820&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java Thu Oct 20 14:04:08 2016
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.UIMA_IllegalStateException;
@@ -46,6 +47,7 @@ import org.apache.uima.resource.Resource
 import org.apache.uima.resource.ResourceAccessException;
 import org.apache.uima.resource.ResourceInitializationException;
 import org.apache.uima.resource.ResourceManager;
+import org.apache.uima.resource.ResourceSpecifier;
 import org.apache.uima.resource.SharedResourceObject;
 import org.apache.uima.resource.metadata.ExternalResourceBinding;
 import org.apache.uima.resource.metadata.ResourceManagerConfiguration;
@@ -58,6 +60,34 @@ import org.apache.uima.util.XMLizable;
  * 
  */
 public class ResourceManager_impl implements ResourceManager {
+  
+  /**
+   * Ties an External Resource instance to
+   *   - its description 
+   *     -- name
+   *     -- textual description
+   *     -- a ResourceSpecifier describing how to create it
+   *     -- the String name of the Java class that implements the resource)
+   *   - its defining UIMA Context
+   *   
+   *   These are used to validate multiple declarations, and to get
+   *   a resource to tie it to a binding
+   */
+  static protected class ResourceRegistration { // make protected https://issues.apache.org/jira/browse/UIMA-2102
+    Resource resource;
+
+    ExternalResourceDescription description;
+
+    String definingContext;
+
+    public ResourceRegistration(Resource resource, ExternalResourceDescription description,
+            String definingContext) {
+      this.resource = resource;
+      this.description = description;
+      this.definingContext = definingContext;
+    }
+  }
+
   /**
    * resource bundle for log messages
    */
@@ -65,6 +95,7 @@ public class ResourceManager_impl implem
   
   protected static final Class<Resource> EMPTY_RESOURCE_CLASS = Resource.class; 
 
+  private AtomicBoolean isDestroyed = new AtomicBoolean(false);
   /**
    * a monitor lock for synchronizing get/set of casManager ref
    */
@@ -77,6 +108,7 @@ public class ResourceManager_impl implem
 
   /**
    * Map from qualified key names (declared in resource dependency XML) to Resource objects.
+   * This map is many to one (multiple keys may refer to the same Resource object)
    * 
    * Can't be concurrentMap because it (currently) depends on storing nulls
    */
@@ -85,27 +117,37 @@ public class ResourceManager_impl implem
   /**
    * Internal map from resource names (declared in resource declaration XML) to ResourceRegistration
    * objects. Used during initialization only.
+   * 
+   * This is a one-to-one map.
    */
   final protected Map<String, ResourceRegistration> mInternalResourceRegistrationMap;
 
   /**
    * Map from String keys to Class objects. For ParameterizedResources only, stores the
    * implementation class corresponding to each resource name.
+   * 
+   * This is a many to one map; many keys may refer to the same class
+   * 
+   * key = aQualifiedContextName + the key name in an external resource binding
    */
   final protected Map<String, Class<?>> mParameterizedResourceImplClassMap;
 
   /**
-   * Internal map from resource names (declared in resource declaration XML) to Class objects. Used
+   * Internal map from resource names (declared in resource declaration XML) to Class objects
+   * for parameterized Resource.  These are potentially "customized" when referenced, by 
+   * parameter strings (such as language, for a Dictionary resource). Used
    * internally during resource initialization.
+   * 
+   * key = external resource declared name.
    */
   final protected Map<String, Class<?>> mInternalParameterizedResourceImplClassMap;
 
   /**
-   * Map from ParameterizedResourceKey to Resource objects. For
-   * ParameterizedResources only, stores the DataResources that have already been encountered, and
+   * Map from ParameterizedResourceKey to Resource objects. 
+   * For ParameterizedResources only, stores the DataResources that have already been encountered, and
    * the Resources that have been instantiated therefrom.
    */
-  final protected Map<List<Object>, Object> mParameterizedResourceInstanceMap;
+  final protected Map<List<Object>, Resource> mParameterizedResourceInstanceMap;
 
   /**
    * UIMA extension ClassLoader. ClassLoader is created if an extension classpath is specified at
@@ -158,7 +200,7 @@ public class ResourceManager_impl implem
     mInternalResourceRegistrationMap = new ConcurrentHashMap<String, ResourceRegistration>();
     mParameterizedResourceImplClassMap =  new ConcurrentHashMap<String, Class<?>>();
     mInternalParameterizedResourceImplClassMap = new ConcurrentHashMap<String, Class<?>>();
-    mParameterizedResourceInstanceMap =  new ConcurrentHashMap<List<Object>, Object>();
+    mParameterizedResourceInstanceMap =  new ConcurrentHashMap<List<Object>, Resource>();
     mRelativePathResolver = new RelativePathResolver_impl(); 
   }
 
@@ -172,7 +214,7 @@ public class ResourceManager_impl implem
     mInternalResourceRegistrationMap = new ConcurrentHashMap<String, ResourceRegistration>();
     mParameterizedResourceImplClassMap =  new ConcurrentHashMap<String, Class<?>>();
     mInternalParameterizedResourceImplClassMap = new ConcurrentHashMap<String, Class<?>>();
-    mParameterizedResourceInstanceMap =  new ConcurrentHashMap<List<Object>, Object>();
+    mParameterizedResourceInstanceMap =  new ConcurrentHashMap<List<Object>, Resource>();
     mRelativePathResolver = new RelativePathResolver_impl(aClassLoader);
   }
 
@@ -184,7 +226,7 @@ public class ResourceManager_impl implem
       Map<String, ResourceRegistration> internalResourceRegistrationMap,
       Map<String, Class<?>> parameterizedResourceImplClassMap,
       Map<String, Class<?>> internalParameterizedResourceImplClassMap,
-      Map<List<Object>, Object> parameterizedResourceInstanceMap) {
+      Map<List<Object>, Resource> parameterizedResourceInstanceMap) {
     mResourceMap = resourceMap;
     mInternalResourceRegistrationMap = internalResourceRegistrationMap;
     mParameterizedResourceImplClassMap =  parameterizedResourceImplClassMap;
@@ -231,6 +273,7 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#setExtensionClassPath(java.lang.String, boolean)
    */
+  @Override
   public synchronized void setExtensionClassPath(String classpath, boolean resolveResource)
           throws MalformedURLException {
     // create UIMA extension ClassLoader with the given classpath
@@ -246,6 +289,7 @@ public class ResourceManager_impl implem
    * @see org.apache.uima.resource.ResourceManager#setExtensionClassPath(ClassLoader,java.lang.String,
    *      boolean)
    */
+  @Override
   public synchronized void setExtensionClassPath(ClassLoader parent, String classpath, boolean resolveResource)
           throws MalformedURLException {
     // create UIMA extension ClassLoader with the given classpath
@@ -260,6 +304,7 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#getExtensionClassLoader()
    */
+  @Override
   public ClassLoader getExtensionClassLoader() {
     return uimaCL;
   }
@@ -267,6 +312,7 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#getDataPath()
    */
+  @Override
   public String getDataPath() {
     return getRelativePathResolver().getDataPath();
   }
@@ -274,6 +320,7 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#setDataPath(String)
    */
+  @Override
   public void setDataPath(String aPath) throws MalformedURLException {
     getRelativePathResolver().setDataPath(aPath);
   }
@@ -283,6 +330,7 @@ public class ResourceManager_impl implem
    * 
    * @see org.apache.uima.resource.ResourceManager#resolveRelativePath(java.lang.String)
    */
+  @Override
   public URL resolveRelativePath(String aRelativePath) throws MalformedURLException {
     URL relativeUrl;
     try {
@@ -293,10 +341,18 @@ public class ResourceManager_impl implem
     return getRelativePathResolver().resolveRelativePath(relativeUrl);
   }
 
+  private void checkDestroyed() {
+    if (isDestroyed.get()) {
+      throw new IllegalStateException("ResourceManager is destroyed");
+    }    
+  }
+  
   /**
    * @see org.apache.uima.resource.ResourceManager#getResource(String)
    */
+  @Override
   public Object getResource(String aName) throws ResourceAccessException {
+    checkDestroyed();
     Object r = mResourceMap.get(aName);
     // if this is a ParameterizedDataResource, it is an error
     if (r instanceof ParameterizedDataResource) {
@@ -309,12 +365,14 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#getResource(java.lang.String, java.lang.String[])
    */
+  @Override
   public Object getResource(String aName, String[] aParams) throws ResourceAccessException {
     /* Multi-core design
      *   This may be called by user code sharing the same Resource Manager, and / or the same 
      *     uima context object.
      *   Do double-checked idiom to avoid locking where resource is already available, loaded   
      */
+    checkDestroyed();
     Object r = mResourceMap.get(aName);
 
     // if no resource found, return null
@@ -357,7 +415,7 @@ public class ResourceManager_impl implem
         try {
           SharedResourceObject sro = (SharedResourceObject) sharedResourceObjectClass.newInstance();
           sro.load(dr);
-          mParameterizedResourceInstanceMap.put(nameAndResource, sro);
+          mParameterizedResourceInstanceMap.put(nameAndResource, (Resource) sro);
           return sro;
         } catch (InstantiationException e) {
           throw new ResourceAccessException(e);
@@ -378,6 +436,7 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#getResourceClass(java.lang.String)
    */
+  @Override
   @SuppressWarnings("unchecked")
   public Class<? extends Resource> getResourceClass(String aName) {
     Object r = mResourceMap.get(aName);
@@ -406,6 +465,7 @@ public class ResourceManager_impl implem
    * @see org.apache.uima.resource.ResourceManager#getResourceAsStream(java.lang.String,
    *      java.lang.String[])
    */
+  @Override
   public InputStream getResourceAsStream(String aKey, String[] aParams)
           throws ResourceAccessException {
     return getResourceAsStreamCommon(getResource(aKey, aParams));
@@ -416,11 +476,13 @@ public class ResourceManager_impl implem
    * 
    * @see org.apache.uima.resource.ResourceManager#getResourceAsStream(java.lang.String)
    */
+  @Override
   public InputStream getResourceAsStream(String aKey) throws ResourceAccessException {
     return getResourceAsStreamCommon(getResource(aKey));
   }
 
   private InputStream getResourceAsStreamCommon(Object resource) throws ResourceAccessException {
+    checkDestroyed();
     try {
       if (resource != null && resource instanceof DataResource) {
         return ((DataResource) resource).getInputStream();
@@ -446,6 +508,7 @@ public class ResourceManager_impl implem
    * @see org.apache.uima.resource.ResourceManager#getResourceURL(java.lang.String,
    *      java.lang.String[])
    */
+  @Override
   public URL getResourceURL(String aKey, String[] aParams) throws ResourceAccessException {
     return getResourceAsStreamCommonUrl(getResource(aKey, aParams));
   }
@@ -455,6 +518,7 @@ public class ResourceManager_impl implem
    * 
    * @see org.apache.uima.resource.ResourceManager#getResourceURL(java.lang.String)
    */
+  @Override
   public URL getResourceURL(String aKey) throws ResourceAccessException {
     return getResourceAsStreamCommonUrl(getResource(aKey));
   }
@@ -462,13 +526,20 @@ public class ResourceManager_impl implem
   /*
    * (non-Javadoc)
    * 
-   * @see org.apache.uima.resource.ResourceManager#initializeExternalResources(org.apache.uima.resource.metadata.ResourceManagerConfiguration,
-   *      java.lang.String, java.util.Map)
+   * This method is called during Resource Initialization, 
+   *   - only for resources which are "local", that is, instances of ResourceCreationSpecifier
+   *   - and therefore might have external resource declarations 
+   * 
+   * Compare with resolveAndValidateResourceDependencies, called for resource binding resolution.
+   * 
+   * @see ResourceManager#initializeExternalResources(ResourceManagerConfiguration, String, Map<String, Object>)
    */
+  @Override
   public synchronized void initializeExternalResources(ResourceManagerConfiguration aConfiguration,
           String aQualifiedContextName, Map<String, Object> aAdditionalParams)
           throws ResourceInitializationException {
     // register resources
+    checkDestroyed();
     ExternalResourceDescription[] resources = aConfiguration.getExternalResources();
     for (int i = 0; i < resources.length; i++) {
       String name = resources[i].getName();
@@ -518,14 +589,18 @@ public class ResourceManager_impl implem
   /*
    * (non-Javadoc)
    * 
-   * @see org.apache.uima.resource.ResourceManager#resolveAndValidateResourceDependencies(org.apache.uima.resource.ExternalResourceDependency[],
-   *      java.lang.String)
+   * Called during resource initialization, when the resource has external resource bindings,
+   * to resolve those bindings                                              
+   *                                               
+   * @see ResourceManager#resolveAndValidateResourceDependencies(ExternalResourceDependency[], String)
    *      
    * Multi-threaded.  Partial avoidance of re-resolving, but if a resource fails to resolve, it will be 
    *   reattempted on every call
    */
+  @Override
   public synchronized void resolveAndValidateResourceDependencies(ExternalResourceDependency[] aDependencies,
           String aQualifiedContextName) throws ResourceInitializationException {
+    checkDestroyed();
     for (int i = 0; i < aDependencies.length; i++) {
       // get resource
       String qname = aQualifiedContextName + aDependencies[i].getKey();
@@ -558,19 +633,9 @@ public class ResourceManager_impl implem
       } else {
         // make sure resource exists and implements the correct interface
         try {
-          if (aDependencies[i].getInterfaceName() != null
-                  && aDependencies[i].getInterfaceName().length() > 0) {
-            // get UIMA extension ClassLoader if available
-            ClassLoader cl = getExtensionClassLoader();
-            Class<?> theInterface = null;
-
-            if (cl != null) {
-              // use UIMA extension ClassLoader to load the class
-              theInterface = cl.loadClass(aDependencies[i].getInterfaceName());
-            } else {
-              // use application ClassLoader to load the class
-              theInterface = Class.forName(aDependencies[i].getInterfaceName());
-            }
+          String name = aDependencies[i].getInterfaceName();
+          if (name != null && name.length() > 0) {
+            Class<?> theInterface = loadUserClass(name);
 
             Class<? extends Resource> resourceClass = getResourceClass(qname);
             if (!theInterface.isAssignableFrom(resourceClass)) {
@@ -603,7 +668,7 @@ public class ResourceManager_impl implem
     boolean verificationMode = initParams.containsKey(AnalysisEngineImplBase.PARAM_VERIFICATION_MODE);
     
     // create the initial resource using the resource factory
-    Object r = UIMAFramework.produceResource(aResourceDescription.getResourceSpecifier(),
+    Resource r = UIMAFramework.produceResource(aResourceDescription.getResourceSpecifier(),
             initParams);
 
     // load implementation class (if any) and ensure that it implements
@@ -612,16 +677,7 @@ public class ResourceManager_impl implem
     Class<?> implClass = null;
     if (implementationName != null && implementationName.length() > 0) {
       try {
-        // get UIMA extension ClassLoader if available
-        ClassLoader cl = getExtensionClassLoader();
-
-        if (cl != null) {
-          // use UIMA extension ClassLoader to load the class
-          implClass = cl.loadClass(implementationName);
-        } else {
-          // use application ClassLoader to load the class
-          implClass = Class.forName(implementationName);
-        }
+        implClass = loadUserClass(implementationName);
       } catch (ClassNotFoundException e) {
         throw new ResourceInitializationException(ResourceInitializationException.CLASS_NOT_FOUND,
                 new Object[] { implementationName, aResourceDescription.getSourceUrlString() }, e);
@@ -643,7 +699,7 @@ public class ResourceManager_impl implem
           if (!verificationMode) {
             sro.load((DataResource) r);
           }
-          r = sro;
+          r = (Resource) sro;
         } catch (InstantiationException e) {
           throw new ResourceInitializationException(
                   ResourceInitializationException.COULD_NOT_INSTANTIATE, new Object[] {
@@ -683,6 +739,7 @@ public class ResourceManager_impl implem
    * 
    * @see org.apache.uima.resource.ResourceManager#getCasManager()
    */
+  @Override
   public CasManager getCasManager() {
     //Optimization for case where mCasManager already created
     // Some sync contention was observed - this makes it less.  UIMA-4012
@@ -700,6 +757,7 @@ public class ResourceManager_impl implem
   /* (non-Javadoc)
    * @see org.apache.uima.resource.ResourceManager#setCasManager(org.apache.uima.resource.CasManager)
    */
+  @Override
   public void setCasManager(CasManager aCasManager) {
     synchronized(casManagerMonitor) {
       if (mCasManager == null) {
@@ -717,21 +775,7 @@ public class ResourceManager_impl implem
     return mRelativePathResolver;
   }
 
-  static protected class ResourceRegistration { // make protected https://issues.apache.org/jira/browse/UIMA-2102
-    Object resource;
-
-    ExternalResourceDescription description;
-
-    String definingContext;
-
-    public ResourceRegistration(Object resource, ExternalResourceDescription description,
-            String definingContext) {
-      this.resource = resource;
-      this.description = description;
-      this.definingContext = definingContext;
-    }
-  }
-
+  @Override
   public Map<String, XMLizable> getImportCache() {
     return importCache;
   }
@@ -739,4 +783,57 @@ public class ResourceManager_impl implem
   public Map<String, Set<String>> getImportUrlsCache() {
     return importUrlsCache;
   }
+  
+  @Override
+  public Class<?> loadUserClass(String name) throws ClassNotFoundException {
+    ClassLoader cl = getExtensionClassLoader();
+    if (cl == null) {
+      cl = this.getClass().getClassLoader();
+    }
+    return Class.forName(name, true, cl);
+  }
+  
+  public static Class<?> loadUserClass(String name, ResourceManager rm) throws ClassNotFoundException {
+    return (rm == null) 
+             ? Class.forName(name, true, ResourceManager_impl.class.getClassLoader())
+             : rm.loadUserClass(name);
+  }
+  
+  public static Class<?> loadUserClassOrThrow(String name, ResourceManager rm, ResourceSpecifier aSpecifier) 
+      throws ResourceInitializationException {
+    try {
+      return (rm == null) 
+               ? Class.forName(name, true, ResourceManager_impl.class.getClassLoader())
+               : rm.loadUserClass(name);
+    } catch (ClassNotFoundException e) {
+      throw new ResourceInitializationException(
+          ResourceInitializationException.CLASS_NOT_FOUND, new Object[] { name,
+              aSpecifier.getSourceUrlString() }, e);
+    }
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.uima.resource.ResourceManager#destroy()
+   */
+  @Override
+  public void destroy() {
+    boolean alreadyDestroyed = isDestroyed.getAndSet(true);
+    if (alreadyDestroyed) {
+      return;
+    }
+    
+    for (ResourceRegistration r : mInternalResourceRegistrationMap.values()) {
+      r.resource.destroy();
+    }
+    
+    for (Resource r : mParameterizedResourceInstanceMap.values()) {
+      r.destroy();
+    }
+    
+    // no destroy of caspool at this time
+    
+  }
+  
+  
+
 }