This is an automated email from the ASF dual-hosted git repository. struberg pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openjpa.git
commit b51d003ed98aa7663465aad7c9a1b554b006cc7d Author: Mark Struberg <strub...@apache.org> AuthorDate: Mon May 22 15:40:32 2023 +0200 OPENJPA-2911 start migrating away from Serp This introduces 2 methods to tronsform Serp BCClass -> ASM ClassWriter and ASM ClassWriter -> Serp BCClass --- .../org/apache/openjpa/ant/PCEnhancerTask.java | 2 +- .../org/apache/openjpa/enhance/PCEnhancer.java | 52 ++++++++++++++++------ .../apache/openjpa/meta/MetaDataRepository.java | 3 ++ .../org/apache/openjpa/util/ProxyManagerImpl.java | 1 + .../org/apache/openjpa/util/asm/AsmHelper.java | 32 +++++++++++++ .../openjpa/util/{ => asm}/ClassWriterTracker.java | 30 ++++++++++--- .../org/apache/openjpa/lib/conf/PluginValue.java | 2 +- ...TestDataCachingAndUnenhancedPropertyAccess.java | 4 +- .../query/common/apps/RuntimeTest2.java | 2 +- 9 files changed, 105 insertions(+), 23 deletions(-) diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/ant/PCEnhancerTask.java b/openjpa-kernel/src/main/java/org/apache/openjpa/ant/PCEnhancerTask.java index 180161f8f..6e7367466 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/ant/PCEnhancerTask.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/ant/PCEnhancerTask.java @@ -89,5 +89,5 @@ public class PCEnhancerTask OpenJPAConfiguration conf = (OpenJPAConfiguration) getConfiguration(); MetaDataRepository repos = conf.newMetaDataRepositoryInstance(); PCEnhancer.run(conf, files, flags, repos, null, getClassLoader ()); - } + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java index bb868dd2e..72b6380c8 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java @@ -20,6 +20,7 @@ package org.apache.openjpa.enhance; import java.io.Externalizable; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; @@ -28,12 +29,15 @@ import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.ObjectStreamException; +import java.io.OutputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; +import java.net.URL; +import java.net.URLDecoder; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.ArrayList; @@ -90,6 +94,8 @@ import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.ShortId; import org.apache.openjpa.util.StringId; import org.apache.openjpa.util.UserException; +import org.apache.openjpa.util.asm.AsmHelper; +import org.apache.openjpa.util.asm.ClassWriterTracker; import serp.bytecode.BCClass; import serp.bytecode.BCField; @@ -116,6 +122,7 @@ import serp.bytecode.TableSwitchInstruction; * classes. * * @author Abe White + * @author Mark Struberg */ public class PCEnhancer { // Designates a version for maintaining compatbility when PCEnhancer @@ -284,8 +291,10 @@ public class PCEnhancer { if (repos == null) { _repos = conf.newMetaDataRepositoryInstance(); _repos.setSourceMode(MetaDataModes.MODE_META); - } else + } else { _repos = repos; + } + _meta = _repos.getMetaData(type.getType(), loader, false); configureOptimizeIdCopy(); @@ -327,7 +336,7 @@ public class PCEnhancer { } /** - * Whether or not <code>className</code> is the name for a + * Whether <code>className</code> is the name for a * dynamically-created persistence-capable subclass. * * @since 1.1.0 @@ -621,27 +630,44 @@ public class PCEnhancer { */ public void record() throws IOException { - if (_managedType != _pc && getRedefine()) - record(_managedType); - record(_pc); + if (_managedType != _pc && getRedefine()) { + record(AsmHelper.toClassWriter(_managedType)); + } + + record(AsmHelper.toClassWriter(_pc)); + if (_oids != null) for (Object oid : _oids) { - record((BCClass) oid); + record(AsmHelper.toClassWriter((BCClass) oid)); } } /** * Write the given class. */ - private void record(BCClass bc) + private void record(ClassWriterTracker cwt) throws IOException { if (_writer != null) - _writer.write(bc); - else if (_dir == null) - AsmAdaptor.write(bc); + _writer.write(AsmHelper.toBCClass(cwt)); + else if (_dir == null) { + String name = cwt.getName().replace(".", "/"); + ClassLoader cl = cwt.getClassLoader(); + if (cl == null) { + cl = Thread.currentThread().getContextClassLoader(); + } + final URL resource = cl.getResource(name + ".class"); + try (OutputStream out = new FileOutputStream(URLDecoder.decode(resource.getFile()))) { + out.write(cwt.getCw().toByteArray()); + out.flush(); + } + } else { - File dir = Files.getPackageFile(_dir, bc.getPackageName(), true); - AsmAdaptor.write(bc, new File(dir, bc.getClassName() + ".class")); + String name = cwt.getName().replace(".", "/") + ".class"; + File targetFile = new File(_dir, name); + if (!targetFile.getParentFile().exists()) { + targetFile.getParentFile().mkdirs(); + } + java.nio.file.Files.write(targetFile.toPath(), cwt.getCw().toByteArray()); } } @@ -4920,7 +4946,7 @@ public class PCEnhancer { project.clear(); } if(log.isInfoEnabled() && !persAwareClasses.isEmpty()){ - log.info(_loc.get("pers-aware-classes", persAwareClasses.size(), persAwareClasses)); + log.info(_loc.get("pers-aware-classes", persAwareClasses.size(), persAwareClasses)); } return true; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java index 5ad8c92db..f511801bc 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java @@ -1602,6 +1602,9 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con if (_log.isTraceEnabled()) _log.trace(nsme); } + catch (NoClassDefFoundError ndcfe) { + throw ndcfe; + } return null; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java index 0f1c2dc41..b1f6b6eb6 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java @@ -57,6 +57,7 @@ import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.lib.util.StringUtil; import org.apache.openjpa.util.asm.AsmHelper; +import org.apache.openjpa.util.asm.ClassWriterTracker; import org.apache.openjpa.util.proxy.DelayedArrayListProxy; import org.apache.openjpa.util.proxy.DelayedHashSetProxy; import org.apache.openjpa.util.proxy.DelayedLinkedHashSetProxy; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java index ec84023a3..5f6ac6860 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java @@ -16,11 +16,17 @@ */ package org.apache.openjpa.util.asm; +import java.io.ByteArrayInputStream; import java.lang.reflect.Method; +import org.apache.xbean.asm9.ClassReader; +import org.apache.xbean.asm9.ClassWriter; import org.apache.xbean.asm9.Opcodes; import org.apache.xbean.asm9.Type; +import serp.bytecode.BCClass; +import serp.bytecode.Project; + /** * Utility methods to deal with ASM bytecode * @@ -31,6 +37,32 @@ public final class AsmHelper { // utility class ct } + /** + * temporary helper class to convert BCClass to ASM + * @deprecated must get removed when done with migrating from Serp to ASM + */ + public static ClassWriterTracker toClassWriter(BCClass bcClass) { + ClassReader cr = new ClassReader(bcClass.toByteArray()); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + cr.accept(cw, 0); // 0 -> don't skip anything + ClassWriterTracker cwt = new ClassWriterTracker(cw, bcClass.getClassLoader()); + cwt.setName(bcClass.getName()); + + return cwt; + } + + /** + * temporary helper class to convert ClassWriterTracker to BCClass + * @deprecated must get removed when done with migrating from Serp to ASM + */ + public static BCClass toBCClass(ClassWriterTracker cwt) { + final byte[] classBytes = cwt.getCw().toByteArray(); + BCClass bcClass = new Project().loadClass(new ByteArrayInputStream(classBytes), cwt.getClassLoader()); + bcClass.setName(cwt.getName()); + return bcClass; + } + + /** * Calclates the proper Return instruction opcode for the given class * diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ClassWriterTracker.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassWriterTracker.java similarity index 72% rename from openjpa-kernel/src/main/java/org/apache/openjpa/util/ClassWriterTracker.java rename to openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassWriterTracker.java index 0bcee1d47..bd00f85ee 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ClassWriterTracker.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassWriterTracker.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.openjpa.util; +package org.apache.openjpa.util.asm; import java.util.ArrayList; import java.util.List; @@ -30,21 +30,33 @@ import org.apache.xbean.asm9.MethodVisitor; public class ClassWriterTracker { private final ClassWriter cw; + private final ClassLoader cl; + + private String name; private List<String> createdMethods = new ArrayList<>(); public ClassWriterTracker(ClassWriter cw) { + this(cw, null); + } + + public ClassWriterTracker(ClassWriter cw, ClassLoader cl) { this.cw = cw; + this.cl = cl; } public ClassWriter getCw() { return cw; } + public ClassLoader getClassLoader() { + return cl; + } + public MethodVisitor visitMethod(final int access, - final String name, - final String descriptor, - final String signature, - final String[] exceptionTypes) { + final String name, + final String descriptor, + final String signature, + final String[] exceptionTypes) { MethodVisitor mv = cw.visitMethod(access, name, descriptor, signature, exceptionTypes); createdMethods.add(name + descriptor); @@ -55,4 +67,12 @@ public class ClassWriterTracker { public boolean hasMethod(final String name, final String descriptor) { return createdMethods.contains(name + descriptor); } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginValue.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginValue.java index 3cac19630..4b559ac83 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginValue.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginValue.java @@ -163,7 +163,7 @@ public class PluginValue extends ObjectValue { @Override public void setString(String str) { - assertChangeable(); + assertChangeable(); _name = Configurations.getClassName(str); _name = unalias(_name); _props = Configurations.getProperties(str); diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestDataCachingAndUnenhancedPropertyAccess.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestDataCachingAndUnenhancedPropertyAccess.java index e16cb23b4..0b9250ef4 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestDataCachingAndUnenhancedPropertyAccess.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestDataCachingAndUnenhancedPropertyAccess.java @@ -39,8 +39,8 @@ public class TestDataCachingAndUnenhancedPropertyAccess // Not all databases support GenerationType.IDENTITY column(s) if (!((JDBCConfiguration) emf.getConfiguration()). getDBDictionaryInstance().supportsAutoAssign) { - return; - } + return; + } EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); em.persist(new UnenhancedIdentityIdPropertyAccess()); diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/common/apps/RuntimeTest2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/common/apps/RuntimeTest2.java index f09e57525..9f1522254 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/common/apps/RuntimeTest2.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/common/apps/RuntimeTest2.java @@ -22,7 +22,7 @@ import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; /** - * <p>Persitent type used in testing.</p> + * <p>Persistent type used in testing.</p> * * @author Abe White */