You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2020/10/15 21:21:01 UTC
[uima-uimaj] 01/01: [UIMA-6274] Setting feature on builtin JCas
cover class that was loaded before initializing TypeSystemImpl fails
This is an automated email from the ASF dual-hosted git repository.
rec pushed a commit to branch bugfix/UIMA-6274-Setting-feature-on-builtin-JCas-cover-class-that-was-loaded-before-initializing-TypeSystemImpl-fails
in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git
commit aa003d98cb8b993d68419adffedc7d687fda32c5
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Thu Oct 15 23:20:45 2020 +0200
[UIMA-6274] Setting feature on builtin JCas cover class that was loaded before initializing TypeSystemImpl fails
- Introduce TypeSystemImpl.createCallSiteForBuiltIn() to provide special handling for the static TSI initialization being triggered by loading a built-in JCas cover class.
- Updated the built-in JCas cover classes to use the new method to initialize their feature callsites
- Added unit test
- Fixed typo in comment
---
.../org/apache/uima/cas/impl/FSClassRegistry.java | 4 +-
.../org/apache/uima/cas/impl/TypeSystemImpl.java | 43 +++++++++++++++++++
.../org/apache/uima/jcas/cas/AnnotationBase.java | 2 +-
.../java/org/apache/uima/jcas/cas/FSArrayList.java | 2 +-
.../java/org/apache/uima/jcas/cas/FSHashSet.java | 2 +-
.../main/java/org/apache/uima/jcas/cas/Int2FS.java | 4 +-
.../org/apache/uima/jcas/cas/IntegerArrayList.java | 2 +-
.../org/apache/uima/jcas/cas/NonEmptyFSList.java | 4 +-
.../apache/uima/jcas/cas/NonEmptyFloatList.java | 4 +-
.../apache/uima/jcas/cas/NonEmptyIntegerList.java | 4 +-
.../apache/uima/jcas/cas/NonEmptyStringList.java | 4 +-
.../main/java/org/apache/uima/jcas/cas/Sofa.java | 12 +++---
.../uima/jcas/impl/JCasCoverClassLoadingTest.java | 48 ++++++++++++++++++++++
13 files changed, 113 insertions(+), 22 deletions(-)
diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
index d4cc147..38dc904 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
@@ -294,7 +294,7 @@ public abstract class FSClassRegistry { // abstract to prevent instantiating; th
reportErrors();
}
-
+
private static void loadBuiltins(TypeImpl ti, ClassLoader cl, Map<String, JCasClassInfo> type2jcci, ArrayList<MutableCallSite> callSites_toSync) {
String typeName = ti.getName();
@@ -1247,7 +1247,7 @@ public abstract class FSClassRegistry { // abstract to prevent instantiating; th
fi.getName(),
staticOffsetInClass,
fi.getAdjustedOffset()),
- staticOffsetInClass != -1); // throw unless static offset is -1, in that case, a runtime error will occur if it is usedd
+ staticOffsetInClass != -1); // throw unless static offset is -1, in that case, a runtime error will occur if it is used
} // end of offset changed
} // end of feature check
} // end of for loop
diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java
index 5bcc51f..083bd05 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java
@@ -2957,6 +2957,49 @@ public class TypeSystemImpl implements TypeSystem, TypeSystemMgr, LowLevelTypeSy
// callSitesForType.add(new AbstractMap.SimpleEntry<String, MutableCallSite>(featName, callSite));
return callSite;
}
+
+ /**
+ * Creates and returns a new MutableCallSite for a built-in type. This handles the special case
+ * where the {@link #staticTsi} is initialized as a result of a builtin type JCas cover class
+ * being loaded in which case the callsite in the cover class is set after the {@link #staticTsi}
+ * already has been committed and therefore won't automatically get its callsites updated during
+ * the commit. So we need to create a proper callsite already pointing to the correct feature
+ * offset here.
+ *
+ * @param clazz the JCas class
+ * @param featName the short name of the feature
+ * @return the created callsite
+ */
+ public final static MutableCallSite createCallSiteForBuiltIn(Class<? extends TOP> clazz, String featName) {
+ // If the static TSI has not yet been initialized, we assume that the initialization of the
+ // static TSI was not triggered by the given JCas cover class. So we return a default callsite
+ // and trust that it will be properly updated when the static TSI is committed.
+ if (staticTsi == null) {
+ return createCallSite(clazz, featName);
+ }
+
+ // If the given JCas cover class not registered yet, we also assume that the initialization of
+ // the static TSI was not triggered by the given JCas cover class.
+ TypeImpl type;
+ try {
+ int typeId = clazz.getField("typeIndexID").getInt(null);
+ type = (typeId >= staticTsi.jcasRegisteredTypes.size()) ? null
+ : staticTsi.jcasRegisteredTypes.get(typeId);
+ if (type == null) {
+ return createCallSite(clazz, featName);
+ }
+ }
+ catch (Exception e) {
+ throw new UIMARuntimeException(e, UIMARuntimeException.INTERNAL_ERROR, e);
+ }
+
+ // If the JCas class has already been registered and the static TSI is already there, we look
+ // up the proper feature offset in the static TSI
+ MutableCallSite callSite = new MutableCallSite(MethodType.methodType(int.class));
+ int adjustedOffset = type.getAdjOffset(featName);
+ callSite.setTarget(FSClassRegistry.getConstantIntMethodHandle(adjustedOffset));
+ return callSite;
+ }
@Override
public Iterator<Type> iterator() {
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java
index 70feb82..00259aa 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java
@@ -73,7 +73,7 @@ public class AnnotationBase extends TOP implements AnnotationBaseImpl {
/* local data */
// public final static int _FI_sofa = TypeSystemImpl.getAdjustedFeatureOffset("sofa");
- private final static CallSite _FC_sofa = TypeSystemImpl.createCallSite(AnnotationBase.class, "sofa");
+ private final static CallSite _FC_sofa = TypeSystemImpl.createCallSiteForBuiltIn(AnnotationBase.class, "sofa");
private final static MethodHandle _FH_sofa = _FC_sofa.dynamicInvoker();
// private final Sofa _F_sofa;
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArrayList.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArrayList.java
index 73eb27e..91f2fb9 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArrayList.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArrayList.java
@@ -128,7 +128,7 @@ public class FSArrayList <T extends TOP> extends TOP implements
/* Feature Adjusted Offsets */
// public final static int _FI_fsArray = TypeSystemImpl.getAdjustedFeatureOffset("fsArray");
- private final static CallSite _FC_fsArray = TypeSystemImpl.createCallSite(FSArrayList.class, "fsArray");
+ private final static CallSite _FC_fsArray = TypeSystemImpl.createCallSiteForBuiltIn(FSArrayList.class, "fsArray");
private final static MethodHandle _FH_fsArray = _FC_fsArray.dynamicInvoker();
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSHashSet.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSHashSet.java
index 360aefd..7ef1014 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSHashSet.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSHashSet.java
@@ -94,7 +94,7 @@ public class FSHashSet <T extends TOP> extends TOP implements
/* Feature Adjusted Offsets */
// public final static int _FI_fsArray = TypeSystemImpl.getAdjustedFeatureOffset("fsArray");
- private final static CallSite _FC_fsArray = TypeSystemImpl.createCallSite(FSHashSet.class, "fsArray");
+ private final static CallSite _FC_fsArray = TypeSystemImpl.createCallSiteForBuiltIn(FSHashSet.class, "fsArray");
private final static MethodHandle _FH_fsArray = _FC_fsArray.dynamicInvoker();
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Int2FS.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Int2FS.java
index 0275544..2ac94fb 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Int2FS.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Int2FS.java
@@ -87,14 +87,14 @@ public class Int2FS <T extends TOP> extends TOP implements
/* Feature Adjusted Offsets */
- private final static CallSite _FC_fsArray = TypeSystemImpl.createCallSite(Int2FS.class, "fsArray");
+ private final static CallSite _FC_fsArray = TypeSystemImpl.createCallSiteForBuiltIn(Int2FS.class, "fsArray");
private final static MethodHandle _FH_fsArray = _FC_fsArray.dynamicInvoker();
public final static String _FeatName_intArray = "intArray";
/* Feature Adjusted Offsets */
- private final static CallSite _FC_intArray = TypeSystemImpl.createCallSite(Int2FS.class, "intArray");
+ private final static CallSite _FC_intArray = TypeSystemImpl.createCallSiteForBuiltIn(Int2FS.class, "intArray");
private final static MethodHandle _FH_intArray = _FC_intArray.dynamicInvoker();
/** Never called. Disable default constructor
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/IntegerArrayList.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/IntegerArrayList.java
index c810a31..3375558 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/IntegerArrayList.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/IntegerArrayList.java
@@ -119,7 +119,7 @@ public class IntegerArrayList extends TOP implements
/* Feature Adjusted Offsets */
// public final static int _FI_intArray = TypeSystemImpl.getAdjustedFeatureOffset("intArray");
- private final static CallSite _FC_intArray = TypeSystemImpl.createCallSite(IntegerArrayList.class, "intArray");
+ private final static CallSite _FC_intArray = TypeSystemImpl.createCallSiteForBuiltIn(IntegerArrayList.class, "intArray");
private final static MethodHandle _FH_intArray = _FC_intArray.dynamicInvoker();
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java
index 39e0591..8668547 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java
@@ -50,9 +50,9 @@ public class NonEmptyFSList<T extends TOP> extends FSList<T> implements NonEmpty
// public static final int _FI_head = TypeSystemImpl.getAdjustedFeatureOffset("head");
// public static final int _FI_tail = TypeSystemImpl.getAdjustedFeatureOffset("tail");
- private final static CallSite _FC_head = TypeSystemImpl.createCallSite(NonEmptyFSList.class, "head");
+ private final static CallSite _FC_head = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyFSList.class, "head");
private final static MethodHandle _FH_head = _FC_head.dynamicInvoker();
- private final static CallSite _FC_tail = TypeSystemImpl.createCallSite(NonEmptyFSList.class, "tail");
+ private final static CallSite _FC_tail = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyFSList.class, "tail");
private final static MethodHandle _FH_tail = _FC_tail.dynamicInvoker();
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java
index be0f009..de74c6e 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java
@@ -50,9 +50,9 @@ public class NonEmptyFloatList extends FloatList implements NonEmptyList {
// public static final int _FI_head = TypeSystemImpl.getAdjustedFeatureOffset("head");
// public static final int _FI_tail = TypeSystemImpl.getAdjustedFeatureOffset("tail");
- private final static CallSite _FC_head = TypeSystemImpl.createCallSite(NonEmptyFloatList.class, "head");
+ private final static CallSite _FC_head = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyFloatList.class, "head");
private final static MethodHandle _FH_head = _FC_head.dynamicInvoker();
- private final static CallSite _FC_tail = TypeSystemImpl.createCallSite(NonEmptyFloatList.class, "tail");
+ private final static CallSite _FC_tail = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyFloatList.class, "tail");
private final static MethodHandle _FH_tail = _FC_tail.dynamicInvoker();
/* local data */
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java
index 8f2ff0e..eedf9f3 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java
@@ -51,9 +51,9 @@ public class NonEmptyIntegerList extends IntegerList implements NonEmptyList {
// public final static int _FI_head = TypeSystemImpl.getAdjustedFeatureOffset("head");
// public final static int _FI_tail = TypeSystemImpl.getAdjustedFeatureOffset("tail");
- private final static CallSite _FC_head = TypeSystemImpl.createCallSite(NonEmptyIntegerList.class, "head");
+ private final static CallSite _FC_head = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyIntegerList.class, "head");
private final static MethodHandle _FH_head = _FC_head.dynamicInvoker();
- private final static CallSite _FC_tail = TypeSystemImpl.createCallSite(NonEmptyIntegerList.class, "tail");
+ private final static CallSite _FC_tail = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyIntegerList.class, "tail");
private final static MethodHandle _FH_tail = _FC_tail.dynamicInvoker();
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java
index ef6abbd..eb69c65 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java
@@ -50,9 +50,9 @@ public class NonEmptyStringList extends StringList implements Iterable<String>,
// public static final int _FI_head = TypeSystemImpl.getAdjustedFeatureOffset("head");
// public static final int _FI_tail = TypeSystemImpl.getAdjustedFeatureOffset("tail");
- private final static CallSite _FC_head = TypeSystemImpl.createCallSite(NonEmptyStringList.class, "head");
+ private final static CallSite _FC_head = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyStringList.class, "head");
private final static MethodHandle _FH_head = _FC_head.dynamicInvoker();
- private final static CallSite _FC_tail = TypeSystemImpl.createCallSite(NonEmptyStringList.class, "tail");
+ private final static CallSite _FC_tail = TypeSystemImpl.createCallSiteForBuiltIn(NonEmptyStringList.class, "tail");
private final static MethodHandle _FH_tail = _FC_tail.dynamicInvoker();
diff --git a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java
index cf19c65..75b6947 100644
--- a/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java
+++ b/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java
@@ -61,12 +61,12 @@ public class Sofa extends TOP implements SofaFSImpl {
// public final static int _FI_sofaString = TypeSystemImpl.getAdjustedFeatureOffset("sofaString");
// public final static int _FI_sofaURI = TypeSystemImpl.getAdjustedFeatureOffset("sofaURI");
- private final static CallSite _FC_sofaNum = TypeSystemImpl.createCallSite(Sofa.class, "sofaNum");
- private final static CallSite _FC_sofaID = TypeSystemImpl.createCallSite(Sofa.class, "sofaID");
- private final static CallSite _FC_mimeType = TypeSystemImpl.createCallSite(Sofa.class, "mimeType");
- private final static CallSite _FC_sofaArray = TypeSystemImpl.createCallSite(Sofa.class, "sofaArray");
- private final static CallSite _FC_sofaString = TypeSystemImpl.createCallSite(Sofa.class, "sofaString");
- private final static CallSite _FC_sofaURI = TypeSystemImpl.createCallSite(Sofa.class, "sofaURI");
+ private final static CallSite _FC_sofaNum = TypeSystemImpl.createCallSiteForBuiltIn(Sofa.class, "sofaNum");
+ private final static CallSite _FC_sofaID = TypeSystemImpl.createCallSiteForBuiltIn(Sofa.class, "sofaID");
+ private final static CallSite _FC_mimeType = TypeSystemImpl.createCallSiteForBuiltIn(Sofa.class, "mimeType");
+ private final static CallSite _FC_sofaArray = TypeSystemImpl.createCallSiteForBuiltIn(Sofa.class, "sofaArray");
+ private final static CallSite _FC_sofaString = TypeSystemImpl.createCallSiteForBuiltIn(Sofa.class, "sofaString");
+ private final static CallSite _FC_sofaURI = TypeSystemImpl.createCallSiteForBuiltIn(Sofa.class, "sofaURI");
private final static MethodHandle _FH_sofaNum = _FC_sofaNum.dynamicInvoker();
private final static MethodHandle _FH_sofaID = _FC_sofaID.dynamicInvoker();
diff --git a/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasCoverClassLoadingTest.java b/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasCoverClassLoadingTest.java
new file mode 100644
index 0000000..b4df0d2
--- /dev/null
+++ b/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasCoverClassLoadingTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.uima.jcas.impl;
+
+import org.apache.uima.cas.impl.TypeSystemImpl;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.jcas.cas.Sofa;
+import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.apache.uima.resource.metadata.impl.TypeSystemDescription_impl;
+import org.apache.uima.util.CasCreationUtils;
+import org.junit.Test;
+
+public class JCasCoverClassLoadingTest {
+
+ /**
+ * This test failed when we were using {@link TypeSystemImpl#createCallSite(Class, String)}
+ * instead of {@link TypeSystemImpl#createCallSiteForBuiltIn(Class, String)} to initialize
+ * built-in JCas cover classes.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/UIMA-6274">UIMA-6274</a>
+ */
+ @Test
+ public void thatLoadingABuiltInCoverClassBeforeTypeSystemImplDoesNotBreakTheClass() throws Exception
+ {
+ Class.forName(Sofa.class.getName());
+
+ TypeSystemDescription tsd = new TypeSystemDescription_impl();
+ JCas jcas = CasCreationUtils.createCas(tsd, null, null).getJCas();
+ // Originally an exception was thrown in the following line
+ jcas.setDocumentText("test text");
+ }
+}