mirror of
https://github.com/apache/openjpa.git
synced 2025-03-06 08:29:08 +00:00
OPENJPA-2911 Bridge from BCClass <-> ASM ClassNode
This will allow us to smoothly migrate from Serp to ASM
This commit is contained in:
parent
d13b85b139
commit
032c6fc7fe
@ -142,9 +142,9 @@ public final class SQLBuffer
|
||||
|
||||
if (!paramOnly) {
|
||||
if (sqlIndex == _sql.length())
|
||||
_sql.append(buf._sql.toString());
|
||||
_sql.append(buf._sql);
|
||||
else
|
||||
_sql.insert(sqlIndex, buf._sql.toString());
|
||||
_sql.insert(sqlIndex, buf._sql);
|
||||
}
|
||||
|
||||
if (buf._params != null) {
|
||||
@ -326,7 +326,7 @@ public final class SQLBuffer
|
||||
if (o == null)
|
||||
_sql.append("NULL");
|
||||
else if (o instanceof Raw)
|
||||
_sql.append(o.toString());
|
||||
_sql.append(o);
|
||||
else {
|
||||
Class<?> type = Filters.wrap(o.getClass());
|
||||
if (useParamToken || !validParamLiteralType(type)) {
|
||||
@ -366,7 +366,7 @@ public final class SQLBuffer
|
||||
|
||||
} else if ( type == Character.class ) {
|
||||
if (_dict.storeCharsAsNumbers) {
|
||||
_sql.append(Integer.toString((Character) o));
|
||||
_sql.append(o);
|
||||
} else {
|
||||
_sql.append("'" + o.toString().replace("'", "''") + "'");
|
||||
}
|
||||
@ -375,7 +375,7 @@ public final class SQLBuffer
|
||||
// We store B(b)ooleans as ints. Convert
|
||||
_sql.append(_dict.getBooleanRepresentation().getRepresentation(b));
|
||||
} else {
|
||||
_sql.append(o.toString());
|
||||
_sql.append(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,12 +96,15 @@ 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.ClassNodeTracker;
|
||||
import org.apache.openjpa.util.asm.ClassWriterTracker;
|
||||
import org.apache.xbean.asm9.Opcodes;
|
||||
import org.apache.xbean.asm9.Type;
|
||||
import org.apache.xbean.asm9.tree.AbstractInsnNode;
|
||||
import org.apache.xbean.asm9.tree.ClassNode;
|
||||
import org.apache.xbean.asm9.tree.FieldInsnNode;
|
||||
import org.apache.xbean.asm9.tree.InsnNode;
|
||||
import org.apache.xbean.asm9.tree.LdcInsnNode;
|
||||
import org.apache.xbean.asm9.tree.MethodNode;
|
||||
import org.apache.xbean.asm9.tree.VarInsnNode;
|
||||
|
||||
@ -289,8 +292,7 @@ public class PCEnhancer {
|
||||
* @param loader the environment classloader to use for loading
|
||||
* classes and resources.
|
||||
*/
|
||||
public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
|
||||
MetaDataRepository repos, ClassLoader loader) {
|
||||
public PCEnhancer(OpenJPAConfiguration conf, BCClass type, MetaDataRepository repos, ClassLoader loader) {
|
||||
_managedType = type;
|
||||
_pc = type;
|
||||
|
||||
@ -326,8 +328,7 @@ public class PCEnhancer {
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public PCEnhancer(MetaDataRepository repos, BCClass type,
|
||||
ClassMetaData meta) {
|
||||
public PCEnhancer(MetaDataRepository repos, BCClass type, ClassMetaData meta) {
|
||||
_managedType = type;
|
||||
_pc = type;
|
||||
|
||||
@ -373,14 +374,6 @@ public class PCEnhancer {
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Supply configuration, type, and metadata.
|
||||
*/
|
||||
public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
|
||||
ClassMetaData meta) {
|
||||
this(conf, type, meta.getRepository());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bytecode representation of the persistence-capable class
|
||||
* being manipulated.
|
||||
@ -3076,10 +3069,17 @@ public class PCEnhancer {
|
||||
*/
|
||||
private void enhanceClass() {
|
||||
// make the class implement PersistenceCapable
|
||||
_pc.declareInterface(PCTYPE);
|
||||
//_pc.declareInterface(PCTYPE);
|
||||
|
||||
final ClassNodeTracker classNodeTracker = AsmHelper.toClassNode(_pc);
|
||||
|
||||
// make the class implement PersistenceCapable
|
||||
classNodeTracker.getClassNode().interfaces.add(Type.getInternalName(PCTYPE));
|
||||
|
||||
// add a version stamp
|
||||
addGetEnhancementContractVersionMethod();
|
||||
addGetEnhancementContractVersionMethod(classNodeTracker);
|
||||
|
||||
AsmHelper.readIntoBCClass(classNodeTracker, _pc);
|
||||
|
||||
// find the default constructor
|
||||
BCMethod method = _pc.getDeclaredMethod("<init>", (String[]) null);
|
||||
@ -4893,6 +4893,17 @@ public class PCEnhancer {
|
||||
return setter;
|
||||
}
|
||||
|
||||
private void addGetEnhancementContractVersionMethod(ClassNodeTracker cnt) {
|
||||
MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC,
|
||||
PRE + "GetEnhancementContractVersion",
|
||||
Type.getMethodDescriptor(Type.INT_TYPE),
|
||||
null, null);
|
||||
methodNode.instructions.add(new LdcInsnNode(ENHANCER_VERSION));
|
||||
methodNode.instructions.add(new InsnNode(Opcodes.IRETURN));
|
||||
cnt.getClassNode().methods.add(methodNode);
|
||||
}
|
||||
|
||||
@Deprecated //X TODO REMOVE
|
||||
private void addGetEnhancementContractVersionMethod() {
|
||||
// public int getEnhancementContractVersion()
|
||||
BCMethod method = _pc.declareMethod(PRE +
|
||||
|
@ -124,7 +124,7 @@ class InterfaceImplGenerator {
|
||||
iface)).setFatal(true);
|
||||
try {
|
||||
// load the Class<?> for real.
|
||||
impl = Class.forName(bc.getName(), true, enhLoader);
|
||||
impl = Class.forName(enhancer.getPCBytecode().getName(), true, enhLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new InternalException(_loc.get("interface-load2", iface,
|
||||
enhLoader), t).setFatal(true);
|
||||
|
@ -19,6 +19,7 @@ package org.apache.openjpa.util.asm;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.xbean.asm9.ClassReader;
|
||||
@ -78,7 +79,7 @@ public final class AsmHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* temporary helper class to convert BCClass to ASM
|
||||
* temporary helper class to convert BCClass to ASM ClassWriter
|
||||
* @deprecated must get removed when done with migrating from Serp to ASM
|
||||
*/
|
||||
public static ClassWriterTracker toClassWriter(BCClass bcClass) {
|
||||
@ -102,6 +103,40 @@ public final class AsmHelper {
|
||||
return bcClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* temporary helper class to convert BCClass to ASM ClassNode
|
||||
* @deprecated must get removed when done with migrating from Serp to ASM
|
||||
*/
|
||||
public static ClassNodeTracker toClassNode(BCClass bcClass) {
|
||||
ClassReader cr = new ClassReader(bcClass.toByteArray());
|
||||
ClassNode classNode = new ClassNode(Opcodes.ASM9);
|
||||
cr.accept(classNode, 0);
|
||||
|
||||
return new ClassNodeTracker(classNode, bcClass.getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the changes from ClassNodeTracker and read it into the given BCClass instance.
|
||||
* Effectively replace all the content of BCClass with the content from our ClassNode
|
||||
*/
|
||||
public static void readIntoBCClass(ClassNodeTracker cnt, BCClass bcClass) {
|
||||
|
||||
// sadly package scoped
|
||||
try {
|
||||
Method readMethod = BCClass.class.getDeclaredMethod("read", InputStream.class, ClassLoader.class);
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
cnt.getClassNode().accept(cw);
|
||||
final byte[] classBytes = cw.toByteArray();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(classBytes);
|
||||
|
||||
readMethod.setAccessible(true);
|
||||
readMethod.invoke(bcClass, bais, bcClass.getClassLoader());
|
||||
}
|
||||
catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calclates the proper Return instruction opcode for the given class
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.openjpa.util.asm;
|
||||
|
||||
import org.apache.xbean.asm9.tree.ClassNode;
|
||||
|
||||
/**
|
||||
* Helper class to transit from BCClass to ASM
|
||||
*
|
||||
* @author <a href="mailto:struberg@apache.org">Mark Struberg</a>
|
||||
*/
|
||||
public class ClassNodeTracker {
|
||||
private final ClassNode classNode;
|
||||
private final ClassLoader cl;
|
||||
|
||||
public ClassNodeTracker(ClassNode classNode, ClassLoader cl) {
|
||||
this.classNode = classNode;
|
||||
this.cl = cl;
|
||||
}
|
||||
|
||||
public ClassNode getClassNode() {
|
||||
return classNode;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return cl;
|
||||
}
|
||||
}
|
@ -56,7 +56,8 @@ public class TestEnhancementWithMultiplePUs
|
||||
PCEnhancer enhancer = new PCEnhancer(conf, bc, repos, loader);
|
||||
|
||||
assertEquals(PCEnhancer.ENHANCE_PC, enhancer.run());
|
||||
assertTrue(Arrays.asList(bc.getInterfaceNames()).contains(
|
||||
|
||||
assertTrue(Arrays.asList(enhancer.getPCBytecode().getInterfaceNames()).contains(
|
||||
PersistenceCapable.class.getName()));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user