From f2fea999e737c1a1714e53a57f11696efca48268 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 1 Jun 2022 14:21:30 +0200 Subject: [PATCH 1/2] [UIMA-6468] Problem with JCas classes with re-used across different type systems - Added test - Added a smart little classloader in the test code which works around the problem --- .../uima/jcas/test/JCasFeatureOffsetTest.java | 231 ++++++++++++++++++ .../JCasFeatureOffsetTest/BaseDescriptor.xml | 49 ++++ .../test/jcasfeatureoffsettest/Base.class | Bin 0 -> 1575 bytes .../test/jcasfeatureoffsettest/Subtype.class | Bin 0 -> 2458 bytes .../uima/test/jcasfeatureoffsettest/Base.java | 105 ++++++++ .../test/jcasfeatureoffsettest/Subtype.java | 139 +++++++++++ .../SubtypeDescriptor1.xml | 60 +++++ .../test/jcasfeatureoffsettest/Base.class | Bin 0 -> 1575 bytes .../test/jcasfeatureoffsettest/Subtype.class | Bin 0 -> 2458 bytes .../uima/test/jcasfeatureoffsettest/Base.java | 105 ++++++++ .../test/jcasfeatureoffsettest/Subtype.java | 131 ++++++++++ .../SubtypeDescriptor2.xml | 60 +++++ 12 files changed, 880 insertions(+) create mode 100644 uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/BaseDescriptor.xml create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Base.class create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Subtype.class create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Base.java create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1.xml create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Base.class create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Subtype.class create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Base.java create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java create mode 100644 uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2.xml diff --git a/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java new file mode 100644 index 0000000000..a4834913a1 --- /dev/null +++ b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java @@ -0,0 +1,231 @@ +/* + * 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.test; + +import static java.util.Arrays.asList; +import static org.apache.uima.UIMAFramework.getResourceSpecifierFactory; +import static org.apache.uima.util.CasCreationUtils.createCas; +import static org.apache.uima.util.CasCreationUtils.mergeTypeSystems; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +import org.apache.commons.io.IOUtils; +import org.apache.uima.UIMAFramework; +import org.apache.uima.UIMARuntimeException; +import org.apache.uima.analysis_component.JCasAnnotator_ImplBase; +import org.apache.uima.analysis_engine.AnalysisEngine; +import org.apache.uima.analysis_engine.AnalysisEngineDescription; +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.cas.impl.BuiltinTypeKinds; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.TOP; +import org.apache.uima.resource.ResourceInitializationException; +import org.apache.uima.resource.ResourceManager; +import org.apache.uima.resource.metadata.TypeSystemDescription; +import org.apache.uima.util.InvalidXMLException; +import org.apache.uima.util.XMLInputSource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JCasFeatureOffsetTest { + static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + static final String BASE = "src/test/resources/JCasFeatureOffsetTest"; + + TypeSystemDescription tdBase; + TypeSystemDescription tdSubtype1; + TypeSystemDescription tdSubtype2; + TypeSystemDescription tdMerged; + + ClassLoader clSubtype1; + ClassLoader clSubtype2; + + ResourceManager rmBase; + ResourceManager rmSubtype1; + ResourceManager rmSubtype2; + + @BeforeEach + void setup() throws Exception { + tdBase = loadTypeSystem("BaseDescriptor.xml"); + tdSubtype1 = loadTypeSystem("SubtypeDescriptor1.xml"); + tdSubtype2 = loadTypeSystem("SubtypeDescriptor2.xml"); + tdMerged = mergeTypeSystems(asList(tdBase, tdSubtype1, tdSubtype2)); + + rmBase = UIMAFramework.newDefaultResourceManager(); + + clSubtype1 = createScopedJCasClassKoader("SubtypeDescriptor1-jcas/classes"); + rmSubtype1 = UIMAFramework.newDefaultResourceManager(); + rmSubtype1.setExtensionClassLoader(clSubtype1, true); + + clSubtype2 = createScopedJCasClassKoader("SubtypeDescriptor2-jcas/classes"); + rmSubtype2 = UIMAFramework.newDefaultResourceManager(); + rmSubtype2.setExtensionClassLoader(clSubtype2, true); + } + + @Test + void thatPreMergedTypeSystemWorks() throws Exception { + JCas jcas = createCas(tdMerged, null, null).getJCas(); + + AnalysisEngine ae1 = createTestEngine(rmSubtype1); + AnalysisEngine ae2 = createTestEngine(rmSubtype2); + + ae1.process(jcas); + ae2.process(jcas); + } + + @Test + void thatNotPreMergedTypeSystemsWithIsolatedLoadersWorks() throws Exception { + JCas jcas = createCas(tdBase, null, null).getJCas(); + + AnalysisEngine ae1 = createTestEngine(rmSubtype1); + AnalysisEngine ae2 = createTestEngine(rmSubtype2); + + ae1.process(jcas); + ae2.process(jcas); + } + + @Test + void thatRebindingFeaturesToDifferentIndexFails() throws Exception { + + LOG.info("=== Initializing the JCas built-in classes"); + createCas().getJCas(); + + // Bind callsite of featureX from rmSubtype1 to index 1 + createCas(tdMerged, null, null, null, rmSubtype1).getJCas(); + + // Bind callsite of featureY from rmSubtype2 to index 2 + createCas(tdMerged, null, null, null, rmSubtype2).getJCas(); + + // featureY from rmSubtype2 is bound to index 2 but in tdSubtype2, it would be index 1 + // because featureX does not exist here -> FAIL + assertThatExceptionOfType(UIMARuntimeException.class).isThrownBy(() -> { + createCas(tdSubtype2, null, null, null, rmSubtype2).getJCas(); + }); + } + + @Test + void thatRebindingFeaturesToDifferentIndexWorksWithIsolation() throws Exception { + + LOG.info("=== Initializing the JCas built-in classes"); + createCas().getJCas(); + + // Bind callsite of featureX from rmSubtype1 to index 1 + createCas(tdMerged, null, null, null, rmSubtype1).getJCas(); + + // Bind callsite of featureY from rmSubtype2 to index 2 + createCas(tdMerged, null, null, null, rmSubtype2).getJCas(); + + // Using an isolating classloader, we make sure that a new JCas wrapper class instance is + // used that is not bound yet - and we should not re-use this classloader + ClassLoader icl = new JCasIsolatingClassLoader(clSubtype2); + ResourceManager otherRmSubtype2 = UIMAFramework.newDefaultResourceManager(); + otherRmSubtype2.setExtensionClassLoader(icl, true); + + assertThatNoException().isThrownBy(() -> { + createCas(tdSubtype2, null, null, null, otherRmSubtype2).getJCas(); + }); + } + + private AnalysisEngine createTestEngine(ResourceManager rm1) + throws ResourceInitializationException { + AnalysisEngineDescription aed = getResourceSpecifierFactory().createAnalysisEngineDescription(); + aed.setPrimitive(true); + aed.setImplementationName(TestEngine.class.getName()); + return UIMAFramework.produceAnalysisEngine(aed, rm1, null); + } + + public static class TestEngine extends JCasAnnotator_ImplBase { + @Override + public void process(JCas aJCas) throws AnalysisEngineProcessException { + // Nothing to do + } + } + + private TypeSystemDescription loadTypeSystem(String aPath) + throws InvalidXMLException, IOException { + return UIMAFramework.getXMLParser() + .parseTypeSystemDescription(new XMLInputSource(new File(BASE + "/" + aPath))); + } + + private URLClassLoader createScopedJCasClassKoader(String aPath) throws MalformedURLException { + return new URLClassLoader(new URL[] { new File(BASE + "/" + aPath).toURI().toURL() }); + } + + public static class JCasIsolatingClassLoader extends ClassLoader { + public JCasIsolatingClassLoader(ClassLoader aParent) { + super(aParent); + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + synchronized (getClassLoadingLock(name)) { + Class clazz = getParent().loadClass(name); + + if (!TOP.class.isAssignableFrom(clazz)) { + return clazz; + } + + Object typeName; + try { + Field typeNameField = clazz.getField("_TypeName"); + typeName = typeNameField.get(null); + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException + | IllegalAccessException e) { + return clazz; + } + + if (BuiltinTypeKinds.creatableBuiltinJCas.contains(typeName)) { + return clazz; + } + + String internalName = name.replace(".", "/") + ".class"; + InputStream is = getParent().getResourceAsStream(internalName); + if (is == null) { + throw new ClassNotFoundException(name); + } + + try { + byte[] bytes = IOUtils.toByteArray(is); + Class cls = defineClass(name, bytes, 0, bytes.length); + if (cls.getPackage() == null) { + int packageSeparator = name.lastIndexOf('.'); + if (packageSeparator != -1) { + String packageName = name.substring(0, packageSeparator); + definePackage(packageName, null, null, null, null, null, null, null); + } + } + return cls; + } catch (IOException ex) { + throw new ClassNotFoundException("Cannot load resource for class [" + name + "]", ex); + } + } + } + } +} diff --git a/uimaj-core/src/test/resources/JCasFeatureOffsetTest/BaseDescriptor.xml b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/BaseDescriptor.xml new file mode 100644 index 0000000000..3fe986837c --- /dev/null +++ b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/BaseDescriptor.xml @@ -0,0 +1,49 @@ + + + + + + typeSystemDescriptor + + + + + + + + 1.0 + + + + + + + + + + + + + + + + org.apache.uima.test.jcasfeatureoffsettest.Base + + + + + + + + uima.tcas.Annotation + + + + + + + + + + + diff --git a/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Base.class b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Base.class new file mode 100644 index 0000000000000000000000000000000000000000..36a5349b1994ce42e516945d064b4fc86bbf4bc3 GIT binary patch literal 1575 zcmah|Yi|=r6g?9=alBp<2*wazO$eoq170Z4;s6Chz$gtWK^89wO`M6@$X-XgV+8++ zFMvcUKJWwhQB}{~-Nq?NiY4#Ny>sum=bpLq?e8yN0bIiGISeUyy|C@+4c&TeyuRPn zo;8v6)>}GSGurk;(_34MjE%i_bYybKDxCg4N#Z>#pW8vuv)cN-Kq3F?$-51+q`O98 zVsTx+(OyRfZEx9ze$cKd?5p>J$m+m0b*FDekx%$k6FybpQu!~ds87(o^8@!@2wgK2XHWl35DrhyLedF(PPv0BOAVRQN$qv zg|Tfyg<^SIAN7uoqS|aD4~4@n928_X>B2=pVSLdK%u>I*V!|hSr4wt=Yw1o?hrZaU zbF6Kw$h6e~xyC)b_9KN0i{F#{!TnIxk@>W1=dRfZO-oy|N?MQmf%Utl=|?`R5AKOo zO52(m!xKDX7XwRil#brnwTY#^Rmx$l(L1)=3}PUJx0*bdl1g2L4Q z;WZl4sKON&S8`$vWe3J5((UmZE(XW92LhIrbzOigcS`6mASK<_=OO&0|==J++(!` z_H;jnno7b`C?-;(vvK_bxmVe_zzZjVU!W~oIF-3goZk)o4@$p;JRZg9r6hU_-NCQ1 z+=6*2#q2O9OUz<|dHgdjS5AD!Z~sLv5f^yM?=y0LPBt%a5HI5@l_Yi-&9}CNoP~lOvkkk zG~C230@6n4wb(Rd zy(Ddu*TH7Ird$@IQ%008uaI_4N8sVwc?JKwYbgB#b3yW>i>hTSgG8;;jW^qtYc^EL zbW9>JZ&^)Ox+e94z*tDcu1_|KUd(Cu7^4C!$qQs&OD88Xd$mb!zUWz`N(}mxK|hO< zUh^6j7(Pn5uRgErDZ>@Gdo_+H7KajuP<+M|n7-QnEH2gQ#S8554Y=&HKCKm|m8W*$ z1MbT6@^>Am+W!r&P+&xXbqyPMPK`vfZGn2pBJgBz_CmuZpAFF2l0_NnulN?didQiz z4W1)38@IXr!qpelK1bNr@HM^>xbc%MTg%EVSZ+?b#_rN9L$x@)Bu}`H&Uz$VxTyjo zeW&4jycD=zrpSH-Z$fSu0;5DaR3kxrB1zo4BuB%6&id2Sp`yV6T`Ex~hcNaIfsZ8% z7qNM4iG3=JVzX@O%)-;mndz=T7_r4Z7 zk7I&|0qsw4v(kHrd`2)z2xGL`APoMSPKZ;yb%e=7OdjEOLL}m+m^#ADA!d$|I)eT? zS@qxpdM40E&wGTEMjVf6)MoL(I|ZSBNWX(Vc81=9_WKC)SMQv?nLD6+9-4oSNBD^C zxclgqpU^k(DgCqUV|p`Foxa(#KYfC1my8d$5Q6Iu-~{&_xv=vKf@S$)>Dl`yctQ}L zcOl~5(JDoIMp~|UPl6D(hbzDZdtlJ;93 z`j~IsL64$ + * Write your own initialization here + * + * + * @generated modifiable + */ + private void readObject() {/*default - does nothing empty block */} + +} + + \ No newline at end of file diff --git a/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java new file mode 100644 index 0000000000..3448e5787b --- /dev/null +++ b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java @@ -0,0 +1,139 @@ + + + +/* Apache UIMA v3 - First created by JCasGen Wed Jun 01 09:28:33 CEST 2022 */ + +package org.apache.uima.test.jcasfeatureoffsettest; + + + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; + +import org.apache.uima.cas.impl.CASImpl; +import org.apache.uima.cas.impl.TypeImpl; +import org.apache.uima.cas.impl.TypeSystemImpl; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.JCasRegistry; + + + + +/** + * Updated by JCasGen Wed Jun 01 09:31:48 CEST 2022 + * XML source: /Users/bluefire/git/uima-uimaj/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1.xml + * @generated */ +public class Subtype extends Base { + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static String _TypeName = "org.apache.uima.test.jcasfeatureoffsettest.Subtype"; + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int typeIndexID = JCasRegistry.register(Subtype.class); + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int type = typeIndexID; + /** @generated + * @return index of the type + */ + @Override + public int getTypeIndexID() {return typeIndexID;} + + + /* ******************* + * Feature Offsets * + * *******************/ + + public final static String _FeatName_featureX = "featureX"; + + + /* Feature Adjusted Offsets */ + private final static CallSite _FC_featureX = TypeSystemImpl.createCallSite(Subtype.class, "featureX"); + private final static MethodHandle _FH_featureX = _FC_featureX.dynamicInvoker(); + + + /* ******************* + * Feature Offsets * + * *******************/ + + + + /* Feature Adjusted Offsets */ + + + /** Never called. Disable default constructor + * @generated */ + @Deprecated + @SuppressWarnings ("deprecation") + protected Subtype() {/* intentionally empty block */} + + /** Internal - constructor used by generator + * @generated + * @param casImpl the CAS this Feature Structure belongs to + * @param type the type of this Feature Structure + */ + public Subtype(TypeImpl type, CASImpl casImpl) { + super(type, casImpl); + readObject(); + } + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + */ + public Subtype(JCas jcas) { + super(jcas); + readObject(); + } + + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + * @param begin offset to the begin spot in the SofA + * @param end offset to the end spot in the SofA + */ + public Subtype(JCas jcas, int begin, int end) { + super(jcas); + setBegin(begin); + setEnd(end); + readObject(); + } + + /** + * + * Write your own initialization here + * + * + * @generated modifiable + */ + private void readObject() {/*default - does nothing empty block */} + + //*--------------* + //* Feature: featureX + + /** getter for featureX - gets + * @generated + * @return value of the feature + */ + public String getFeatureX() { + return _getStringValueNc(wrapGetIntCatchException(_FH_featureX)); + } + + /** setter for featureX - sets + * @generated + * @param v value to set into the feature + */ + public void setFeatureX(String v) { + _setStringValueNfc(wrapGetIntCatchException(_FH_featureX), v); + } + + } + + \ No newline at end of file diff --git a/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1.xml b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1.xml new file mode 100644 index 0000000000..24a143d73a --- /dev/null +++ b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor1.xml @@ -0,0 +1,60 @@ + + + + + typeSystemDescriptor + + + + + + 1.0 + + + + + + + + + + + + org.apache.uima.test.jcasfeatureoffsettest.Base + + + + + + uima.tcas.Annotation + + + + + + + org.apache.uima.test.jcasfeatureoffsettest.Subtype + + + + org.apache.uima.test.jcasfeatureoffsettest.Base + + + + + + featureX + + + + uima.cas.String + + + + + + + + + + diff --git a/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Base.class b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/classes/org/apache/uima/test/jcasfeatureoffsettest/Base.class new file mode 100644 index 0000000000000000000000000000000000000000..36a5349b1994ce42e516945d064b4fc86bbf4bc3 GIT binary patch literal 1575 zcmah|Yi|=r6g?9=alBp<2*wazO$eoq170Z4;s6Chz$gtWK^89wO`M6@$X-XgV+8++ zFMvcUKJWwhQB}{~-Nq?NiY4#Ny>sum=bpLq?e8yN0bIiGISeUyy|C@+4c&TeyuRPn zo;8v6)>}GSGurk;(_34MjE%i_bYybKDxCg4N#Z>#pW8vuv)cN-Kq3F?$-51+q`O98 zVsTx+(OyRfZEx9ze$cKd?5p>J$m+m0b*FDekx%$k6FybpQu!~ds87(o^8@!@2wgK2XHWl35DrhyLedF(PPv0BOAVRQN$qv zg|Tfyg<^SIAN7uoqS|aD4~4@n928_X>B2=pVSLdK%u>I*V!|hSr4wt=Yw1o?hrZaU zbF6Kw$h6e~xyC)b_9KN0i{F#{!TnIxk@>W1=dRfZO-oy|N?MQmf%Utl=|?`R5AKOo zO52(m!xKDX7XwRil#brnwTY#^Rmx$l(L1)=3}PUJx0*bdl1g2L4Q z;WZl4sKON&S8`$vWe3J5((UmZE(XW92LhIrbzOigcS`6mASK<_=OO&0|==J++(!` z_H;jnno7b`C?-;(vvK_bxmVe_zzZjVU!W~oIF-3goZk)o4@$p;JRZg9r6hU_-NCQ1 z+=6*2#q2O9OUz<|dHgdjS5AD!Z~sLv5f^yM?=y0LPBt%a5HI5@l_YjGr5GpWRf*A!SY4_ zkRKG*0+t{A0sbhL=gbVrl!q=^i4jTqtbJ-UN4%iBEn?65;DGh z(Rf|CyUpr~w5oM>7@RZere(TM1bUOH5)sQat15~cn22CpVCuZ6d{ccjC!I}IGac7H z&~OvC2*~!<$`%+&hQj9R(s8n>!Vm=B)(}OEzwT(z5Q}0O??iA{VCH-nj$$@ib)7R* zJaAmqD9}>FJ-jOrH*Atkon2gD`C`ZrhajJ+&{iPbdfSzidIu=W+>#pJ!1XB7xF5l+ zz<9SX&IzvJJ!FVY^}v!1(6+9F0%IW&yFS?{dNHTrV~h%{BrlM8EuEam?A0c@`J!i$DlzC&2K_8b zdd+KCVE8EIzWThfrwmu%?$tP+SR6_qLh%_>VEStNv$#~J7ca2KH{i0*`m|Plrfi6n9Fk{k^OI_pnQhl&ORbg4v{9KzT;1U{B5 zT*T(FCHAQ>ip{odsJzKNqy@t_!`+K1BHc^BF#{M!KRu}=Xw`#3TGL3P?{OYT-uqhU zJdOz-2DCrH%}Vbf@)^M>A&k*#gE07SIw4N+))6KTF?odB36Y4OV(JJphnP7=>InMp zWYvQY=$SwtJ?{}t8gV?PQJcjB?-YdkA^i^e*co~Y+V3OGU%hkoX6}IQd1(GQ9^oUl z@y zeES + * Write your own initialization here + * + * + * @generated modifiable + */ + private void readObject() {/*default - does nothing empty block */} + +} + + \ No newline at end of file diff --git a/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java new file mode 100644 index 0000000000..88471d905d --- /dev/null +++ b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2-jcas/src/org/apache/uima/test/jcasfeatureoffsettest/Subtype.java @@ -0,0 +1,131 @@ + + + +/* Apache UIMA v3 - First created by JCasGen Wed Jun 01 09:36:38 CEST 2022 */ + +package org.apache.uima.test.jcasfeatureoffsettest; + + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; + +import org.apache.uima.cas.impl.CASImpl; +import org.apache.uima.cas.impl.TypeImpl; +import org.apache.uima.cas.impl.TypeSystemImpl; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.JCasRegistry; + + + + +/** + * Updated by JCasGen Wed Jun 01 09:36:38 CEST 2022 + * XML source: /Users/bluefire/git/uima-uimaj/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2.xml + * @generated */ +public class Subtype extends Base { + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static String _TypeName = "org.apache.uima.test.jcasfeatureoffsettest.Subtype"; + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int typeIndexID = JCasRegistry.register(Subtype.class); + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int type = typeIndexID; + /** @generated + * @return index of the type + */ + @Override + public int getTypeIndexID() {return typeIndexID;} + + + /* ******************* + * Feature Offsets * + * *******************/ + + public final static String _FeatName_featureY = "featureY"; + + + /* Feature Adjusted Offsets */ + private final static CallSite _FC_featureY = TypeSystemImpl.createCallSite(Subtype.class, "featureY"); + private final static MethodHandle _FH_featureY = _FC_featureY.dynamicInvoker(); + + + /** Never called. Disable default constructor + * @generated */ + @Deprecated + @SuppressWarnings ("deprecation") + protected Subtype() {/* intentionally empty block */} + + /** Internal - constructor used by generator + * @generated + * @param casImpl the CAS this Feature Structure belongs to + * @param type the type of this Feature Structure + */ + public Subtype(TypeImpl type, CASImpl casImpl) { + super(type, casImpl); + readObject(); + } + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + */ + public Subtype(JCas jcas) { + super(jcas); + readObject(); + } + + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + * @param begin offset to the begin spot in the SofA + * @param end offset to the end spot in the SofA + */ + public Subtype(JCas jcas, int begin, int end) { + super(jcas); + setBegin(begin); + setEnd(end); + readObject(); + } + + /** + * + * Write your own initialization here + * + * + * @generated modifiable + */ + private void readObject() {/*default - does nothing empty block */} + + + + //*--------------* + //* Feature: featureY + + /** getter for featureY - gets + * @generated + * @return value of the feature + */ + public String getFeatureY() { + return _getStringValueNc(wrapGetIntCatchException(_FH_featureY)); + } + + /** setter for featureY - sets + * @generated + * @param v value to set into the feature + */ + public void setFeatureY(String v) { + _setStringValueNfc(wrapGetIntCatchException(_FH_featureY), v); + } + + } + + \ No newline at end of file diff --git a/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2.xml b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2.xml new file mode 100644 index 0000000000..f7b31009b6 --- /dev/null +++ b/uimaj-core/src/test/resources/JCasFeatureOffsetTest/SubtypeDescriptor2.xml @@ -0,0 +1,60 @@ + + + + + typeSystemDescriptor + + + + + + 1.0 + + + + + + + + + + + + org.apache.uima.test.jcasfeatureoffsettest.Base + + + + + + uima.tcas.Annotation + + + + + + + org.apache.uima.test.jcasfeatureoffsettest.Subtype + + + + org.apache.uima.test.jcasfeatureoffsettest.Base + + + + + + featureY + + + + uima.cas.String + + + + + + + + + + From d23f5067013962f26922b73f08114fb0d7b68336 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 1 Jun 2022 16:05:52 +0200 Subject: [PATCH 2/2] [UIMA-6468] Problem with JCas classes with re-used across different type systems - Avoid redundant definition of already loaded classes --- .../org/apache/uima/jcas/test/JCasFeatureOffsetTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java index a4834913a1..97b07fea0b 100644 --- a/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasFeatureOffsetTest.java @@ -186,6 +186,11 @@ public JCasIsolatingClassLoader(ClassLoader aParent) { @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { + Class alreadyLoadedClazz = findLoadedClass(name); + if (alreadyLoadedClazz != null) { + return alreadyLoadedClazz; + } + Class clazz = getParent().loadClass(name); if (!TOP.class.isAssignableFrom(clazz)) {