Author: schor
Date: Tue Oct 18 17:47:44 2016
New Revision: 1765487

URL: http://svn.apache.org/viewvc?rev=1765487&view=rev
Log:
[UIMA-2977] add destroy() method and impl; extend a test case

Modified:
    
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java
    
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java
    
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/resource/impl/ResourceManager_implTest.java

Modified: 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java?rev=1765487&r1=1765486&r2=1765487&view=diff
==============================================================================
--- 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java
 (original)
+++ 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/ResourceManager.java
 Tue Oct 18 17:47:44 2016
@@ -324,4 +324,18 @@ public interface ResourceManager {
    * @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/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java?rev=1765487&r1=1765486&r2=1765487&view=diff
==============================================================================
--- 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java
 (original)
+++ 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/resource/impl/ResourceManager_impl.java
 Tue Oct 18 17:47:44 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;
@@ -59,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
    */
@@ -66,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
    */
@@ -78,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
    */
@@ -86,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
@@ -159,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(); 
   }
 
@@ -173,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);
   }
 
@@ -185,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;
@@ -216,6 +257,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
@@ -231,6 +273,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
@@ -245,6 +288,7 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#getExtensionClassLoader()
    */
+  @Override
   public ClassLoader getExtensionClassLoader() {
     return uimaCL;
   }
@@ -252,6 +296,7 @@ public class ResourceManager_impl implem
   /**
    * @see org.apache.uima.resource.ResourceManager#getDataPath()
    */
+  @Override
   public String getDataPath() {
     return getRelativePathResolver().getDataPath();
   }
@@ -259,6 +304,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);
   }
@@ -268,6 +314,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 {
@@ -278,10 +325,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) {
@@ -294,12 +349,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
@@ -342,7 +399,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);
@@ -363,6 +420,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);
@@ -391,6 +449,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));
@@ -401,11 +460,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();
@@ -431,6 +492,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));
   }
@@ -440,6 +502,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));
   }
@@ -447,13 +510,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();
@@ -502,15 +572,19 @@ 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();
@@ -578,7 +652,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
@@ -609,7 +683,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[] {
@@ -649,6 +723,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
@@ -666,6 +741,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) {
@@ -683,21 +759,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;
   }
@@ -706,6 +768,7 @@ public class ResourceManager_impl implem
     return importUrlsCache;
   }
   
+  @Override
   public Class<?> loadUserClass(String name) throws ClassNotFoundException {
     ClassLoader cl = getExtensionClassLoader();
     if (cl == null) {
@@ -732,6 +795,29 @@ public class ResourceManager_impl implem
               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
+    
+  }
+  
   
 
 }

Modified: 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/resource/impl/ResourceManager_implTest.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/resource/impl/ResourceManager_implTest.java?rev=1765487&r1=1765486&r2=1765487&view=diff
==============================================================================
--- 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/resource/impl/ResourceManager_implTest.java
 (original)
+++ 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/resource/impl/ResourceManager_implTest.java
 Tue Oct 18 17:47:44 2016
@@ -208,6 +208,14 @@ public class ResourceManager_implTest ex
       URI expectedUri = expectedBaseUri.resolve("Test.dat");
       Assert.assertEquals(expectedUri, r3.getUri());
 
+      mManager.destroy();
+      boolean caught = false;
+      try {
+        mManager.getResource(TEST_CONTEXT_NAME + 
"myResourceWithSpaceInPathKey");
+      } catch (IllegalStateException e) {
+        caught = true;
+      }
+      assertTrue(caught);
     } catch (Exception e) {
       JUnitExtension.handleException(e);
     }


Reply via email to