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.Localizer;
|
||||||
import org.apache.openjpa.lib.util.Options;
|
import org.apache.openjpa.lib.util.Options;
|
||||||
import org.apache.openjpa.meta.MetaDataRepository;
|
import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
|
import org.apache.openjpa.util.ClassResolver;
|
||||||
import org.apache.openjpa.util.GeneralException;
|
import org.apache.openjpa.util.GeneralException;
|
||||||
import serp.bytecode.Project;
|
import serp.bytecode.Project;
|
||||||
import serp.bytecode.lowlevel.ConstantPoolTable;
|
import serp.bytecode.lowlevel.ConstantPoolTable;
|
||||||
|
@ -43,9 +44,10 @@ public class PCClassFileTransformer
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage
|
||||||
(PCClassFileTransformer.class);
|
(PCClassFileTransformer.class);
|
||||||
|
|
||||||
|
private boolean _transforming = false;
|
||||||
private final MetaDataRepository _repos;
|
private final MetaDataRepository _repos;
|
||||||
private final PCEnhancer.Flags _flags;
|
private final PCEnhancer.Flags _flags;
|
||||||
private final ClassLoader _loader;
|
private final ClassLoader _tmpLoader;
|
||||||
private final Log _log;
|
private final Log _log;
|
||||||
private final Set _names;
|
private final Set _names;
|
||||||
|
|
||||||
|
@ -86,14 +88,23 @@ public class PCClassFileTransformer
|
||||||
* if none are configured
|
* if none are configured
|
||||||
*/
|
*/
|
||||||
public PCClassFileTransformer(MetaDataRepository repos,
|
public PCClassFileTransformer(MetaDataRepository repos,
|
||||||
PCEnhancer.Flags flags, ClassLoader loader, boolean devscan) {
|
PCEnhancer.Flags flags, ClassLoader tmpLoader, boolean devscan) {
|
||||||
_repos = repos;
|
_repos = repos;
|
||||||
_log =
|
_tmpLoader = tmpLoader;
|
||||||
repos.getConfiguration().getLog(OpenJPAConfiguration.LOG_ENHANCE);
|
|
||||||
_flags = flags;
|
|
||||||
_loader = loader;
|
|
||||||
|
|
||||||
_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())
|
if (_names == null && _log.isInfoEnabled())
|
||||||
_log.info(_loc.get("runtime-enhance-pcclasses"));
|
_log.info(_loc.get("runtime-enhance-pcclasses"));
|
||||||
}
|
}
|
||||||
|
@ -101,9 +112,18 @@ public class PCClassFileTransformer
|
||||||
public byte[] transform(ClassLoader loader, String className,
|
public byte[] transform(ClassLoader loader, String className,
|
||||||
Class redef, ProtectionDomain domain, byte[] bytes)
|
Class redef, ProtectionDomain domain, byte[] bytes)
|
||||||
throws IllegalClassFormatException {
|
throws IllegalClassFormatException {
|
||||||
if (loader == _loader)
|
|
||||||
|
if (loader == _tmpLoader)
|
||||||
return null;
|
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 {
|
try {
|
||||||
Boolean enhance = needsEnhance(className, redef, bytes);
|
Boolean enhance = needsEnhance(className, redef, bytes);
|
||||||
if (enhance != null && _log.isTraceEnabled())
|
if (enhance != null && _log.isTraceEnabled())
|
||||||
|
@ -114,7 +134,7 @@ public class PCClassFileTransformer
|
||||||
|
|
||||||
PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(),
|
PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(),
|
||||||
new Project().loadClass(new ByteArrayInputStream(bytes),
|
new Project().loadClass(new ByteArrayInputStream(bytes),
|
||||||
_loader), _repos);
|
_tmpLoader), _repos);
|
||||||
enhancer.setAddDefaultConstructor(_flags.addDefaultConstructor);
|
enhancer.setAddDefaultConstructor(_flags.addDefaultConstructor);
|
||||||
enhancer.setEnforcePropertyRestrictions
|
enhancer.setEnforcePropertyRestrictions
|
||||||
(_flags.enforcePropertyRestrictions);
|
(_flags.enforcePropertyRestrictions);
|
||||||
|
@ -129,6 +149,8 @@ public class PCClassFileTransformer
|
||||||
if (t instanceof IllegalClassFormatException)
|
if (t instanceof IllegalClassFormatException)
|
||||||
throw (IllegalClassFormatException) t;
|
throw (IllegalClassFormatException) t;
|
||||||
throw new GeneralException(t);
|
throw new GeneralException(t);
|
||||||
|
} finally {
|
||||||
|
_transforming = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +179,8 @@ public class PCClassFileTransformer
|
||||||
return Boolean.FALSE;
|
return Boolean.FALSE;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class c = Class.forName(clsName.replace('/', '.'), false, _loader);
|
Class c = Class.forName(clsName.replace('/', '.'), false,
|
||||||
|
_tmpLoader);
|
||||||
if (_repos.getMetaData(c, null, false) != null)
|
if (_repos.getMetaData(c, null, false) != null)
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in New Issue