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 2014/12/09 23:10:45 UTC

svn commit: r1644204 - /uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasDeserializer.java

Author: schor
Date: Tue Dec  9 22:10:45 2014
New Revision: 1644204

URL: http://svn.apache.org/r1644204
Log:
[UIMA-4126] fix delta cas deserialization to protect indices

Modified:
    uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasDeserializer.java

Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasDeserializer.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasDeserializer.java?rev=1644204&r1=1644203&r2=1644204&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasDeserializer.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasDeserializer.java Tue Dec  9 22:10:45 2014
@@ -47,13 +47,11 @@ import org.apache.uima.cas.Feature;
 import org.apache.uima.cas.SofaFS;
 import org.apache.uima.cas.Type;
 import org.apache.uima.cas.TypeSystem;
-import org.apache.uima.cas.impl.FSIndexRepositoryImpl.IndexRepoTodos;
 import org.apache.uima.cas.impl.XmiSerializationSharedData.OotsElementData;
 import org.apache.uima.internal.util.I18nUtil;
 import org.apache.uima.internal.util.IntListIterator;
 import org.apache.uima.internal.util.IntVector;
 import org.apache.uima.internal.util.PositiveIntSet;
-import org.apache.uima.internal.util.PositiveIntSet_impl;
 import org.apache.uima.internal.util.XmlAttribute;
 import org.apache.uima.internal.util.XmlElementName;
 import org.apache.uima.internal.util.XmlElementNameAndContents;
