diff --git a/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java b/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java index 1153ab869..642a4920e 100644 --- a/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java +++ b/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java @@ -26,6 +26,7 @@ import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Options; import org.apache.openjpa.meta.MetaDataRepository; +import org.apache.openjpa.util.ClassResolver; import org.apache.openjpa.util.GeneralException; import serp.bytecode.Project; import serp.bytecode.lowlevel.ConstantPoolTable; @@ -43,9 +44,10 @@ public class PCClassFileTransformer private static final Localizer _loc = Localizer.forPackage (PCClassFileTransformer.class); + private boolean _transforming = false; private final MetaDataRepository _repos; private final PCEnhancer.Flags _flags; - private final ClassLoader _loader; + private final ClassLoader _tmpLoader; private final Log _log; private final Set _names; @@ -86,14 +88,23 @@ public class PCClassFileTransformer * if none are configured */ public PCClassFileTransformer(MetaDataRepository repos, - PCEnhancer.Flags flags, ClassLoader loader, boolean devscan) { + PCEnhancer.Flags flags, ClassLoader tmpLoader, boolean devscan) { _repos = repos; - _log = - repos.getConfiguration().getLog(OpenJPAConfiguration.LOG_ENHANCE); - _flags = flags; - _loader = loader; + _tmpLoader = tmpLoader; - _names = repos.getPersistentTypeNames(devscan, loader); + // ensure that we are using the temporary class loader for + // all class resolution + repos.getConfiguration().setClassResolver(new ClassResolver() { + public ClassLoader getClassLoader(Class context, ClassLoader env) { + return _tmpLoader; + } + }); + + _log = repos.getConfiguration(). + getLog(OpenJPAConfiguration.LOG_ENHANCE); + _flags = flags; + + _names = repos.getPersistentTypeNames(devscan, tmpLoader); if (_names == null && _log.isInfoEnabled()) _log.info(_loc.get("runtime-enhance-pcclasses")); } @@ -101,9 +112,18 @@ public class PCClassFileTransformer public byte[] transform(ClassLoader loader, String className, Class redef, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException { - if (loader == _loader) + + if (loader == _tmpLoader) return null; + // prevent re-entrant calls, which can occur if the enhanceing + // loader is used to also load OpenJPA libraries; this is to prevent + // recursive enhancement attempts for internal openjpa libraries + if (_transforming) + return null; + + _transforming = true; + try { Boolean enhance = needsEnhance(className, redef, bytes); if (enhance != null && _log.isTraceEnabled()) @@ -114,7 +134,7 @@ public class PCClassFileTransformer PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(), new Project().loadClass(new ByteArrayInputStream(bytes), - _loader), _repos); + _tmpLoader), _repos); enhancer.setAddDefaultConstructor(_flags.addDefaultConstructor); enhancer.setEnforcePropertyRestrictions (_flags.enforcePropertyRestrictions); @@ -129,6 +149,8 @@ public class PCClassFileTransformer if (t instanceof IllegalClassFormatException) throw (IllegalClassFormatException) t; throw new GeneralException(t); + } finally { + _transforming = false; } } @@ -157,7 +179,8 @@ public class PCClassFileTransformer return Boolean.FALSE; try { - Class c = Class.forName(clsName.replace('/', '.'), false, _loader); + Class c = Class.forName(clsName.replace('/', '.'), false, + _tmpLoader); if (_repos.getMetaData(c, null, false) != null) return Boolean.TRUE; return null;