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).

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@451517 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Marc Prud'hommeaux 2006-09-30 02:00:40 +00:00
parent cc25d2a536
commit f74ac8b6b9
1 changed files with 33 additions and 10 deletions

View File

@ -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;