Author: mprudhom
Date: Fri Sep 29 19:00:40 2006
New Revision: 451517
URL: http://svn.apache.org/viewvc?view=rev&rev=451517
Log:
Prevent reentrant calls to transform() in order to prevent attempts to enhance
OpenJPA libraries (for cases where OpenJPA falls under the control of the
enhancing class loader).
Modified:
incubator/openjpa/trunk/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java
Modified:
incubator/openjpa/trunk/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java?view=diff&rev=451517&r1=451516&r2=451517
==============================================================================
---
incubator/openjpa/trunk/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java
(original)
+++
incubator/openjpa/trunk/openjpa-kernel-5/src/main/java/org/apache/openjpa/enhance/PCClassFileTransformer.java
Fri Sep 29 19:00:40 2006
@@ -26,6 +26,7 @@
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 @@
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 @@
* 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);
+ _tmpLoader = tmpLoader;
+
+ // 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;
- _loader = loader;
- _names = repos.getPersistentTypeNames(devscan, loader);
+ _names = repos.getPersistentTypeNames(devscan, tmpLoader);
if (_names == null && _log.isInfoEnabled())
_log.info(_loc.get("runtime-enhance-pcclasses"));
}
@@ -101,9 +112,18 @@
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 @@
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 @@
if (t instanceof IllegalClassFormatException)
throw (IllegalClassFormatException) t;
throw new GeneralException(t);
+ } finally {
+ _transforming = false;
}
}
@@ -157,7 +179,8 @@
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;