mirror of https://github.com/apache/openjpa.git
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:
parent
cc25d2a536
commit
f74ac8b6b9
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue