From 7dd60fd64d090e0d5a3d2e4a27804e84e6330d17 Mon Sep 17 00:00:00 2001 From: Radek Felcman Date: Tue, 30 Jan 2024 20:21:20 +0100 Subject: [PATCH] ClassWeaver refresh - code generated by weaving (#2049) Contains following main changes: - Replacement of deprecated e.g. new Integer(...) by Integer.valueOf(...) - Generated _persistence_shallow_clone content is wrapped by try/catch - Remove dependency to JPA module (org.eclipse.persistence.internal.jpa.EntityManagerImpl class) in generated _persistence_checkFetched and _persistence_checkFetchedForSet There are some extensions in weaving test to more deeply check methods/logic generated by ClassWeaver. Signed-off-by: Radek Felcman --- .../exceptions/StaticWeaveException.java | 1 - .../jpa.test.weaving/pom.xml | 25 ++- .../main/resources/META-INF/persistence.xml | 31 ++++ .../jpa/weaving/WeavingChangeListener.java | 32 ++++ .../jpa/weaving/WeavingEntityInDir.java | 135 +++++++++++++++ .../tests/jpa/weaving/WeavingTest.java | 149 ++++++++++++++++- .../internal/jpa/weaving/ClassWeaver.java | 155 ++++++++++++------ 7 files changed, 473 insertions(+), 55 deletions(-) create mode 100644 jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/main/resources/META-INF/persistence.xml create mode 100644 jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingChangeListener.java create mode 100644 jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingEntityInDir.java diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/exceptions/StaticWeaveException.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/exceptions/StaticWeaveException.java index 354a4354329..dd93731e188 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/exceptions/StaticWeaveException.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/exceptions/StaticWeaveException.java @@ -143,7 +143,6 @@ public static StaticWeaveException exceptionPerformWeaving(Exception cause, Obje return loadingException; } - public String getResourceName(){ return resourceName; } diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.weaving/pom.xml b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/pom.xml index 5340b40e9be..31c0f41c926 100644 --- a/jpa/eclipselink.jpa.testapps/jpa.test.weaving/pom.xml +++ b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/pom.xml @@ -1,7 +1,7 @@ + ${db.driver} + ${db.url} + ${db.user} + ${db.pwd} + ${db.platform} @@ -110,6 +127,12 @@ ow2 + + ${db.driver} + ${db.url} + ${db.user} + ${db.pwd} + ${db.platform} org.eclipse.persistence.asm diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/main/resources/META-INF/persistence.xml b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000000..d320565de84 --- /dev/null +++ b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,31 @@ + + + + + + + org.eclipse.persistence.jpa.PersistenceProvider + org.eclipse.persistence.testing.models.jpa.weaving.WeavingEntityInDir + true + + + + + + + + + + diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingChangeListener.java b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingChangeListener.java new file mode 100644 index 00000000000..e115673e592 --- /dev/null +++ b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingChangeListener.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Contributors: +// Oracle - initial API and implementation +package org.eclipse.persistence.testing.models.jpa.weaving; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class WeavingChangeListener implements PropertyChangeListener { + + private boolean listenerInvoked = false; + + @Override + public void propertyChange(PropertyChangeEvent evt) { + listenerInvoked = true; + } + + public boolean isListenerInvoked() { + return listenerInvoked; + } +} diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingEntityInDir.java b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingEntityInDir.java new file mode 100644 index 00000000000..60c10b4646f --- /dev/null +++ b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/models/jpa/weaving/WeavingEntityInDir.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Contributors: +// Oracle - initial API and implementation +package org.eclipse.persistence.testing.models.jpa.weaving; + +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import org.eclipse.persistence.annotations.FetchAttribute; +import org.eclipse.persistence.annotations.FetchGroup; + +@Entity +@FetchGroup(name="FloatingPointFieldsOnly", + attributes={ + @FetchAttribute(name="floatField"), + @FetchAttribute(name="doubleField")}) +@Cacheable(false) +public class WeavingEntityInDir { + private int id; + private boolean booleanField; + private byte byteField; + private short shortField; + private int intField; + private long longField; + private float floatField; + private double doubleField; + private String stringField; + private byte[] blobField; + + public WeavingEntityInDir() { + } + + public WeavingEntityInDir(int id) { + this.id = id; + } + + @Id + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } + + public boolean isBooleanField() { + return booleanField; + } + + public void setBooleanField(boolean booleanField) { + this.booleanField = booleanField; + } + + public byte getByteField() { + return byteField; + } + + public void setByteField(byte byteField) { + this.byteField = byteField; + } + + public short getShortField() { + return shortField; + } + + public void setShortField(short shortFiled) { + this.shortField = shortFiled; + } + + public int getIntField() { + return intField; + } + + public void setIntField(int intField) { + this.intField = intField; + } + + public long getLongField() { + return longField; + } + + public void setLongField(long longField) { + this.longField = longField; + } + + public float getFloatField() { + return floatField; + } + + public void setFloatField(float floatField) { + this.floatField = floatField; + } + + public double getDoubleField() { + return doubleField; + } + + public void setDoubleField(double doubleField) { + this.doubleField = doubleField; + } + + public String getStringField() { + return stringField; + } + + public void setStringField(String stringField) { + this.stringField = stringField; + } + + @Lob + @Column(length=4800) + @Basic(fetch= FetchType.LAZY) + public byte[] getBlobField() { + return blobField; + } + + public void setBlobField(byte[] blobField) { + this.blobField = blobField; + } +} diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/tests/jpa/weaving/WeavingTest.java b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/tests/jpa/weaving/WeavingTest.java index 17af58fe630..072b4316ae9 100644 --- a/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/tests/jpa/weaving/WeavingTest.java +++ b/jpa/eclipselink.jpa.testapps/jpa.test.weaving/src/test/java/org/eclipse/persistence/testing/tests/jpa/weaving/WeavingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,24 +14,40 @@ // Oracle - initial API and implementation package org.eclipse.persistence.testing.tests.jpa.weaving; +import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; import junit.framework.Test; import junit.framework.TestSuite; +import org.eclipse.persistence.config.QueryHints; import org.eclipse.persistence.config.SystemProperties; +import org.eclipse.persistence.descriptors.changetracking.ChangeTracker; +import org.eclipse.persistence.internal.descriptors.PersistenceObject; +import org.eclipse.persistence.queries.FetchGroupTracker; import org.eclipse.persistence.testing.framework.jpa.junit.JUnitTestCase; +import org.eclipse.persistence.testing.models.jpa.weaving.WeavingChangeListener; +import org.eclipse.persistence.testing.models.jpa.weaving.WeavingEntityInDir; import org.eclipse.persistence.tools.weaving.jpa.StaticWeaveProcessor; import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; public class WeavingTest extends JUnitTestCase { + private final String PU_NAME = "weaving-dir-test-pu"; private final String WEAVING_ENTITY_CLASS = "org.eclipse.persistence.testing.models.jpa.weaving.WeavingEntity"; private final String SOURCE_JAR = "source.jar"; private final String TARGET_JAR = "target" + System.getProperty(SystemProperties.ASM_SERVICE, "") + ".jar"; + private final String DIR_WEAVING_ENTITY_CLASS = "org.eclipse.persistence.testing.models.jpa.weaving.WeavingEntityInDir"; + private final int ID = 1; + private final int NEW_INT_FIELD_VALUE = 100; + public WeavingTest() { super(); } @@ -40,14 +56,141 @@ public WeavingTest(String name) { super(name); } + @Override + public String getPersistenceUnitName() { + return PU_NAME; + } + public static Test suite() { TestSuite suite = new TestSuite(); suite.setName("WeavingTest"); - suite.addTest(new WeavingTest("testWeaving")); + suite.addTest(new WeavingTest("setup")); + suite.addTest(new WeavingTest("testWeavingDir")); + suite.addTest(new WeavingTest("testWeavingDirChangeListener")); + suite.addTest(new WeavingTest("testWeavingDirFetchGroup")); + suite.addTest(new WeavingTest("testWeavingDirInvokeGeneratedMethods")); + suite.addTest(new WeavingTest("testWeavingJar")); return suite; } - public void testWeaving() throws IOException, URISyntaxException, ClassNotFoundException, NoSuchMethodException { + public void setup() { + WeavingEntityInDir weavingEntityInDir = new WeavingEntityInDir(ID); + weavingEntityInDir.setBooleanField(true); + weavingEntityInDir.setByteField((byte)1); + weavingEntityInDir.setShortField((short)2); + weavingEntityInDir.setIntField(3); + weavingEntityInDir.setLongField(4); + weavingEntityInDir.setFloatField(1.1F); + weavingEntityInDir.setDoubleField(2.2); + weavingEntityInDir.setStringField("abcde"); + weavingEntityInDir.setBlobField(new byte[] {1, 2, 3}); + + EntityManager em = createEntityManager(); + try { + beginTransaction(em); + em.persist(weavingEntityInDir); + commitTransaction(em); + em.clear(); + } finally { + if (isTransactionActive(em)) { + rollbackTransaction(em); + } + closeEntityManager(em); + } + } + + public void testWeavingDir() throws Throwable { + final String PU_PATH = "META-INF/persistence.xml"; + URL source = Thread.currentThread().getContextClassLoader().getResource("."); + URL target = Thread.currentThread().getContextClassLoader().getResource("."); + URL puInfo = new URL("file:" + Thread.currentThread().getContextClassLoader().getResource(PU_PATH).getFile().replace(PU_PATH, "")); + + StaticWeaveProcessor staticWeaverProcessor= new StaticWeaveProcessor(source,target); + staticWeaverProcessor.setPersistenceInfo(puInfo.getFile()); + staticWeaverProcessor.performWeaving(); + + ClassLoader classLoader = new URLClassLoader(new URL[]{target}); + Class weavingEntityClass = classLoader.loadClass(DIR_WEAVING_ENTITY_CLASS); + //Check existence of various methods added to entity by weaving + assertNotNull(weavingEntityClass.getMethod("_persistence_post_clone")); + assertNotNull(weavingEntityClass.getMethod("_persistence_shallow_clone")); + assertNotNull(weavingEntityClass.getMethod("_persistence_getId")); + assertNotNull(weavingEntityClass.getMethod("_persistence_getCacheKey")); + assertNotNull(weavingEntityClass.getMethod("_persistence_getPropertyChangeListener")); + assertNotNull(weavingEntityClass.getMethod("_persistence_checkFetched", String.class)); + assertNotNull(weavingEntityClass.getMethod("_persistence_checkFetchedForSet", String.class)); + + } + + public void testWeavingDirChangeListener() { + WeavingEntityInDir weavingEntityInDir = null; + EntityManager em = createEntityManager(); + try { + beginTransaction(em); + weavingEntityInDir = em.find(WeavingEntityInDir.class, ID); + // Verify _persistence_checkFetchedForSet(...) as blobField has "@Basic(fetch= FetchType.LAZY)" + weavingEntityInDir.setBlobField(null); + commitTransaction(em); + } finally { + if (isTransactionActive(em)) { + rollbackTransaction(em); + } + closeEntityManager(em); + } + + //Test change listener support generated by weaving + WeavingChangeListener weavingChangeListener = new WeavingChangeListener(); + ((ChangeTracker)weavingEntityInDir)._persistence_setPropertyChangeListener(weavingChangeListener); + weavingEntityInDir.setIntField(NEW_INT_FIELD_VALUE); + assertTrue(weavingChangeListener.isListenerInvoked()); + } + + public void testWeavingDirFetchGroup() { + WeavingEntityInDir weavingEntityInDir = null; + EntityManager em = createEntityManager(); + try { + TypedQuery query = em.createQuery("SELECT w FROM WeavingEntityInDir w WHERE w.id = ?1", WeavingEntityInDir.class); + query.setHint(QueryHints.FETCH_GROUP_NAME, "FloatingPointFieldsOnly"); + query.setParameter(1, ID); + weavingEntityInDir = (WeavingEntityInDir)query.getSingleResult(); + assertNotNull(((FetchGroupTracker)weavingEntityInDir)._persistence_getFetchGroup()); + assertEquals(3, weavingEntityInDir.getIntField()); + assertNull(((FetchGroupTracker)weavingEntityInDir)._persistence_getFetchGroup()); + } finally { + if (isTransactionActive(em)) { + rollbackTransaction(em); + } + closeEntityManager(em); + } + } + + public void testWeavingDirInvokeGeneratedMethods() throws Throwable { + final int NEW_INT_FIELD_VALUE = 100; + WeavingEntityInDir weavingEntityInDir = null; + EntityManager em = createEntityManager(); + try { + weavingEntityInDir = em.find(WeavingEntityInDir.class, ID); + } finally { + if (isTransactionActive(em)) { + rollbackTransaction(em); + } + closeEntityManager(em); + } + + //Test _persistence_set_intField method generated by weaving + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(void.class, int.class); + MethodHandle mh = lookup.findVirtual(WeavingEntityInDir.class, "_persistence_set_intField", mt); + mh.invoke(weavingEntityInDir, NEW_INT_FIELD_VALUE); + assertEquals(NEW_INT_FIELD_VALUE, weavingEntityInDir.getIntField()); + assertEquals(NEW_INT_FIELD_VALUE, ((PersistenceObject)weavingEntityInDir)._persistence_get("intField")); + + //Test _persistence_shallow_clone method generated by weaving + Object weavingEntityInDirCloned = ((PersistenceObject)weavingEntityInDir)._persistence_shallow_clone(); + assertNotNull(weavingEntityInDirCloned); + } + + public void testWeavingJar() throws IOException, URISyntaxException, ClassNotFoundException, NoSuchMethodException { URL source = Thread.currentThread().getContextClassLoader().getResource(SOURCE_JAR); URL target = new URL(source.toString().replace(SOURCE_JAR, TARGET_JAR)); diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/weaving/ClassWeaver.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/weaving/ClassWeaver.java index 0d4a97f0cfb..83863e70c2c 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/weaving/ClassWeaver.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/weaving/ClassWeaver.java @@ -79,7 +79,6 @@ public class ClassWeaver extends ClassVisitor { public static final String FETCHGROUP_SHORT_SIGNATURE = "org/eclipse/persistence/queries/FetchGroup"; public static final String FETCHGROUP_SIGNATURE = "Lorg/eclipse/persistence/queries/FetchGroup;"; public static final String SESSION_SIGNATURE = "Lorg/eclipse/persistence/sessions/Session;"; - public static final String ENTITY_MANAGER_IMPL_SHORT_SIGNATURE = "org/eclipse/persistence/internal/jpa/EntityManagerImpl"; public static final String PBOOLEAN_SIGNATURE = "Z"; public static final String LONG_SIGNATURE = "J"; @@ -97,6 +96,9 @@ public class ClassWeaver extends ClassVisitor { public static final String JPA_TRANSIENT_DESCRIPTION = "Ljakarta/persistence/Transient;"; public static final String XML_TRANSIENT_DESCRIPTION = "Ljakarta/xml/bind/annotation/XmlTransient;"; + // Jakarta Persistence API + public static final String JPA_ENTITY_NOT_FOUND_EXCEPTION_SHORT_SIGNATURE = "jakarta/persistence/EntityNotFoundException"; + public static final String PERSISTENCE_SET = Helper.PERSISTENCE_SET; public static final String PERSISTENCE_GET = Helper.PERSISTENCE_GET; @@ -598,32 +600,22 @@ public void addSetterMethodForFieldAccess(ClassDetails classDetails, AttributeDe // e.g. if it is an integer: Integer.valueOf(attribute) // This is the first part of the wrapping String wrapper = ClassWeaver.wrapperFor(attributeDetails.getReferenceClassType().getSort()); - if (wrapper != null) { - cv_set.visitTypeInsn(Opcodes.valueInt("NEW"), wrapper); - cv_set.visitInsn(Opcodes.valueInt("DUP")); - } - // load the method argument cv_set.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); cv_set.visitFieldInsn(Opcodes.valueInt("GETFIELD"), classDetails.getClassName(), attribute, attributeDetails.getReferenceClassType().getDescriptor()); if (wrapper != null) { - // invoke the constructor for wrapping - // e.g. Integer.valueOf(variableName) - cv_set.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), wrapper, "", "(" + attributeDetails.getReferenceClassType().getDescriptor() + ")V", false); - - // wrap the method argument - // e.g. Integer.valueOf(argument) - cv_set.visitTypeInsn(Opcodes.valueInt("NEW"), wrapper); - cv_set.visitInsn(Opcodes.valueInt("DUP")); + //convert from global field e.g. Integer.valueOf(this.intField) + cv_set.visitMethodInsn(Opcodes.valueInt("INVOKESTATIC"), wrapper, "valueOf", "(" + attributeDetails.getReferenceClassType().getDescriptor() + ")L" + wrapper + ";", false); + //convert from method argument e.g. Integer.valueOf(var1) cv_set.visitVarInsn(opcode, 1); - cv_set.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), wrapper, "", "(" + attributeDetails.getReferenceClassType().getDescriptor() + ")V", false); + cv_set.visitMethodInsn(Opcodes.valueInt("INVOKESTATIC"), wrapper, "valueOf", "(" + attributeDetails.getReferenceClassType().getDescriptor() + ")L" + wrapper + ";", false); } else { // if we are not wrapping the argument, just load it cv_set.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); } - // _persistence_propertyChange("variableName", variableName, - // argument); + // _persistence_propertyChange("variableName", variableName, argument); + //e.g. this._persistence_propertyChange("intField", Integer.valueOf(this.intField), Integer.valueOf(var1)); cv_set.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), classDetails.getClassName(), "_persistence_propertyChange", "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", false); } else { if (attributeDetails.weaveValueHolders()) { @@ -881,10 +873,34 @@ public void addShallowClone(ClassDetails classDetails) { // create the _persistence_shallow_clone() method MethodVisitor cv_clone = cv.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "_persistence_shallow_clone", "()Ljava/lang/Object;", null, null); + Label l0 = ASMFactory.createLabel(); + Label l1 = ASMFactory.createLabel(); + Label l2 = ASMFactory.createLabel(); + // try { + cv_clone.visitTryCatchBlock(l0, l1, l2, "java/lang/CloneNotSupportedException"); + cv_clone.visitLabel(l0); // return super.clone(); cv_clone.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); - cv_clone.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), "java/lang/Object", "clone", "()Ljava/lang/Object;", false); - + cv_clone.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), "java/lang/Object", "clone", "()" + OBJECT_SIGNATURE, false); + // } catch (CloneNotSupportedException e) { + cv_clone.visitLabel(l1); + cv_clone.visitInsn(Opcodes.valueInt("ARETURN")); + cv_clone.visitLabel(l2); + cv_clone.visitFrame(Opcodes.valueInt("F_SAME1"), 0, null, 1, new Object[]{"java/lang/CloneNotSupportedException"}); + cv_clone.visitVarInsn(Opcodes.valueInt("ASTORE"), 1); + // throw new InternalError(e); + Label l3 = ASMFactory.createLabel(); + cv_clone.visitLabel(l3); + cv_clone.visitTypeInsn(Opcodes.valueInt("NEW"), "java/lang/InternalError"); + cv_clone.visitInsn(Opcodes.valueInt("DUP")); + cv_clone.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); + cv_clone.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), "java/lang/InternalError", "", "(Ljava/lang/Throwable;)V", false); + cv_clone.visitInsn(Opcodes.valueInt("ATHROW")); + Label l4 = ASMFactory.createLabel(); + cv_clone.visitLabel(l4); + cv_clone.visitLocalVariable("e", "Ljava/lang/CloneNotSupportedException;", null, l3, l4, 1); + cv_clone.visitLocalVariable("this", "L" + classDetails.getClassName() + ";", null, l0, l4, 0); + // Method end - implicit return cv_clone.visitInsn(Opcodes.valueInt("ARETURN")); cv_clone.visitMaxs(0, 0); } @@ -1120,13 +1136,17 @@ public void addFetchGroupVariables() { * _persistence_fetchGroup.containsAttribute(attribute); } *

* public void _persistence_checkFetched(String attribute) { if - * (this._persistence_fetchGroup != null) { - * EntityManagerImpl.processUnfetchedAttribute(this, attribute); } } + * (!this._persistence_isAttributeFetched(var1)) { + * String var2 = this._persistence_getFetchGroup().onUnfetchedAttribute(this, var1); + * if (var2 != null) { + * throw new EntityNotFoundException(var2);}}} *

