You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by al...@apache.org on 2006/12/07 18:09:50 UTC

svn commit: r483554 - in /incubator/uima/uimaj/trunk/uimaj-core/src: main/java/org/apache/uima/analysis_engine/ main/java/org/apache/uima/analysis_engine/impl/ main/java/org/apache/uima/util/ main/resources/org/apache/uima/ test/java/org/apache/uima/an...

Author: alally
Date: Thu Dec  7 09:09:49 2006
New Revision: 483554

URL: http://svn.apache.org/viewvc?view=rev&rev=483554
Log:
UIMA-86: an aggregate descriptor that imports itself either directly
or indirectly will now cause an exception to be thrown, rather than going
into infinite recursion.
https://issues.apache.org/jira/browse/UIMA-86

Added:
    incubator/uima/uimaj/trunk/uimaj-core/src/test/resources/TextAnalysisEngineImplTest/AggregateThatImportsItself.xml
Modified:
    incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineDescription.java
    incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java
    incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/InvalidXMLException.java
    incubator/uima/uimaj/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties
    incubator/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java

Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineDescription.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineDescription.java?view=diff&rev=483554&r1=483553&r2=483554
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineDescription.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineDescription.java Thu Dec  7 09:09:49 2006
@@ -22,9 +22,11 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Writer;
+import java.util.Collection;
 import java.util.Map;
 
 import org.apache.uima.Constants;
+import org.apache.uima.UIMAFramework;
 import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
 import org.apache.uima.analysis_engine.metadata.FlowControllerDeclaration;
 import org.apache.uima.analysis_engine.metadata.SofaMapping;
@@ -326,6 +328,43 @@
    */
   public void doFullValidation(ResourceManager aResourceManager)
           throws ResourceInitializationException;
+
+  /**
+   * Resolves all import declarations in this AnalysisEngineDescription. For an aggregate, this is
+   * recursive, also resolving all imports in each delegate AnalysisEngine. Users do not typically
+   * need to call this method; it is called automatically when
+   * {@link UIMAFramework#produceAnalysisEngine(ResourceSpecifier)} is called.
+   * 
+   * @param aResourceManager
+   *          the Resource Manager used to locate imports by name. For example, the path in which to
+   *          locate these imported descriptors can be set via the
+   *          {@link ResourceManager#setDataPath(String)} method.
+   * 
+   * @throws InvalidXMLException
+   *           if an import target does not exist or is invalid
+   */
+  public void resolveImports(ResourceManager aResourceManager) throws InvalidXMLException;
+
+  /**
+   * Resolves all import declarations in this AnalysisEngineDescription. For an aggregate, this is
+   * recursive, also resolving all imports in each delegate AnalysisEngine. Users do not typically
+   * need to call this method; it is called automatically when
+   * {@link UIMAFramework#produceAnalysisEngine(ResourceSpecifier)} is called.
+   * <p>
+   * This version is used internally to resolve nested imports.
+   * 
+   * @param aAlreadyImportedDelegateAeUrls
+   *          URLs of already imported AE descriptors, so we don't import them again.
+   * @param aResourceManager
+   *          the Resource Manager used to locate imports by name. For example, the path in which to
+   *          locate these imported descriptors can be set via the
+   *          {@link ResourceManager#setDataPath(String)} method.
+   * 
+   * @throws InvalidXMLException
+   *           if an import target does not exist or is invalid
+   */
+  public void resolveImports(Collection aAlreadyImportedDelegateAeUrls,
+          ResourceManager aResourceManager) throws InvalidXMLException;
 
   /**
    * Writes this object's XML representation as a string. Note that if you want to write the XML to

Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java?view=diff&rev=483554&r1=483553&r2=483554
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java Thu Dec  7 09:09:49 2006
@@ -23,6 +23,7 @@
 import java.io.Writer;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -176,7 +177,7 @@
    * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getDelegateAnalysisEngineSpecifiers()
    */
   public Map getDelegateAnalysisEngineSpecifiers() throws InvalidXMLException {
-    resolveDelegateAnalysisEngineImports(UIMAFramework.newDefaultResourceManager());
+    resolveImports(UIMAFramework.newDefaultResourceManager());
     return Collections.unmodifiableMap(mDelegateAnalysisEngineSpecifiers);
   }
 