@@ -74,7 +72,8 @@ import org.xml.sax.helpers.XMLReaderFact
 
 public class XmiCasDeserializer {
   
-
+  private final static boolean IS_NEW_FS = true;
+  private final static boolean IS_EXISTING_FS = false;
 
   private class XmiCasDeserializerHandler extends DefaultHandler {
     // ///////////////////////////////////////////////////////////////////////
@@ -225,13 +224,14 @@ public class XmiCasDeserializer {
     boolean disallowedViewMemberEncountered;
 
     /**
-     * a list of ViewAddrs (view + FSs) to be added to the indices
+     * a list by view of FSs to be added to the indices
      */
-    final private IndexRepoTodos toBeAdded = new IndexRepoTodos();
+    final private DeferredIndexUpdates toBeAdded = new DeferredIndexUpdates();
     /**
-     * a list of ints of FSs to be removed from the indices
+     * a list by view of FSs to be removed from the indices
      */
-    final private IndexRepoTodos toBeRemoved = new IndexRepoTodos();
+    final private DeferredIndexUpdates toBeRemoved = new DeferredIndexUpdates();
+
     /**
      * Creates a SAX handler used for deserializing an XMI CAS.
      * @param aCAS CAS to deserialize into
@@ -455,7 +455,14 @@ public class XmiCasDeserializer {
       }
     }
 
-    // Create a new FS.
+    /**
+     * Read one FS, create a new FS or update an existing one
+     * @param nameSpaceURI -
+     * @param localName -
+     * @param qualifiedName -
+     * @param attrs -
+     * @throws SAXException -
+     */
     private void readFS(String nameSpaceURI, String localName, String qualifiedName, 
             Attributes attrs) throws SAXException {
       String typeName = xmiElementName2uimaTypeName(nameSpaceURI, localName);
@@ -514,7 +521,7 @@ public class XmiCasDeserializer {
   
       	if (isNewFS(xmiId)) {  //new FS so create it.  
       		final int addr = casBeingFilled.ll_createFS(currentType.getCode());
-          	readFS(addr, attrs);
+          readFS(addr, attrs, IS_NEW_FS);
       	} else {  //preexisting
       		if (this.allowPreexistingFS == AllowPreexistingFS.disallow) {
       		  CASRuntimeException e = new CASRuntimeException(
@@ -528,11 +535,19 @@ public class XmiCasDeserializer {
       		  final int addr = getFsAddrForXmiId(xmiId);
       		  // remove from indices, and remember if was there, per view
       		  //   (might be indexed in some views, not in others)
-      		  casBeingFilled.removeFromCorruptableIndexAnyView(addr, toBeAdded);
-         	  readFS(addr, attrs);
-         	  // if was removed, the remove will be added to the "toBeAdded list
-         	  // to be added back after the finalize fixups
-         	  
+//      		  FSsTobeReindexed modifySafely = casBeingFilled.modifySafely()
+//       		  casBeingFilled.removeFromCorruptableIndexAnyView(addr, toBeAddedBack);
+            
+      		  AutoCloseable addbacks = casBeingFilled.protectIndices();
+      		  try {      		  
+         	    readFS(addr, attrs, IS_EXISTING_FS);
+      		  } finally {
+        		  try {
+                addbacks.close();
+              } catch (Exception e) {
+                assert(false); // never happen
+              }
+      		  }
       		} // otherwise ignore
       	}
       }
@@ -714,22 +729,22 @@ public class XmiCasDeserializer {
 //      }
     }
 
-    private void readFS(final int addr, Attributes attrs) throws SAXException {
+    private void readFS(final int fsAddr, Attributes attrs, boolean isNewFs) throws SAXException {
       // Hang on to address for handle features encoded as child elements
-      this.currentAddr = addr;
+      this.currentAddr = fsAddr;
       int id = -1;
       String attrName, attrValue;
-      final int typeCode = casBeingFilled.getHeapValue(addr);
+      final int typeCode = casBeingFilled.getHeapValue(fsAddr);
       final Type type = casBeingFilled.getTypeSystemImpl().ll_getTypeForCode(typeCode);
       int thisSofaNum = 0;
       
-      //is it a new FS
-      try {
-        id = Integer.parseInt(attrs.getValue(ID_ATTR_NAME));
-      } catch (NumberFormatException e) {
-        throw createException(XCASParsingException.ILLEGAL_ID, attrs.getValue(ID_ATTR_NAME));
-      }
-      boolean newFS = this.isNewFS(id);
+//      //is it a new FS
+//      try {
+//        id = Integer.parseInt(attrs.getValue(ID_ATTR_NAME));
+//      } catch (NumberFormatException e) {
+//        throw createException(XCASParsingException.ILLEGAL_ID, attrs.getValue(ID_ATTR_NAME));
+//      }
+      boolean newFS = isNewFs;
       
       if (sofaTypeCode == typeCode) {
         String sofaID = attrs.getValue(CAS.FEATURE_BASE_NAME_SOFAID);
@@ -737,7 +752,7 @@ public class XmiCasDeserializer {
           // initial view Sofa always has sofaNum = 1
           thisSofaNum = 1;
         } else {
-          if (newFS) {	
+          if (isNewFs) {	
             thisSofaNum = this.nextSofaNum++;
           } else {
         	thisSofaNum = Integer.parseInt(attrs.getValue(CAS.FEATURE_BASE_NAME_SOFANUM));
@@ -746,13 +761,15 @@ public class XmiCasDeserializer {
       }
       
       this.featsSeen = null;
+      
+      // loop over all features for this FS
       for (int i = 0; i < attrs.getLength(); i++) {
         attrName = attrs.getQName(i);
         attrValue = attrs.getValue(i);
         if (attrName.equals(ID_ATTR_NAME)) {
           try {
             id = Integer.parseInt(attrValue);
-            newFS = this.isNewFS(id);
+//            newFS = this.isNewFS(id);  // we already specifically got this attribute
             if (sofaTypeCode != typeCode && !newFS) {
               this.featsSeen = new IntVector(attrs.getLength());
             } else {
@@ -770,18 +787,18 @@ public class XmiCasDeserializer {
           } else if (sofaTypeCode == typeCode && attrName.equals(CAS.FEATURE_BASE_NAME_SOFANUM)) {
             attrValue = Integer.toString(thisSofaNum);
           }
-          int featCode = handleFeature(type, addr, attrName, attrValue, newFS);
+          int featCode = handleFeature(type, fsAddr, attrName, attrValue, isNewFs);
           //if processing delta cas preexisting FS, keep track of features that have
           //been deserialized.
           if (this.featsSeen != null && !newFS && featCode != -1) {
             this.featsSeen.add(featCode); 
           }
         }
-      }
+      }  // end of all features loop
       
       if (sofaTypeCode == typeCode && newFS) {
         // If a Sofa, create CAS view to get new indexRepository
-        SofaFS sofa = (SofaFS) casBeingFilled.createFS(addr);
+        SofaFS sofa = (SofaFS) casBeingFilled.createFS(fsAddr);
         // also add to indexes so we can retrieve the Sofa later
         casBeingFilled.getBaseIndexRepository().addFS(sofa);
         CAS view = casBeingFilled.getView(sofa);
@@ -794,8 +811,8 @@ public class XmiCasDeserializer {
         ((CASImpl) view).registerView(sofa);
         views.add(view);
       }
-      deserializedFsAddrs.add(addr);
-      addFsAddrXmiIdMapping(addr, id);
+      deserializedFsAddrs.add(fsAddr);
+      addFsAddrXmiIdMapping(fsAddr, id);
     }
 
     // The definition of a null value. Any other value must be in the expected
@@ -804,14 +821,24 @@ public class XmiCasDeserializer {
       return ((val == null) || (val.length() == 0));
     }
 
-    private int handleFeature(final Type type, int addr, String featName, String featVal, boolean newFS) throws SAXException {
+    /**
+     * Deserialize one feature 
+     * @param type -
+     * @param fsAddr the address of the FS
+     * @param featName the feature name
+     * @param featVal the value of the feature
+     * @param isNewFS  true if this is a new FS
+     * @return feature code or -1 if no feature in this type system
+     * @throws SAXException if Type doesn't have the feature, and we're not in lenient mode
+     */
+    private int handleFeature(final Type type, int fsAddr, String featName, String featVal, final boolean isNewFS) throws SAXException {
       final FeatureImpl feat = (FeatureImpl) type.getFeatureByBaseName(featName);
       if (feat == null) {
         if (!this.lenient) {
           throw createException(XCASParsingException.UNKNOWN_FEATURE, featName);
         }
         else {
-          sharedData.addOutOfTypeSystemAttribute(addr, featName, featVal);
+          sharedData.addOutOfTypeSystemAttribute(fsAddr, featName, featVal);
         }
         return -1;
       }
@@ -820,19 +847,19 @@ public class XmiCasDeserializer {
       //only update Sofa data features and mime type feature. skip other features.
       //skip Sofa data features if Sofa data is already set.
       //these features may not be modified.
-      if (sofaTypeCode == casBeingFilled.getHeapValue(addr) && !isNewFS(addr) ) {
-    	if (featName.equals(CAS.FEATURE_BASE_NAME_SOFAID) || 
-    		  featName.equals(CAS.FEATURE_BASE_NAME_SOFANUM))   { 
-          return feat.getCode();
-    	} else if (featName.equals(CAS.FEATURE_BASE_NAME_SOFASTRING)  || 
-    			     featName.equals(CAS.FEATURE_BASE_NAME_SOFAURI) || 
-    			     featName.equals(CAS.FEATURE_BASE_NAME_SOFAARRAY)) {
-          int currVal = casBeingFilled.getFeatureValue(addr, feat.getCode());
-    	  if (currVal != 0) 
-    	    return feat.getCode();
-    	}
+      if (sofaTypeCode == casBeingFilled.getHeapValue(fsAddr) && !isNewFS(fsAddr) ) {
+      	if (featName.equals(CAS.FEATURE_BASE_NAME_SOFAID) || 
+      		  featName.equals(CAS.FEATURE_BASE_NAME_SOFANUM))   { 
+            return feat.getCode();
+      	} else if (featName.equals(CAS.FEATURE_BASE_NAME_SOFASTRING)  || 
+      			     featName.equals(CAS.FEATURE_BASE_NAME_SOFAURI) || 
+      			     featName.equals(CAS.FEATURE_BASE_NAME_SOFAARRAY)) {
+            int currVal = casBeingFilled.getFeatureValue(fsAddr, feat.getCode());
+      	  if (currVal != 0) 
+      	    return feat.getCode();
+      	}
       }	  
-      handleFeature(addr, feat.getCode(), featVal);
+      handleFeature(fsAddr, feat.getCode(), featVal);
       return feat.getCode();
     }
 
@@ -1435,13 +1462,12 @@ public class XmiCasDeserializer {
       }
       
       // add FSs to indexes
-      //   These come from the add list and from 
-      //   delta below-the-line updates
+      //   These come from the add list
       // https://issues.apache.org/jira/browse/UIMA-4099
       for (Entry<FSIndexRepositoryImpl, PositiveIntSet> e : toBeAdded.entrySet()) {
         FSIndexRepositoryImpl indexRep = e.getKey();
         final PositiveIntSet todo = e.getValue();
-        final IntListIterator it = ((PositiveIntSet_impl)todo).getOrderedIterator();
+        final IntListIterator it = todo.iterator();
         while (it.hasNext()) {
           indexRep.addFS(it.next());
         }
@@ -1451,7 +1477,7 @@ public class XmiCasDeserializer {
       for (Entry<FSIndexRepositoryImpl, PositiveIntSet> e : toBeRemoved.entrySet()) {
         FSIndexRepositoryImpl indexRep = e.getKey();
         final PositiveIntSet todo = e.getValue();
-        final IntListIterator it = ((PositiveIntSet_impl)todo).getOrderedIterator();
+        final IntListIterator it = todo.iterator();
         while (it.hasNext()) {
           indexRep.removeFS(it.next());
         }
@@ -1467,7 +1493,7 @@ public class XmiCasDeserializer {
         ((CASImpl) views.get(i)).updateDocumentAnnotation();
       }
       
-      //check if disallowed fs was encoutered]
+      //check if disallowed fs  encoutered]
       if (this.disallowedViewMemberEncountered) {
     	  CASRuntimeException e = new CASRuntimeException(
   		          CASRuntimeException.DELTA_CAS_PREEXISTING_FS_DISALLOWED,