mirror of https://github.com/apache/openjpa.git
OPENJPA-2911 move PCEnhancer off Serp
This commit is contained in:
parent
dfaf8da48e
commit
0a81c3de7b
|
@ -29,6 +29,7 @@ import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
import org.apache.openjpa.persistence.PersistenceMetaDataFactory;
|
import org.apache.openjpa.persistence.PersistenceMetaDataFactory;
|
||||||
import org.apache.openjpa.util.asm.AsmHelper;
|
import org.apache.openjpa.util.asm.AsmHelper;
|
||||||
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
||||||
|
import org.apache.openjpa.util.asm.EnhancementProject;
|
||||||
import org.apache.xbean.asm9.AnnotationVisitor;
|
import org.apache.xbean.asm9.AnnotationVisitor;
|
||||||
import org.apache.xbean.asm9.ClassReader;
|
import org.apache.xbean.asm9.ClassReader;
|
||||||
import org.apache.xbean.asm9.Type;
|
import org.apache.xbean.asm9.Type;
|
||||||
|
@ -265,18 +266,16 @@ public class OpenJPADirectoriesEnhancer implements Runnable {
|
||||||
final Thread thread = Thread.currentThread();
|
final Thread thread = Thread.currentThread();
|
||||||
final ClassLoader old = thread.getContextClassLoader();
|
final ClassLoader old = thread.getContextClassLoader();
|
||||||
thread.setContextClassLoader(tmpLoader);
|
thread.setContextClassLoader(tmpLoader);
|
||||||
try (final InputStream stream = new ByteArrayInputStream(classBytes)) {
|
try {
|
||||||
final PCEnhancer enhancer = new PCEnhancer(
|
final PCEnhancer enhancer = new PCEnhancer(
|
||||||
repos.getConfiguration(),
|
repos.getConfiguration(),
|
||||||
new Project().loadClass(stream, tmpLoader),
|
new EnhancementProject().loadClass(classBytes, tmpLoader),
|
||||||
repos, tmpLoader);
|
repos, tmpLoader);
|
||||||
if (enhancer.run() == PCEnhancer.ENHANCE_NONE) {
|
if (enhancer.run() == PCEnhancer.ENHANCE_NONE) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final ClassNodeTracker cnt = enhancer.getPCBytecode();
|
final ClassNodeTracker cnt = enhancer.getPCBytecode();
|
||||||
return AsmHelper.toByteArray(cnt);
|
return AsmHelper.toByteArray(cnt);
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
} finally {
|
} finally {
|
||||||
thread.setContextClassLoader(old);
|
thread.setContextClassLoader(old);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.enhance;
|
package org.apache.openjpa.enhance;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.IllegalClassFormatException;
|
import java.lang.instrument.IllegalClassFormatException;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
|
@ -34,11 +33,11 @@ import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
import org.apache.openjpa.util.GeneralException;
|
import org.apache.openjpa.util.GeneralException;
|
||||||
import org.apache.openjpa.util.asm.AsmHelper;
|
import org.apache.openjpa.util.asm.AsmHelper;
|
||||||
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
||||||
|
import org.apache.openjpa.util.asm.EnhancementProject;
|
||||||
import org.apache.xbean.asm9.ClassReader;
|
import org.apache.xbean.asm9.ClassReader;
|
||||||
import org.apache.xbean.asm9.ClassVisitor;
|
import org.apache.xbean.asm9.ClassVisitor;
|
||||||
import org.apache.xbean.asm9.Opcodes;
|
import org.apache.xbean.asm9.Opcodes;
|
||||||
|
|
||||||
import serp.bytecode.Project;
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,9 +148,9 @@ public class PCClassFileTransformer
|
||||||
ClassLoader oldLoader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
|
ClassLoader oldLoader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
|
||||||
AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(_tmpLoader));
|
AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(_tmpLoader));
|
||||||
try {
|
try {
|
||||||
PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(),
|
EnhancementProject project = new EnhancementProject();
|
||||||
new Project().loadClass(new ByteArrayInputStream(bytes),
|
final ClassNodeTracker bc = project.loadClass(bytes, _tmpLoader);
|
||||||
_tmpLoader), _repos);
|
PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(), bc, _repos);
|
||||||
enhancer.setAddDefaultConstructor(_flags.addDefaultConstructor);
|
enhancer.setAddDefaultConstructor(_flags.addDefaultConstructor);
|
||||||
enhancer.setEnforcePropertyRestrictions
|
enhancer.setEnforcePropertyRestrictions
|
||||||
(_flags.enforcePropertyRestrictions);
|
(_flags.enforcePropertyRestrictions);
|
||||||
|
|
|
@ -100,14 +100,13 @@ import org.apache.openjpa.util.StringId;
|
||||||
import org.apache.openjpa.util.UserException;
|
import org.apache.openjpa.util.UserException;
|
||||||
import org.apache.openjpa.util.asm.AsmHelper;
|
import org.apache.openjpa.util.asm.AsmHelper;
|
||||||
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
||||||
|
import org.apache.openjpa.util.asm.EnhancementProject;
|
||||||
import org.apache.openjpa.util.asm.RedefinedAttribute;
|
import org.apache.openjpa.util.asm.RedefinedAttribute;
|
||||||
import org.apache.xbean.asm9.Attribute;
|
import org.apache.xbean.asm9.Attribute;
|
||||||
import org.apache.xbean.asm9.Opcodes;
|
import org.apache.xbean.asm9.Opcodes;
|
||||||
import org.apache.xbean.asm9.Type;
|
import org.apache.xbean.asm9.Type;
|
||||||
import org.apache.xbean.asm9.tree.*;
|
import org.apache.xbean.asm9.tree.*;
|
||||||
|
|
||||||
import serp.bytecode.BCClass;
|
|
||||||
import serp.bytecode.Project;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bytecode enhancer used to enhance persistent classes from metadata. The
|
* Bytecode enhancer used to enhance persistent classes from metadata. The
|
||||||
|
@ -193,12 +192,15 @@ public class PCEnhancer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BCClass _pc;
|
|
||||||
private final BCClass _managedType;
|
|
||||||
private final MetaDataRepository _repos;
|
private final MetaDataRepository _repos;
|
||||||
|
private final ClassMetaData _meta;
|
||||||
|
private final Log _log;
|
||||||
|
|
||||||
boolean _addVersionInitFlag = true;
|
boolean _addVersionInitFlag = true;
|
||||||
|
|
||||||
|
|
||||||
|
private final EnhancementProject project;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* represents the managed type.
|
* represents the managed type.
|
||||||
*/
|
*/
|
||||||
|
@ -211,8 +213,6 @@ public class PCEnhancer {
|
||||||
*/
|
*/
|
||||||
private ClassNodeTracker pc;
|
private ClassNodeTracker pc;
|
||||||
|
|
||||||
private final ClassMetaData _meta;
|
|
||||||
private final Log _log;
|
|
||||||
private boolean _defCons = true;
|
private boolean _defCons = true;
|
||||||
private boolean _redefine = false;
|
private boolean _redefine = false;
|
||||||
private boolean _subclass = false;
|
private boolean _subclass = false;
|
||||||
|
@ -235,8 +235,7 @@ public class PCEnhancer {
|
||||||
* repository.
|
* repository.
|
||||||
*/
|
*/
|
||||||
public PCEnhancer(OpenJPAConfiguration conf, Class<?> type) {
|
public PCEnhancer(OpenJPAConfiguration conf, Class<?> type) {
|
||||||
this(conf, AccessController.doPrivileged(SerpPrivacyHelper.loadProjectClassAction(new Project(), type)),
|
this(conf, new EnhancementProject().loadClass(type), (MetaDataRepository) null);
|
||||||
(MetaDataRepository) null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,8 +244,7 @@ public class PCEnhancer {
|
||||||
* and then loading from <code>conf</code>'s repository.
|
* and then loading from <code>conf</code>'s repository.
|
||||||
*/
|
*/
|
||||||
public PCEnhancer(OpenJPAConfiguration conf, ClassMetaData meta) {
|
public PCEnhancer(OpenJPAConfiguration conf, ClassMetaData meta) {
|
||||||
this(conf, AccessController.doPrivileged(SerpPrivacyHelper.loadProjectClassAction(new Project(), meta.getDescribedType())),
|
this(conf, new EnhancementProject().loadClass(meta.getDescribedType()), meta.getRepository());
|
||||||
meta.getRepository());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,12 +258,11 @@ public class PCEnhancer {
|
||||||
* because the configuration might be an
|
* because the configuration might be an
|
||||||
* implementation-specific subclass whose metadata
|
* implementation-specific subclass whose metadata
|
||||||
* required more than just base metadata files
|
* required more than just base metadata files
|
||||||
* @deprecated use {@link #PCEnhancer(OpenJPAConfiguration, BCClass,
|
* @deprecated use {@link #PCEnhancer(OpenJPAConfiguration, ClassNodeTracker,
|
||||||
* MetaDataRepository, ClassLoader)} instead.
|
* MetaDataRepository, ClassLoader)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
|
public PCEnhancer(OpenJPAConfiguration conf, ClassNodeTracker type, MetaDataRepository repos) {
|
||||||
MetaDataRepository repos) {
|
|
||||||
this(conf, type, repos, null);
|
this(conf, type, repos, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,12 +280,11 @@ public class PCEnhancer {
|
||||||
* @param loader the environment classloader to use for loading
|
* @param loader the environment classloader to use for loading
|
||||||
* classes and resources.
|
* classes and resources.
|
||||||
*/
|
*/
|
||||||
public PCEnhancer(OpenJPAConfiguration conf, BCClass type, MetaDataRepository repos, ClassLoader loader) {
|
public PCEnhancer(OpenJPAConfiguration conf, ClassNodeTracker type, MetaDataRepository repos, ClassLoader loader) {
|
||||||
_managedType = type;
|
|
||||||
_pc = type;
|
|
||||||
|
|
||||||
// we assume that the original class and the enhanced class is the same
|
// we assume that the original class and the enhanced class is the same
|
||||||
managedType = AsmHelper.toClassNode(type);
|
project = type.getProject();
|
||||||
|
managedType = type;
|
||||||
pc = managedType;
|
pc = managedType;
|
||||||
|
|
||||||
_log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
|
_log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
|
||||||
|
@ -323,12 +319,10 @@ public class PCEnhancer {
|
||||||
* @param meta the metadata to use for processing this type.
|
* @param meta the metadata to use for processing this type.
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public PCEnhancer(MetaDataRepository repos, BCClass type, ClassMetaData meta) {
|
public PCEnhancer(MetaDataRepository repos, ClassNodeTracker type, ClassMetaData meta) {
|
||||||
_managedType = type;
|
|
||||||
_pc = type;
|
|
||||||
|
|
||||||
// we assume that the original class and the enhanced class is the same
|
// we assume that the original class and the enhanced class is the same
|
||||||
managedType = AsmHelper.toClassNode(type);
|
project = type.getProject();
|
||||||
|
managedType = type;
|
||||||
pc = managedType;
|
pc = managedType;
|
||||||
|
|
||||||
_log = repos.getConfiguration()
|
_log = repos.getConfiguration()
|
||||||
|
@ -597,7 +591,6 @@ public class PCEnhancer {
|
||||||
addCloningCode();
|
addCloningCode();
|
||||||
runAuxiliaryEnhancers();
|
runAuxiliaryEnhancers();
|
||||||
|
|
||||||
AsmHelper.readIntoBCClass(pc, _pc);
|
|
||||||
return ENHANCE_PC;
|
return ENHANCE_PC;
|
||||||
}
|
}
|
||||||
return ENHANCE_AWARE;
|
return ENHANCE_AWARE;
|
||||||
|
@ -631,19 +624,19 @@ public class PCEnhancer {
|
||||||
if (getCreateSubclass()) {
|
if (getCreateSubclass()) {
|
||||||
PCSubclassValidator val = new PCSubclassValidator(_meta, managedType.getClassNode(), _log, _fail);
|
PCSubclassValidator val = new PCSubclassValidator(_meta, managedType.getClassNode(), _log, _fail);
|
||||||
val.assertCanSubclass();
|
val.assertCanSubclass();
|
||||||
pc = AsmHelper.copyClassNode(managedType, toPCSubclassName(managedType));
|
pc = project.loadClass(toPCSubclassName(managedType));
|
||||||
_pc = _managedType.getProject().loadClass(toPCSubclassName(managedType));
|
if (pc.getClassNode().superName.equals("java/lang/Object")) {
|
||||||
_pc.setMajorVersion(_managedType.getMajorVersion());
|
// set the parent class
|
||||||
_pc.setMinorVersion(_managedType.getMinorVersion());
|
pc.getClassNode().superName = managedType.getClassNode().name;
|
||||||
if (_pc.getSuperclassBC() != _managedType) {
|
if ((managedType.getClassNode().access & Opcodes.ACC_ABSTRACT) > 0) {
|
||||||
_pc.setSuperclass(_managedType);
|
pc.getClassNode().access |= Opcodes.ACC_ABSTRACT;
|
||||||
_pc.setAbstract(_managedType.isAbstract());
|
}
|
||||||
_pc.declareInterface(DynamicPersistenceCapable.class);
|
|
||||||
|
pc.declareInterface(DynamicPersistenceCapable.class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_isAlreadySubclassed = true;
|
_isAlreadySubclassed = true;
|
||||||
}
|
}
|
||||||
pc = AsmHelper.toClassNode(_pc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_bcsConfigured = true;
|
_bcsConfigured = true;
|
||||||
|
@ -1408,7 +1401,7 @@ public class PCEnhancer {
|
||||||
classNode.methods.add(newInstance);
|
classNode.methods.add(newInstance);
|
||||||
final InsnList instructions = newInstance.instructions;
|
final InsnList instructions = newInstance.instructions;
|
||||||
|
|
||||||
if (_pc.isAbstract()) {
|
if ((pc.getClassNode().access & Opcodes.ACC_ABSTRACT) > 0) {
|
||||||
instructions.add(throwException(USEREXCEP));
|
instructions.add(throwException(USEREXCEP));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3317,7 +3310,7 @@ public class PCEnhancer {
|
||||||
accessMode = Opcodes.ACC_PUBLIC;
|
accessMode = Opcodes.ACC_PUBLIC;
|
||||||
access = "public";
|
access = "public";
|
||||||
}
|
}
|
||||||
else if (_pc.isFinal()) {
|
else if ((pc.getClassNode().access & Opcodes.ACC_FINAL) > 0) {
|
||||||
accessMode = Opcodes.ACC_PRIVATE;
|
accessMode = Opcodes.ACC_PRIVATE;
|
||||||
access = "private";
|
access = "private";
|
||||||
}
|
}
|
||||||
|
@ -3461,7 +3454,7 @@ public class PCEnhancer {
|
||||||
instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pc.isAbstract()) {
|
if ((pc.getClassNode().access & Opcodes.ACC_ABSTRACT) > 0) {
|
||||||
instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4716,7 +4709,7 @@ public class PCEnhancer {
|
||||||
|
|
||||||
// declare externalizable interface
|
// declare externalizable interface
|
||||||
if (!Externalizable.class.isAssignableFrom(_meta.getDescribedType())) {
|
if (!Externalizable.class.isAssignableFrom(_meta.getDescribedType())) {
|
||||||
pc.getClassNode().interfaces.add(Type.getInternalName(Externalizable.class));
|
pc.declareInterface(Externalizable.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the user doesn't already have custom externalization or
|
// make sure the user doesn't already have custom externalization or
|
||||||
|
@ -5602,8 +5595,8 @@ public class PCEnhancer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Project project = new Project();
|
EnhancementProject project = new EnhancementProject();
|
||||||
BCClass bc;
|
ClassNodeTracker cnt;
|
||||||
PCEnhancer enhancer;
|
PCEnhancer enhancer;
|
||||||
Collection persAwareClasses = new HashSet();
|
Collection persAwareClasses = new HashSet();
|
||||||
|
|
||||||
|
@ -5614,12 +5607,12 @@ public class PCEnhancer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o instanceof String) {
|
if (o instanceof String) {
|
||||||
bc = project.loadClass((String) o, loader);
|
cnt = project.loadClass((String) o, loader);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bc = project.loadClass((Class) o);
|
cnt = project.loadClass((Class) o);
|
||||||
}
|
}
|
||||||
enhancer = new PCEnhancer(conf, bc, repos, loader);
|
enhancer = new PCEnhancer(conf, cnt, repos, loader);
|
||||||
if (writer != null) {
|
if (writer != null) {
|
||||||
enhancer.setBytecodeWriter(writer);
|
enhancer.setBytecodeWriter(writer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,10 +248,10 @@ public class PCRegistry {
|
||||||
* Look up the metadata for a <code>PersistenceCapable</code> class.
|
* Look up the metadata for a <code>PersistenceCapable</code> class.
|
||||||
*/
|
*/
|
||||||
private static Meta getMeta(Class<?> pcClass) {
|
private static Meta getMeta(Class<?> pcClass) {
|
||||||
Meta ret = (Meta) _metas.get(pcClass);
|
Meta ret = _metas.get(pcClass);
|
||||||
if (ret == null)
|
if (ret == null) {
|
||||||
throw new IllegalStateException(_loc.get("no-meta", pcClass).
|
throw new IllegalStateException(_loc.get("no-meta", pcClass).getMessage());
|
||||||
getMessage());
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.meta;
|
package org.apache.openjpa.meta;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedActionException;
|
import java.security.PrivilegedActionException;
|
||||||
|
@ -28,14 +27,17 @@ import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
import org.apache.openjpa.enhance.PCEnhancer;
|
import org.apache.openjpa.enhance.PCEnhancer;
|
||||||
import org.apache.openjpa.enhance.SerpPrivacyHelper;
|
|
||||||
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
import org.apache.openjpa.lib.util.StringUtil;
|
import org.apache.openjpa.lib.util.StringUtil;
|
||||||
import org.apache.openjpa.util.InternalException;
|
import org.apache.openjpa.util.InternalException;
|
||||||
|
import org.apache.openjpa.util.asm.AsmHelper;
|
||||||
|
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
||||||
|
import org.apache.openjpa.util.asm.EnhancementClassLoader;
|
||||||
|
import org.apache.openjpa.util.asm.EnhancementProject;
|
||||||
|
import org.apache.xbean.asm9.Type;
|
||||||
|
|
||||||
import serp.bytecode.BCClass;
|
import serp.bytecode.BCClass;
|
||||||
import serp.bytecode.BCClassLoader;
|
|
||||||
import serp.bytecode.BCField;
|
import serp.bytecode.BCField;
|
||||||
import serp.bytecode.BCMethod;
|
import serp.bytecode.BCMethod;
|
||||||
import serp.bytecode.Code;
|
import serp.bytecode.Code;
|
||||||
|
@ -49,16 +51,13 @@ import serp.bytecode.Project;
|
||||||
* @author Steve Kim
|
* @author Steve Kim
|
||||||
*/
|
*/
|
||||||
class InterfaceImplGenerator {
|
class InterfaceImplGenerator {
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage(InterfaceImplGenerator.class);
|
||||||
(InterfaceImplGenerator.class);
|
|
||||||
private static final String POSTFIX = "openjpaimpl";
|
private static final String POSTFIX = "openjpaimpl";
|
||||||
|
|
||||||
private final MetaDataRepository _repos;
|
private final MetaDataRepository _repos;
|
||||||
private final Map<Class<?>,Class<?>> _impls = new WeakHashMap<>();
|
private final Map<Class<?>,Class<?>> _impls = new WeakHashMap<>();
|
||||||
private final Project _project = new Project();
|
private final EnhancementProject _project = new EnhancementProject();
|
||||||
|
|
||||||
// distinct project / loader for enhanced version of class
|
|
||||||
private final Project _enhProject = new Project();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Supply repository.
|
* Constructor. Supply repository.
|
||||||
|
@ -79,45 +78,46 @@ class InterfaceImplGenerator {
|
||||||
if (impl != null)
|
if (impl != null)
|
||||||
return impl;
|
return impl;
|
||||||
|
|
||||||
|
// distinct temp project / loader for enhancing
|
||||||
|
EnhancementProject _enhProject = new EnhancementProject();
|
||||||
|
|
||||||
ClassLoader parentLoader = AccessController.doPrivileged(
|
ClassLoader parentLoader = AccessController.doPrivileged(
|
||||||
J2DoPrivHelper.getClassLoaderAction(iface));
|
J2DoPrivHelper.getClassLoaderAction(iface));
|
||||||
BCClassLoader loader = AccessController
|
EnhancementClassLoader loader = new EnhancementClassLoader(_project, parentLoader);
|
||||||
.doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(_project,
|
EnhancementClassLoader enhLoader = new EnhancementClassLoader(_enhProject, parentLoader);
|
||||||
parentLoader));
|
ClassNodeTracker bc = _project.loadClass(getClassName(meta), loader);
|
||||||
BCClassLoader enhLoader = AccessController
|
|
||||||
.doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(_enhProject,
|
|
||||||
parentLoader));
|
|
||||||
BCClass bc = _project.loadClass(getClassName(meta));
|
|
||||||
bc.declareInterface(iface);
|
bc.declareInterface(iface);
|
||||||
ClassMetaData sup = meta.getPCSuperclassMetaData();
|
ClassMetaData sup = meta.getPCSuperclassMetaData();
|
||||||
if (sup != null) {
|
if (sup != null) {
|
||||||
bc.setSuperclass(sup.getInterfaceImpl());
|
bc.getClassNode().superName = Type.getInternalName(sup.getInterfaceImpl());
|
||||||
enhLoader = AccessController
|
//X enhLoader = new EnhancementClassLoader(_enhProject, sup.getInterfaceImpl().getClassLoader());
|
||||||
.doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(
|
|
||||||
_enhProject, AccessController
|
|
||||||
.doPrivileged(J2DoPrivHelper.getClassLoaderAction(sup
|
|
||||||
.getInterfaceImpl()))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldMetaData[] fields = meta.getDeclaredFields();
|
FieldMetaData[] fields = meta.getDeclaredFields();
|
||||||
Set<Method> methods = new HashSet<>();
|
Set<Method> methods = new HashSet<>();
|
||||||
|
|
||||||
|
//X TODO REMOVE
|
||||||
|
BCClass _bc = new Project().loadClass(getClassName(meta));
|
||||||
|
AsmHelper.readIntoBCClass(bc, _bc);
|
||||||
|
|
||||||
for (FieldMetaData field : fields) {
|
for (FieldMetaData field : fields) {
|
||||||
addField(bc, iface, field, methods);
|
addField(_bc, iface, field, methods);
|
||||||
}
|
}
|
||||||
invalidateNonBeanMethods(bc, iface, methods);
|
invalidateNonBeanMethods(_bc, iface, methods);
|
||||||
|
|
||||||
// first load the base Class<?> as the enhancer requires the class
|
// first load the base Class<?> as the enhancer requires the class
|
||||||
// to be available
|
// to be available
|
||||||
try {
|
try {
|
||||||
meta.setInterfaceImpl(Class.forName(bc.getName(), true, loader));
|
meta.setInterfaceImpl(Class.forName(_bc.getName(), true, loader));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new InternalException(_loc.get("interface-load", iface,
|
throw new InternalException(_loc.get("interface-load", iface,
|
||||||
loader), t).setFatal(true);
|
loader), t).setFatal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the BCClass<?> into the enhancer project.
|
// copy the BCClass<?> into the enhancer project.
|
||||||
bc = _enhProject.loadClass(new ByteArrayInputStream(bc.toByteArray()),
|
//X bc = _enhProject.loadClass(new ByteArrayInputStream(_bc.toByteArray()), loader);
|
||||||
loader);
|
ClassNodeTracker bcEnh = AsmHelper.toClassNode(_enhProject, _bc);
|
||||||
PCEnhancer enhancer = new PCEnhancer(_repos, bc, meta);
|
PCEnhancer enhancer = new PCEnhancer(_repos, bcEnh, meta);
|
||||||
|
|
||||||
int result = enhancer.run();
|
int result = enhancer.run();
|
||||||
if (result != PCEnhancer.ENHANCE_PC)
|
if (result != PCEnhancer.ENHANCE_PC)
|
||||||
|
@ -128,8 +128,8 @@ class InterfaceImplGenerator {
|
||||||
String pcClassName = enhancer.getPCBytecode().getClassNode().name.replace("/", ".");
|
String pcClassName = enhancer.getPCBytecode().getClassNode().name.replace("/", ".");
|
||||||
impl = Class.forName(pcClassName, true, enhLoader);
|
impl = Class.forName(pcClassName, true, enhLoader);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new InternalException(_loc.get("interface-load2", iface,
|
//X throw new InternalException(_loc.get("interface-load2", iface, enhLoader), t).setFatal(true);
|
||||||
enhLoader), t).setFatal(true);
|
throw new InternalException(_loc.get("interface-load2", iface, loader), t).setFatal(true);
|
||||||
}
|
}
|
||||||
// cache the generated impl.
|
// cache the generated impl.
|
||||||
_impls.put(iface, impl);
|
_impls.put(iface, impl);
|
||||||
|
|
|
@ -50,7 +50,7 @@ import serp.bytecode.Project;
|
||||||
*/
|
*/
|
||||||
public final class AsmHelper {
|
public final class AsmHelper {
|
||||||
private static final char[] PRIMITIVE_DESCRIPTORS = {'V','Z','C','B','S','I','F','J','D'};
|
private static final char[] PRIMITIVE_DESCRIPTORS = {'V','Z','C','B','S','I','F','J','D'};
|
||||||
private static final Attribute[] ATTRS = new Attribute[] {
|
public static final Attribute[] ATTRS = new Attribute[] {
|
||||||
new RedefinedAttribute()
|
new RedefinedAttribute()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,40 +79,20 @@ public final class AsmHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy the binary information from the ClassNodeTracker to a new one
|
|
||||||
* @param cntIn the original ASM class representation
|
|
||||||
* @param newClassName the class name of the new ClassNodeTracker
|
|
||||||
* @return a new ClassNodeTracker
|
|
||||||
*/
|
|
||||||
public static ClassNodeTracker copyClassNode(ClassNodeTracker cntIn, String newClassName) {
|
|
||||||
final byte[] classBytes = toByteArray(cntIn);
|
|
||||||
|
|
||||||
ClassReader cr = new ClassReader(classBytes);
|
|
||||||
ClassNode classNode = new ClassNode(Opcodes.ASM9);
|
|
||||||
cr.accept(classNode, ATTRS, 0);
|
|
||||||
|
|
||||||
if ((classNode.version & 0xffff) < 49) {
|
|
||||||
classNode.version = 49;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ClassNodeTracker(classNode, cntIn.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the binary bytecode from the class with the given name
|
* Read the binary bytecode from the class with the given name
|
||||||
* @param classLoader the ClassLoader to use
|
* @param classLoader the ClassLoader to use
|
||||||
* @param className the fully qualified class name to read. e.g. "org.mycorp.mypackage.MyEntity"
|
* @param className the fully qualified class name to read. e.g. "org.mycorp.mypackage.MyEntity"
|
||||||
* @return the ClassNode constructed from that class
|
* @return the ClassNode constructed from that class
|
||||||
*/
|
*/
|
||||||
public static ClassNode readClassNode(ClassLoader classLoader, String className) {
|
public static ClassNode readClassNode(ClassLoader classLoader, String className) throws ClassNotFoundException {
|
||||||
ClassReader cr;
|
ClassReader cr;
|
||||||
final String classResourceName = className.replace(".", "/") + ".class";
|
final String classResourceName = className.replace(".", "/") + ".class";
|
||||||
try (final InputStream classBytesStream = classLoader.getResourceAsStream(classResourceName)) {
|
try (final InputStream classBytesStream = classLoader.getResourceAsStream(classResourceName)) {
|
||||||
cr = new ClassReader(classBytesStream);
|
cr = new ClassReader(classBytesStream);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new ClassNotFoundException("Cannot read ClassNode for class " + className, e);
|
||||||
}
|
}
|
||||||
ClassNode classNode = new ClassNode();
|
ClassNode classNode = new ClassNode();
|
||||||
cr.accept(classNode, ATTRS, 0);
|
cr.accept(classNode, ATTRS, 0);
|
||||||
|
@ -184,7 +164,7 @@ public final class AsmHelper {
|
||||||
* temporary helper class to convert BCClass to ASM ClassNode
|
* temporary helper class to convert BCClass to ASM ClassNode
|
||||||
* @deprecated must get removed when done with migrating from Serp to ASM
|
* @deprecated must get removed when done with migrating from Serp to ASM
|
||||||
*/
|
*/
|
||||||
public static ClassNodeTracker toClassNode(BCClass bcClass) {
|
public static ClassNodeTracker toClassNode(EnhancementProject project, BCClass bcClass) {
|
||||||
ClassReader cr = new ClassReader(bcClass.toByteArray());
|
ClassReader cr = new ClassReader(bcClass.toByteArray());
|
||||||
ClassNode classNode = new ClassNode(Opcodes.ASM9);
|
ClassNode classNode = new ClassNode(Opcodes.ASM9);
|
||||||
cr.accept(classNode, ATTRS, 0);
|
cr.accept(classNode, ATTRS, 0);
|
||||||
|
@ -193,7 +173,8 @@ public final class AsmHelper {
|
||||||
classNode.version = 49;
|
classNode.version = 49;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ClassNodeTracker(classNode, bcClass.getClassLoader());
|
final ClassNodeTracker cnt = new ClassNodeTracker(project, classNode, bcClass.getClassLoader());
|
||||||
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.util.asm;
|
package org.apache.openjpa.util.asm;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.xbean.asm9.Type;
|
||||||
import org.apache.xbean.asm9.tree.ClassNode;
|
import org.apache.xbean.asm9.tree.ClassNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,11 +29,32 @@ import org.apache.xbean.asm9.tree.ClassNode;
|
||||||
public class ClassNodeTracker {
|
public class ClassNodeTracker {
|
||||||
private final ClassNode classNode;
|
private final ClassNode classNode;
|
||||||
private final ClassLoader cl;
|
private final ClassLoader cl;
|
||||||
|
private final EnhancementProject project;
|
||||||
|
|
||||||
public ClassNodeTracker(ClassNode classNode, ClassLoader cl) {
|
public ClassNodeTracker(EnhancementProject project, ClassNode classNode, ClassLoader cl) {
|
||||||
|
this.project = project;
|
||||||
this.classNode = classNode;
|
this.classNode = classNode;
|
||||||
|
if (hasEnhancementCl(cl)) {
|
||||||
this.cl = cl;
|
this.cl = cl;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this.cl = new EnhancementClassLoader(project, cl);
|
||||||
|
}
|
||||||
|
project.putClass(classNode.name.replace("/", "."), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasEnhancementCl(ClassLoader cl) {
|
||||||
|
boolean hasEhCl = false;
|
||||||
|
do {
|
||||||
|
if (cl instanceof EnhancementClassLoader) {
|
||||||
|
hasEhCl = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cl = cl.getParent();
|
||||||
|
} while (cl != null);
|
||||||
|
|
||||||
|
return hasEhCl;
|
||||||
|
}
|
||||||
|
|
||||||
public ClassNode getClassNode() {
|
public ClassNode getClassNode() {
|
||||||
return classNode;
|
return classNode;
|
||||||
|
@ -40,6 +64,10 @@ public class ClassNodeTracker {
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EnhancementProject getProject() {
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
public Class<?> getType() {
|
public Class<?> getType() {
|
||||||
try {
|
try {
|
||||||
return Class.forName(classNode.name.replace("/", "."), false, cl);
|
return Class.forName(classNode.name.replace("/", "."), false, cl);
|
||||||
|
@ -48,4 +76,11 @@ public class ClassNodeTracker {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void declareInterface(Class<?> iface) {
|
||||||
|
if (classNode.interfaces == null) {
|
||||||
|
classNode.interfaces = new ArrayList<>();
|
||||||
|
}
|
||||||
|
classNode.interfaces.add(Type.getInternalName(iface));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class EnhancementClassLoader extends ClassLoader {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnhancementClassLoader(ClassLoader parent, EnhancementProject project) {
|
public EnhancementClassLoader(EnhancementProject project, ClassLoader parent) {
|
||||||
super(parent);
|
super(parent);
|
||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,15 @@ public class EnhancementClassLoader extends ClassLoader {
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||||
|
return super.loadClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
|
return super.loadClass(name, resolve);
|
||||||
|
}
|
||||||
|
|
||||||
protected Class findClass(String name) throws ClassNotFoundException {
|
protected Class findClass(String name) throws ClassNotFoundException {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
|
|
|
@ -18,8 +18,9 @@ package org.apache.openjpa.util.asm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.apache.openjpa.util.asm.AsmHelper;
|
import org.apache.openjpa.lib.util.JavaVersions;
|
||||||
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
import org.apache.xbean.asm9.ClassReader;
|
||||||
|
import org.apache.xbean.asm9.Opcodes;
|
||||||
import org.apache.xbean.asm9.tree.ClassNode;
|
import org.apache.xbean.asm9.tree.ClassNode;
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,26 +31,36 @@ import org.apache.xbean.asm9.tree.ClassNode;
|
||||||
*/
|
*/
|
||||||
public class EnhancementProject {
|
public class EnhancementProject {
|
||||||
|
|
||||||
private HashMap<String, ClassNodeTracker> classNodTrackers = new HashMap<>();
|
private HashMap<String, ClassNodeTracker> classNodeTrackers = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the project already contains the given class.
|
* Return true if the project already contains the given class.
|
||||||
*/
|
*/
|
||||||
public boolean containsClass(String type) {
|
public boolean containsClass(String type) {
|
||||||
return classNodTrackers.containsKey(type);
|
return classNodeTrackers.containsKey(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a class with the given name.
|
* Load a class with the given name.
|
||||||
*
|
*
|
||||||
|
* @param name the fully qualified class name
|
||||||
* @see #loadClass(String,ClassLoader)
|
* @see #loadClass(String,ClassLoader)
|
||||||
*/
|
*/
|
||||||
public ClassNodeTracker loadClass(String name) {
|
public ClassNodeTracker loadClass(String name) {
|
||||||
return loadClass(name, null);
|
return loadClass(name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a class with the given type.
|
||||||
|
*
|
||||||
|
* @see #loadClass(String,ClassLoader)
|
||||||
|
*/
|
||||||
|
public ClassNodeTracker loadClass(Class<?> type) {
|
||||||
|
return loadClass(type.getName(), type.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the bytecode for the class with the given name.
|
* Load the bytecode for the class with the given name.
|
||||||
* If a {@link ClassNodeTracker} with the given name already exists in this project,
|
* If a {@link ClassNodeTracker} with the given name already exists in this project,
|
||||||
|
@ -66,7 +77,7 @@ public class EnhancementProject {
|
||||||
* @throws RuntimeException on parse error
|
* @throws RuntimeException on parse error
|
||||||
*/
|
*/
|
||||||
public ClassNodeTracker loadClass(String name, ClassLoader loader) {
|
public ClassNodeTracker loadClass(String name, ClassLoader loader) {
|
||||||
ClassNodeTracker cached = classNodTrackers.get(name);
|
ClassNodeTracker cached = classNodeTrackers.get(name);
|
||||||
if (cached != null) {
|
if (cached != null) {
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
@ -76,10 +87,54 @@ public class EnhancementProject {
|
||||||
loader = Thread.currentThread().getContextClassLoader();
|
loader = Thread.currentThread().getContextClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
final ClassNode classNode = AsmHelper.readClassNode(loader, name);
|
ClassNode classNode;
|
||||||
ClassNodeTracker cnt = new ClassNodeTracker(classNode, loader);
|
try {
|
||||||
classNodTrackers.put(name, cnt);
|
classNode = AsmHelper.readClassNode(loader, name);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e) {
|
||||||
|
// otherwise create a new ClassNode
|
||||||
|
classNode = new ClassNode(Opcodes.ASM9);
|
||||||
|
classNode.version = detectJavaBytecodeVersion();
|
||||||
|
classNode.name = name.replace(".", "/");
|
||||||
|
classNode.access = Opcodes.ACC_PUBLIC;
|
||||||
|
classNode.superName = "java/lang/Object";
|
||||||
|
}
|
||||||
|
ClassNodeTracker cnt = new ClassNodeTracker(this, classNode, loader);
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 49 Java 1.5
|
||||||
|
* 50 Java 1.6
|
||||||
|
* 51 Java 1.7
|
||||||
|
* 52 Java 1.8
|
||||||
|
* 53 Java9
|
||||||
|
* 54 Java10
|
||||||
|
* 55 Java11
|
||||||
|
* etc
|
||||||
|
*
|
||||||
|
* @return the bytecode version of the current VM
|
||||||
|
*/
|
||||||
|
private int detectJavaBytecodeVersion() {
|
||||||
|
return JavaVersions.VERSION + 44;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassNodeTracker loadClass(byte[] bytes, ClassLoader loader) {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassNode classNode = new ClassNode();
|
||||||
|
cr.accept(classNode, AsmHelper.ATTRS, 0);
|
||||||
|
ClassNodeTracker cnt = new ClassNodeTracker(this, classNode, loader);
|
||||||
|
String name = classNode.name.replace("/", ".");
|
||||||
|
classNodeTrackers.put(name, cnt);
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
classNodeTrackers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void putClass(String name, ClassNodeTracker cnt) {
|
||||||
|
classNodeTrackers.put(name, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,15 @@ public class JavaVersions {
|
||||||
else if ("1.8".equals(specVersion))
|
else if ("1.8".equals(specVersion))
|
||||||
VERSION = 8;
|
VERSION = 8;
|
||||||
else {
|
else {
|
||||||
VERSION = Integer.parseInt(specVersion);
|
int v;
|
||||||
|
try {
|
||||||
|
v = Integer.parseInt(specVersion);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException nfe) {
|
||||||
|
// default to Java 8
|
||||||
|
v = 8;
|
||||||
|
}
|
||||||
|
VERSION = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ package org.apache.openjpa.enhance;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||||
|
@ -33,26 +32,24 @@ import org.apache.openjpa.lib.util.Options;
|
||||||
import org.apache.openjpa.meta.MetaDataRepository;
|
import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
import org.apache.openjpa.persistence.test.AbstractCachedEMFTestCase;
|
import org.apache.openjpa.persistence.test.AbstractCachedEMFTestCase;
|
||||||
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
import org.apache.openjpa.util.asm.ClassNodeTracker;
|
||||||
|
import org.apache.openjpa.util.asm.EnhancementProject;
|
||||||
import org.apache.xbean.asm9.Type;
|
import org.apache.xbean.asm9.Type;
|
||||||
|
|
||||||
import serp.bytecode.BCClass;
|
|
||||||
import serp.bytecode.Project;
|
|
||||||
|
|
||||||
public class TestEnhancementWithMultiplePUs
|
public class TestEnhancementWithMultiplePUs
|
||||||
extends AbstractCachedEMFTestCase {
|
extends AbstractCachedEMFTestCase {
|
||||||
|
|
||||||
public void testExplicitEnhancementWithClassNotInFirstPU()
|
public void testExplicitEnhancementWithClassNotInFirstPU() throws ClassNotFoundException {
|
||||||
throws ClassNotFoundException {
|
|
||||||
OpenJPAConfiguration conf = new OpenJPAConfigurationImpl();
|
OpenJPAConfiguration conf = new OpenJPAConfigurationImpl();
|
||||||
Configurations.populateConfiguration(conf, new Options());
|
Configurations.populateConfiguration(conf, new Options());
|
||||||
MetaDataRepository repos = conf.getMetaDataRepositoryInstance();
|
MetaDataRepository repos = conf.getMetaDataRepositoryInstance();
|
||||||
ClassLoader loader = AccessController
|
ClassLoader loader = AccessController
|
||||||
.doPrivileged(J2DoPrivHelper.newTemporaryClassLoaderAction(
|
.doPrivileged(J2DoPrivHelper.newTemporaryClassLoaderAction(
|
||||||
getClass().getClassLoader()));
|
getClass().getClassLoader()));
|
||||||
Project project = new Project();
|
EnhancementProject project = new EnhancementProject();
|
||||||
|
|
||||||
String className = "org.apache.openjpa.enhance.UnenhancedBootstrapInstance";
|
String className = "org.apache.openjpa.enhance.UnenhancedBootstrapInstance";
|
||||||
BCClass bc = assertNotPC(loader, project, className);
|
ClassNodeTracker bc = assertNotPC(loader, project, className);
|
||||||
|
|
||||||
PCEnhancer enhancer = new PCEnhancer(conf, bc, repos, loader);
|
PCEnhancer enhancer = new PCEnhancer(conf, bc, repos, loader);
|
||||||
|
|
||||||
|
@ -61,11 +58,10 @@ public class TestEnhancementWithMultiplePUs
|
||||||
assertTrue(enhancer.getPCBytecode().getClassNode().interfaces.contains(Type.getInternalName(PersistenceCapable.class)));
|
assertTrue(enhancer.getPCBytecode().getClassNode().interfaces.contains(Type.getInternalName(PersistenceCapable.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BCClass assertNotPC(ClassLoader loader, Project project, String className) {
|
private ClassNodeTracker assertNotPC(ClassLoader loader, EnhancementProject project, String className) {
|
||||||
BCClass bc = project.loadClass(className, loader);
|
ClassNodeTracker bc = project.loadClass(className, loader);
|
||||||
assertFalse(className + " must not be enhanced already; it was.",
|
assertTrue(className + " must not be enhanced already; it was.",
|
||||||
Arrays.asList(bc.getInterfaceNames()).contains(
|
bc.getClassNode().interfaces == null || !bc.getClassNode().interfaces.contains(Type.getInternalName(PersistenceCapable.class)));
|
||||||
PersistenceCapable.class.getName()));
|
|
||||||
return bc;
|
return bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +76,7 @@ public class TestEnhancementWithMultiplePUs
|
||||||
ClassLoader loader = AccessController
|
ClassLoader loader = AccessController
|
||||||
.doPrivileged(J2DoPrivHelper.newTemporaryClassLoaderAction(
|
.doPrivileged(J2DoPrivHelper.newTemporaryClassLoaderAction(
|
||||||
getClass().getClassLoader()));
|
getClass().getClassLoader()));
|
||||||
Project project = new Project();
|
EnhancementProject project = new EnhancementProject();
|
||||||
|
|
||||||
// make sure that the class is not already enhanced for some reason
|
// make sure that the class is not already enhanced for some reason
|
||||||
String className = "org/apache/openjpa/enhance/UnenhancedBootstrapInstance";
|
String className = "org/apache/openjpa/enhance/UnenhancedBootstrapInstance";
|
||||||
|
@ -118,7 +114,7 @@ public class TestEnhancementWithMultiplePUs
|
||||||
ClassLoader loader = AccessController
|
ClassLoader loader = AccessController
|
||||||
.doPrivileged(J2DoPrivHelper.newTemporaryClassLoaderAction(
|
.doPrivileged(J2DoPrivHelper.newTemporaryClassLoaderAction(
|
||||||
getClass().getClassLoader()));
|
getClass().getClassLoader()));
|
||||||
Project project = new Project();
|
EnhancementProject project = new EnhancementProject();
|
||||||
|
|
||||||
// make sure that the classes is not already enhanced for some reason
|
// make sure that the classes is not already enhanced for some reason
|
||||||
assertNotPC(loader, project,
|
assertNotPC(loader, project,
|
||||||
|
|
Loading…
Reference in New Issue