diff --git a/openjpa-kernel/pom.xml b/openjpa-kernel/pom.xml index 5b508438d..c2d7dd9be 100644 --- a/openjpa-kernel/pom.xml +++ b/openjpa-kernel/pom.xml @@ -74,9 +74,9 @@ provided - asm - asm - 3.2 + org.apache.xbean + xbean-asm4-shaded + 3.14 diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java index ba60affdb..949c4afed 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java @@ -18,84 +18,26 @@ */ package org.apache.openjpa.enhance; -import serp.bytecode.BCClass; - import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; import java.net.URLDecoder; -import org.apache.openjpa.lib.util.Localizer; +import org.apache.xbean.asm4.ClassReader; +import org.apache.xbean.asm4.ClassWriter; +import serp.bytecode.BCClass; + /** * Use ASM to add required StackMapTable attribute to the byte code generated by * Serp. - * - * This class contains a small hack to pickup different known shades of ASM - * to prevent classpath clashes. - * We first try to use standard ASM. If this is not available we try to pickup - * the shaded xbean-asm version used in OpenEJB, Geronimo or WAS. - * At last we try to use the shaded version from Spring. */ public final class AsmAdaptor { - private static final Localizer _loc = Localizer.forPackage(AsmAdaptor.class); - private static final int Java7_MajorVersion = 51; - private static Class cwClass; - private static Class crClass; - private static int COMPUTE_FRAMES; - private static Method classReaderAccept; - private static Method classWritertoByteArray; - private static Constructor classWriterConstructor; - private static Constructor classReaderConstructor; - - static { - // try the "real" asm first, then the others - tryClass("org.objectweb.asm."); - tryClass("org.apache.xbean.asm4."); - tryClass("org.apache.xbean.asm."); - tryClass("org.springframework.asm."); - - // get needed stuff - try { - COMPUTE_FRAMES = cwClass.getField("COMPUTE_FRAMES").getInt(null); - if (cwClass.getInterfaces().length > 0) { // ASM 3 - classReaderAccept = crClass.getMethod("accept", cwClass.getInterfaces()[0], int.class); - } else { // ASM 4 - classReaderAccept = crClass.getMethod("accept", cwClass.getSuperclass(), int.class); - } - classReaderConstructor = crClass.getConstructor(InputStream.class); - classWriterConstructor = cwClass.getConstructor(int.class); - classWritertoByteArray = cwClass.getMethod("toByteArray"); - } catch (Exception e) { - throw new IllegalStateException(_loc.get("static-asm-exception").getMessage(), e); - } - } - - private static void tryClass(final String s) { - if (cwClass == null) { - try { - cwClass = AsmAdaptor.class.getClassLoader().loadClass(s + "ClassWriter"); - } catch (Throwable t) { - //ignore - } - } - if (crClass == null) { - try { - crClass = AsmAdaptor.class.getClassLoader().loadClass(s + "ClassReader"); - } catch (Throwable t) { - //ignore - } - } - } - @SuppressWarnings("deprecation") public static void write(BCClass bc) throws IOException { if (bc.getMajorVersion() < Java7_MajorVersion) { @@ -143,24 +85,47 @@ public final class AsmAdaptor { out.write(java7Bytes); } - private static byte[] toJava7ByteArray(final BCClass bc, final byte[] classBytes) throws IOException { - final ByteArrayInputStream bais = new ByteArrayInputStream(classBytes); - final BufferedInputStream bis = new BufferedInputStream(bais); + private static byte[] toJava7ByteArray(BCClass bc, byte[] classBytes) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(classBytes); + BufferedInputStream bis = new BufferedInputStream(bais); - final ClassLoader cl = Thread.currentThread().getContextClassLoader(); - try { - final Object cw = classWriterConstructor.newInstance(COMPUTE_FRAMES); - final Object cr = classReaderConstructor.newInstance(bis); + ClassWriter cw = new BCClassWriter(ClassWriter.COMPUTE_FRAMES, bc.getClassLoader()); + ClassReader cr = new ClassReader(bis); + cr.accept(cw, 0); + return cw.toByteArray(); + } - // ClassWriter.getCommonSuperClass uses TCCL - Thread.currentThread().setContextClassLoader(bc.getClassLoader()); - classReaderAccept.invoke(cr, cw, 0); + private static class BCClassWriter extends ClassWriter { + private final ClassLoader _loader; - return (byte[]) classWritertoByteArray.invoke(cw); - } catch (Exception e) { - throw new IOException(e); - } finally { - Thread.currentThread().setContextClassLoader(cl); + BCClassWriter(int flags, ClassLoader loader) { + super(flags); + _loader = loader; + } + + @Override + protected String getCommonSuperClass(String type1, String type2) { + Class class1; + Class class2; + try { + class1 = _loader.loadClass(type1.replace('/', '.')); + class2 = _loader.loadClass(type2.replace('/', '.')); + } catch (ClassNotFoundException ex) { + throw new RuntimeException(ex); + } + if (class1.isAssignableFrom(class2)) { + return type1; + } + if (class2.isAssignableFrom(class1)) { + return type2; + } + if (class1.isInterface() || class2.isInterface()) { + return "java/lang/Object"; + } + do { + class1 = class1.getSuperclass(); + } while (!class1.isAssignableFrom(class2)); + return class1.getName().replace('.', '/'); } } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java index c4f0e67ce..f8b2459f4 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java @@ -87,7 +87,7 @@ public class PCClassFileTransformer * * @param repos metadata repository to use internally * @param flags enhancer configuration - * @param loader temporary class loader for loading intermediate classes + * @param tmpLoader temporary class loader for loading intermediate classes * @param devscan whether to scan the dev classpath for persistent types * if none are configured */ diff --git a/pom.xml b/pom.xml index 1e16fe559..93e5f5b27 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,8 @@ 2.3.0-SNAPSHOT + 1.6 + ${project.version} DefaultLevel=INFO UTF-8 @@ -81,10 +83,10 @@ 1.6.1 - 1.6 - 1.6 - 1.6 - 1.6 + ${java.version} + ${java.version} + ${java.version} + ${java.version}