@@ -185,7 +186,7 @@
    */
   public Map getDelegateAnalysisEngineSpecifiers(ResourceManager aResourceManager)
           throws InvalidXMLException {
-    resolveDelegateAnalysisEngineImports(aResourceManager);
+    resolveImports(aResourceManager);
     return Collections.unmodifiableMap(mDelegateAnalysisEngineSpecifiers);
   }
 
@@ -218,10 +219,9 @@
     if (aResourceManager == null) {
       aResourceManager = UIMAFramework.newDefaultResourceManager();
     }
-    resolveDelegateAnalysisEngineImports(aResourceManager);
+    resolveImports(aResourceManager);
     Map map = new HashMap(mDelegateAnalysisEngineSpecifiers);
     if (getFlowControllerDeclaration() != null) {
-      getFlowControllerDeclaration().resolveImports(aResourceManager);
       map.put(getFlowControllerDeclaration().getKey(), getFlowControllerDeclaration()
               .getSpecifier());
     }
@@ -683,10 +683,50 @@
   /*
    * (non-Javadoc)
    * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#resolveDelegateAnalysisEngineImports(org.apache.uima.resource.ResourceManager)
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#resolveImports(org.apache.uima.resource.ResourceManager)
    */
-  protected void resolveDelegateAnalysisEngineImports(ResourceManager aResourceManager)
-          throws InvalidXMLException {
+  public void resolveImports(ResourceManager aResourceManager) throws InvalidXMLException {
+    resolveImports(new HashSet(), aResourceManager);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#resolveImports(java.util.Collection,
+   *      org.apache.uima.resource.ResourceManager)
+   */
+  public void resolveImports(Collection aAlreadyImportedDelegateAeUrls,
+          ResourceManager aResourceManager) throws InvalidXMLException {
+    // add our own URL, if known, to the collection of already imported URLs
+    if (getSourceUrl() != null) {
+      aAlreadyImportedDelegateAeUrls.add(getSourceUrl());
+    }
+    // resolve delegate AE imports
+    resolveDelegateAnalysisEngineImports(aAlreadyImportedDelegateAeUrls, aResourceManager);
+    // resolve flow controller import
+    if (getFlowControllerDeclaration() != null) {
+      getFlowControllerDeclaration().resolveImports(aResourceManager);
+    }
+
+    // resolve imports in metadata (type systems, indexes, type priorities)
+    if (getAnalysisEngineMetaData() != null) {
+      getAnalysisEngineMetaData().resolveImports(aResourceManager);
+    }
+    // resolve imports in resource manager configuration
+    if (getResourceManagerConfiguration() != null) {
+      getResourceManagerConfiguration().resolveImports(aResourceManager);
+    }
+  }
+
+  /**
+   * Resolves imports of delegate Analysis Engines. This reads from the
+   * delegateAnalysisEngineSpecifiersWithImports map and populates the
+   * delegateAnalysisEngineSpecifiers map. This also recursively calls
+   * {@link #resolveImports(Collection, ResourceManager)} on each delegate. If a cirular import is
+   * found, an exception will be thrown.
+   */
+  protected void resolveDelegateAnalysisEngineImports(Collection aAlreadyImportedDelegateAeUrls,
+          ResourceManager aResourceManager) throws InvalidXMLException {
     HashSet keys = new HashSet(); // keep track of keys we've encountered
     // so we can remove stale entries
     Iterator entryIterator = getDelegateAnalysisEngineSpecifiersWithImports().entrySet().iterator();
@@ -708,6 +748,14 @@
         }
         // locate import target
         URL url = aeImport.findAbsoluteUrl(aResourceManager);
+
+        // check for resursive import
+        if (aAlreadyImportedDelegateAeUrls.contains(url)) {
+          String name = getMetaData() == null ? "<null>" : getMetaData().getName();
+          throw new InvalidXMLException(InvalidXMLException.CIRCULAR_AE_IMPORT, new Object[] {
+              name, url });
+        }
+
         // parse import target
         XMLInputSource input;
         try {
@@ -723,9 +771,21 @@
 
         // add to processed imports map so we don't redo
         mProcessedImports.put(key, aeImport);
+
+        // now resolve imports in ths delegate
+        if (spec instanceof AnalysisEngineDescription) {
+          Set alreadyImportedUrls = new HashSet(aAlreadyImportedDelegateAeUrls);
+          alreadyImportedUrls.add(url);
+          ((AnalysisEngineDescription) spec).resolveImports(alreadyImportedUrls, aResourceManager);
+        }
       } else {
         // not an import -- copy directly to derived mDelegateAnalysisEngineSpecifiers map.
         mDelegateAnalysisEngineSpecifiers.put(entry.getKey(), entry.getValue());
+        // resolve imports recursively on the delegate
+        if (entry.getValue() instanceof AnalysisEngineDescription) {
+          ((AnalysisEngineDescription) entry.getValue()).resolveImports(
+                  aAlreadyImportedDelegateAeUrls, aResourceManager);
+        }
       }
     }
     // remove stale entries

Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/InvalidXMLException.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/InvalidXMLException.java?view=diff&rev=483554&r1=483553&r2=483554
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/InvalidXMLException.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/InvalidXMLException.java Thu Dec  7 09:09:49 2006
@@ -110,6 +110,13 @@
   public static final String UNRESOLVED_XINCLUDE = "unresolved_xinclude";
 
   /**
+   * Message key for a standard UIMA exception message: Cycle found in imports. The descriptor for
+   * Aggregate Analysis Engine "{0}" has imported itself as one of its delegate descriptors (perhaps
+   * indirectly through another intermediate Analysis Engine descriptor).
+   */
+  public static final String CIRCULAR_AE_IMPORT = "circular_ae_import";
+
+  /**
    * Message key for a standard UIMA exception message: The element "fsIndexes" cannot occur outside
    * the containing element "fsIndexCollection"
    */

Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties?view=diff&rev=483554&r1=483553&r2=483554
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties Thu Dec  7 09:09:49 2006
@@ -161,6 +161,9 @@
    
 fs_indexes_outside_fs_index_collection = The element "fsIndexes" cannot occur outside the containing element "fsIndexCollection"
 