* * public void _persistence_checkSetFetched(String attribute) { if - * (this._persistence_fetchGroup != null) { - * EntityManagerImpl.processUnfetchedAttributeForSet(this, attribute); } } + * if (!this._persistence_isAttributeFetched(var1)) { + * String var2 = this._persistence_getFetchGroup().onUnfetchedAttributeForSet(this, var1); + * if (var2 != null) { + * throw new EntityNotFoundException(var2);}}} */ public void addFetchGroupMethods(ClassDetails classDetails) { MethodVisitor cv_getSession = cv.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "_persistence_getSession", "()" + SESSION_SIGNATURE, null, null); @@ -1193,33 +1213,68 @@ public void addFetchGroupMethods(ClassDetails classDetails) { cv_isAttributeFetched.visitInsn(Opcodes.valueInt("IRETURN")); cv_isAttributeFetched.visitMaxs(0, 0); - MethodVisitor cv_checkFetched = cv.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "_persistence_checkFetched", "(Ljava/lang/String;)V", null, null); - cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); - cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); - cv_checkFetched.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), classDetails.getClassName(), "_persistence_isAttributeFetched", "(Ljava/lang/String;)Z", false); - gotoReturn = ASMFactory.createLabel(); - cv_checkFetched.visitJumpInsn(Opcodes.valueInt("IFNE"), gotoReturn); - cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); - cv_checkFetched.visitTypeInsn(Opcodes.valueInt("CHECKCAST"), FETCHGROUP_TRACKER_SHORT_SIGNATURE); - cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); - cv_checkFetched.visitMethodInsn(Opcodes.valueInt("INVOKESTATIC"), ENTITY_MANAGER_IMPL_SHORT_SIGNATURE, "processUnfetchedAttribute", "(" + FETCHGROUP_TRACKER_SIGNATURE + "Ljava/lang/String;)V", false); - cv_checkFetched.visitLabel(gotoReturn); - cv_checkFetched.visitInsn(Opcodes.valueInt("RETURN")); - cv_checkFetched.visitMaxs(0, 0); - - MethodVisitor cv_checkFetchedForSet = cv.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "_persistence_checkFetchedForSet", "(Ljava/lang/String;)V", null, null); - cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); - cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); - cv_checkFetchedForSet.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), classDetails.getClassName(), "_persistence_isAttributeFetched", "(Ljava/lang/String;)Z", false); - gotoReturn = ASMFactory.createLabel(); - cv_checkFetchedForSet.visitJumpInsn(Opcodes.valueInt("IFNE"), gotoReturn); - cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); - cv_checkFetchedForSet.visitTypeInsn(Opcodes.valueInt("CHECKCAST"), FETCHGROUP_TRACKER_SHORT_SIGNATURE); - cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); - cv_checkFetchedForSet.visitMethodInsn(Opcodes.valueInt("INVOKESTATIC"), ENTITY_MANAGER_IMPL_SHORT_SIGNATURE, "processUnfetchedAttributeForSet", "(" + FETCHGROUP_TRACKER_SIGNATURE + "Ljava/lang/String;)V", false); - cv_checkFetchedForSet.visitLabel(gotoReturn); - cv_checkFetchedForSet.visitInsn(Opcodes.valueInt("RETURN")); - cv_checkFetchedForSet.visitMaxs(0, 0); + MethodVisitor cv_checkFetched = cv.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "_persistence_checkFetched", "(" + STRING_SIGNATURE + ")V", null, null); { + Label l0 = ASMFactory.createLabel(); + cv_checkFetched.visitLabel(l0); + // if (!this._persistence_isAttributeFetched(attributeName)) { + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); + cv_checkFetched.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), classDetails.getClassName(), "_persistence_isAttributeFetched", "(" + STRING_SIGNATURE + ")Z", false); + Label l1 = ASMFactory.createLabel(); + cv_checkFetched.visitJumpInsn(Opcodes.valueInt("IFNE"), l1); + // String errorMsg = _persistence_getFetchGroup(). + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); + cv_checkFetched.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), classDetails.getClassName(), "_persistence_getFetchGroup", "()" + FETCHGROUP_SIGNATURE, false); + // .onUnfetchedAttribute(entity, attributeName); + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); + cv_checkFetched.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), FETCHGROUP_SHORT_SIGNATURE, "onUnfetchedAttribute", "(" + FETCHGROUP_TRACKER_SIGNATURE + STRING_SIGNATURE + ")" + STRING_SIGNATURE, false); + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ASTORE"), 2); + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 2); + cv_checkFetched.visitJumpInsn(Opcodes.valueInt("IFNULL"), l1); + // throw new EntityNotFoundException(errorMsg); + cv_checkFetched.visitTypeInsn(Opcodes.valueInt("NEW"), JPA_ENTITY_NOT_FOUND_EXCEPTION_SHORT_SIGNATURE); + cv_checkFetched.visitInsn(Opcodes.valueInt("DUP")); + cv_checkFetched.visitVarInsn(Opcodes.valueInt("ALOAD"), 2); + cv_checkFetched.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), JPA_ENTITY_NOT_FOUND_EXCEPTION_SHORT_SIGNATURE, "", "(" + STRING_SIGNATURE + ")V", false); + cv_checkFetched.visitInsn(Opcodes.valueInt("ATHROW")); + cv_checkFetched.visitLabel(l1); + cv_checkFetched.visitFrame(Opcodes.valueInt("F_APPEND"), 1, new Object[]{"java/lang/String"}, 0, null); + cv_checkFetched.visitInsn(Opcodes.valueInt("RETURN")); + cv_checkFetched.visitMaxs(0, 0); + } + + MethodVisitor cv_checkFetchedForSet = cv.visitMethod(Opcodes.valueInt("ACC_PUBLIC"), "_persistence_checkFetchedForSet", "(" + STRING_SIGNATURE + ")V", null, null); + { + Label l0 = ASMFactory.createLabel(); + cv_checkFetchedForSet.visitLabel(l0); + // if (!this._persistence_isAttributeFetched(attributeName)) { + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); + cv_checkFetchedForSet.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), classDetails.getClassName(), "_persistence_isAttributeFetched", "(" + STRING_SIGNATURE + ")Z", false); + Label l1 = ASMFactory.createLabel(); + cv_checkFetchedForSet.visitJumpInsn(Opcodes.valueInt("IFNE"), l1); + // String errorMsg = _persistence_getFetchGroup(). + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); + cv_checkFetchedForSet.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), classDetails.getClassName(), "_persistence_getFetchGroup", "()" + FETCHGROUP_SIGNATURE, false); + // .onUnfetchedAttribute(entity, attributeName); + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 0); + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 1); + cv_checkFetchedForSet.visitMethodInsn(Opcodes.valueInt("INVOKEVIRTUAL"), FETCHGROUP_SHORT_SIGNATURE, "onUnfetchedAttributeForSet", "(" + FETCHGROUP_TRACKER_SIGNATURE + STRING_SIGNATURE + ")" + STRING_SIGNATURE, false); + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ASTORE"), 2); + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 2); + cv_checkFetchedForSet.visitJumpInsn(Opcodes.valueInt("IFNULL"), l1); + // throw new EntityNotFoundException(errorMsg); + cv_checkFetchedForSet.visitTypeInsn(Opcodes.valueInt("NEW"), JPA_ENTITY_NOT_FOUND_EXCEPTION_SHORT_SIGNATURE); + cv_checkFetchedForSet.visitInsn(Opcodes.valueInt("DUP")); + cv_checkFetchedForSet.visitVarInsn(Opcodes.valueInt("ALOAD"), 2); + cv_checkFetchedForSet.visitMethodInsn(Opcodes.valueInt("INVOKESPECIAL"), JPA_ENTITY_NOT_FOUND_EXCEPTION_SHORT_SIGNATURE, "", "(" + STRING_SIGNATURE + ")V", false); + cv_checkFetchedForSet.visitInsn(Opcodes.valueInt("ATHROW")); + cv_checkFetchedForSet.visitLabel(l1); + cv_checkFetchedForSet.visitFrame(Opcodes.valueInt("F_APPEND"), 1, new Object[]{"java/lang/String"}, 0, null); + cv_checkFetchedForSet.visitInsn(Opcodes.valueInt("RETURN")); + cv_checkFetchedForSet.visitMaxs(0, 0); + } } /**