OPENJPA-2283 : Merge changes from 2.3.x to trunk.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1532523 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Richard G. Curtis 2013-10-15 20:32:07 +00:00
parent 3b94663fe2
commit e719ad01e9
4 changed files with 53 additions and 85 deletions

View File

@ -74,9 +74,9 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.2</version>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-asm4-shaded</artifactId>
<version>3.14</version>
</dependency>
</dependencies>

View File

@ -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('.', '/');
}
}
}

View File

@ -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
*/

11
pom.xml
View File

@ -43,6 +43,9 @@
<version>2.3.0-SNAPSHOT</version>
<properties>
<java.class.version>1.6</java.class.version>
<java.testclass.version>1.6</java.testclass.version>
<openjpa.version>${project.version}</openjpa.version>
<openjpa.Log>DefaultLevel=INFO</openjpa.Log>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -81,10 +84,10 @@
<!-- other common versions -->
<slf4jVersion>1.6.1</slf4jVersion>
<!-- Compile Java source/target class level -->
<compile.class.source>1.6</compile.class.source>
<compile.class.target>1.6</compile.class.target>
<compile.testclass.source>1.6</compile.testclass.source>
<compile.testclass.target>1.6</compile.testclass.target>
<compile.class.source>${java.class.version}</compile.class.source>
<compile.class.target>${java.class.version}</compile.class.target>
<compile.testclass.source>${java.testclass.version}</compile.testclass.source>
<compile.testclass.target>${java.testclass.version}</compile.testclass.target>
</properties>
<licenses>