+circular_ae_import =  Cycle found in imports.  The descriptor for Aggregate Analysis Engine "{0}" has imported itself as one of its \
+  delegate descriptors (perhaps indirectly through another intermediate Analysis Engine descriptor). (Descriptor: {1})
+
 #-------------------------------
 #AnalysisEngineProcessException
 #-------------------------------

Modified: incubator/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java?view=diff&rev=483554&r1=483553&r2=483554
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java Thu Dec  7 09:09:49 2006
@@ -389,6 +389,9 @@
     // invalid fs indexes
     _testInvalidDescriptor(JUnitExtension
             .getFile("TextAnalysisEngineImplTest/InvalidFsIndexes.xml"));
+    // circular import
+    _testInvalidDescriptor(JUnitExtension
+            .getFile("TextAnalysisEngineImplTest/AggregateThatImportsItself.xml"));
 
     // try some that should work
     XMLInputSource in = new XMLInputSource(JUnitExtension

Added: incubator/uima/uimaj/trunk/uimaj-core/src/test/resources/TextAnalysisEngineImplTest/AggregateThatImportsItself.xml
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/test/resources/TextAnalysisEngineImplTest/AggregateThatImportsItself.xml?view=auto&rev=483554
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/test/resources/TextAnalysisEngineImplTest/AggregateThatImportsItself.xml (added)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/test/resources/TextAnalysisEngineImplTest/AggregateThatImportsItself.xml Thu Dec  7 09:09:49 2006
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ -->
+
+<!-- Aggregate descriptor for testing merging of type system, type priorities, and indexes. -->
+
+<taeDescription xmlns="http://uima.apache.org/resourceSpecifier">
+<frameworkImplementation>org.apache.uima.java</frameworkImplementation>
+<primitive>false</primitive>
+
+<delegateAnalysisEngineSpecifiers>
+<delegateAnalysisEngine key="Annotator1">
+<import location="TestPrimitiveTae1.xml"/>
+</delegateAnalysisEngine>
+
+<delegateAnalysisEngine key="Myself">
+<import location="AggregateThatImportsItself.xml"/>
+</delegateAnalysisEngine>
+</delegateAnalysisEngineSpecifiers> 
+<analysisEngineMetaData>
+<name>Aggregate TAE that Imports Itself</name>
+<description>For testing that circular import is detected and an errors is reported.</description>
+<version>1.0</version>
+<vendor>The Apache Software Foundation</vendor>
+
+<flowConstraints>
+  <fixedFlow>
+    <node>Annotator1</node>
+    <node>Myself</node>
+  </fixedFlow>
+</flowConstraints>
+
+<!-- Capabilities: Inputs and Outputs -->
+<capabilities>
+<capability>
+<inputs/>
+<outputs/>
+<languagesSupported/>
+</capability>
+</capabilities>
+
+</analysisEngineMetaData>
+</taeDescription>