You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2012/08/10 10:49:04 UTC
svn commit: r1371607 -
/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java
Author: struberg
Date: Fri Aug 10 08:49:03 2012
New Revision: 1371607
URL: http://svn.apache.org/viewvc?rev=1371607&view=rev
Log:
OPENJPA-2171 pickup existing ASM shades if possible
To prevent classpath clashes we try to pickup a few
known ASM shades.
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java?rev=1371607&r1=1371606&r2=1371607&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/AsmAdaptor.java Fri Aug 10 08:49:03 2012
@@ -18,26 +18,75 @@
*/
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 serp.bytecode.BCClass;
-
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassWriter;
-
/**
* 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 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.asm.");
+ tryClass("org.springframework.asm.");
+
+ // get needed stuff
+ try {
+ COMPUTE_FRAMES = cwClass.getField("COMPUTE_FRAMES").getInt(null);
+ classReaderAccept = crClass.getMethod("accept", cwClass.getInterfaces()[0], int.class);
+ classReaderConstructor = crClass.getConstructor(InputStream.class);
+ classWriterConstructor = cwClass.getConstructor(int.class);
+ classWritertoByteArray = cwClass.getMethod("toByteArray");
+ } catch (Exception e) {
+ throw new IllegalStateException("can't find all needed ASM stuff", 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) {
@@ -85,47 +134,24 @@ public final class AsmAdaptor {
out.write(java7Bytes);
}
- private static byte[] toJava7ByteArray(BCClass bc, byte[] classBytes) throws IOException {
- ByteArrayInputStream bais = new ByteArrayInputStream(classBytes);
- BufferedInputStream bis = new BufferedInputStream(bais);
-
- ClassWriter cw = new BCClassWriter(ClassWriter.COMPUTE_FRAMES, bc.getClassLoader());
- ClassReader cr = new ClassReader(bis);
- cr.accept(cw, 0);
- return cw.toByteArray();
- }
-
- private static class BCClassWriter extends ClassWriter {
- private final ClassLoader _loader;
-
- 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('.', '/');
+ private static byte[] toJava7ByteArray(final BCClass bc, final byte[] classBytes) throws IOException {
+ final ByteArrayInputStream bais = new ByteArrayInputStream(classBytes);
+ final 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.getCommonSuperClass uses TCCL
+ Thread.currentThread().setContextClassLoader(bc.getClassLoader());
+ classReaderAccept.invoke(cr, cw, 0);
+
+ return (byte[]) classWritertoByteArray.invoke(cw);
+ } catch (Exception e) {
+ throw new IOException(e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(cl);
}
}
}