mirror of
https://github.com/apache/openjpa.git
synced 2025-02-20 17:05:15 +00:00
OPENJPA-1993: Deadlock Potential with XML ORM Processing
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1100363 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c00af8d5e8
commit
6fc7d55a09
@ -67,6 +67,7 @@ public class Compatibility {
|
||||
private boolean _reloadOnDetach = false;
|
||||
private boolean _ignoreDetachedStateFieldForProxySerialization = false;
|
||||
private boolean _checkDatabaseForCascadePersistToDetachedEntity = false;
|
||||
private boolean _overrideContextClassloader = true;
|
||||
|
||||
/**
|
||||
* Whether to require exact identity value types when creating object
|
||||
@ -558,4 +559,22 @@ public class Compatibility {
|
||||
public void setCheckDatabaseForCascadePersistToDetachedEntity(boolean b){
|
||||
_checkDatabaseForCascadePersistToDetachedEntity = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to temporally override the thread's Context Classloader when processing
|
||||
* ORM XML documents to avoid deadlock potential with certain Classloader hierarchy
|
||||
* configurations. Defaults to false.
|
||||
*/
|
||||
public boolean getOverrideContextClassloader() {
|
||||
return _overrideContextClassloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to temporally override the thread's Context Classloader when processing
|
||||
* ORM XML documents to avoid deadlock potential with certain Classloader hierarchy
|
||||
* configurations. Defaults to false.
|
||||
*/
|
||||
public void setOverrideContextClassloader(boolean overrideContextClassloader) {
|
||||
_overrideContextClassloader = overrideContextClassloader;
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +107,16 @@ public abstract class XMLMetaDataParser extends DefaultHandler
|
||||
private int _ignore = Integer.MAX_VALUE;
|
||||
|
||||
private boolean _parsing = false;
|
||||
|
||||
private boolean _overrideContextClassloader = false;
|
||||
|
||||
public boolean getOverrideContextClassloader() {
|
||||
return _overrideContextClassloader;
|
||||
}
|
||||
|
||||
public void setOverrideContextClassloader(boolean overrideCCL) {
|
||||
_overrideContextClassloader = overrideCCL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Whether the parser is currently parsing.
|
||||
@ -366,36 +376,60 @@ public abstract class XMLMetaDataParser extends DefaultHandler
|
||||
try {
|
||||
setParsing(true);
|
||||
_sourceName = sourceName;
|
||||
SAXParser parser = XMLFactory.getSAXParser(validating, true);
|
||||
Object schema = null;
|
||||
if (validating) {
|
||||
schema = schemaSource;
|
||||
if (schema == null && getDocType() != null)
|
||||
xml = new DocTypeReader(xml, getDocType());
|
||||
|
||||
SAXParser parser = null;
|
||||
ClassLoader oldLoader = null;
|
||||
|
||||
try {
|
||||
if (_overrideContextClassloader == true) {
|
||||
oldLoader = (ClassLoader) AccessController.doPrivileged(
|
||||
J2DoPrivHelper.getContextClassLoaderAction());
|
||||
AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(
|
||||
XMLMetaDataParser.class.getClassLoader()));
|
||||
}
|
||||
|
||||
parser = XMLFactory.getSAXParser(validating, true);
|
||||
Object schema = null;
|
||||
if (validating) {
|
||||
schema = schemaSource;
|
||||
if (schema == null && getDocType() != null)
|
||||
xml = new DocTypeReader(xml, getDocType());
|
||||
}
|
||||
|
||||
if (_parseComments || _lh != null)
|
||||
parser.setProperty
|
||||
("http://xml.org/sax/properties/lexical-handler", this);
|
||||
|
||||
if (schema != null) {
|
||||
parser.setProperty
|
||||
("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
|
||||
"http://www.w3.org/2001/XMLSchema");
|
||||
parser.setProperty
|
||||
("http://java.sun.com/xml/jaxp/properties/schemaSource",
|
||||
schema);
|
||||
}
|
||||
|
||||
InputSource is = new InputSource(xml);
|
||||
if (_systemId && sourceName != null)
|
||||
is.setSystemId(sourceName);
|
||||
parser.parse(is, this);
|
||||
finish();
|
||||
} catch (SAXException se) {
|
||||
IOException ioe = new IOException(se.toString());
|
||||
ioe.initCause(se);
|
||||
throw ioe;
|
||||
} finally {
|
||||
if (_overrideContextClassloader == true && oldLoader != null) {
|
||||
// Restore the old ContextClassloader
|
||||
try {
|
||||
AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(oldLoader));
|
||||
} catch (Throwable t) {
|
||||
if (_log != null && _log.isTraceEnabled()) {
|
||||
_log.trace(_loc.get("restore-contextclassloader-failed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_parseComments || _lh != null)
|
||||
parser.setProperty
|
||||
("http://xml.org/sax/properties/lexical-handler", this);
|
||||
|
||||
if (schema != null) {
|
||||
parser.setProperty
|
||||
("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
|
||||
"http://www.w3.org/2001/XMLSchema");
|
||||
parser.setProperty
|
||||
("http://java.sun.com/xml/jaxp/properties/schemaSource",
|
||||
schema);
|
||||
}
|
||||
|
||||
InputSource is = new InputSource(xml);
|
||||
if (_systemId && sourceName != null)
|
||||
is.setSystemId(sourceName);
|
||||
parser.parse(is, this);
|
||||
finish();
|
||||
} catch (SAXException se) {
|
||||
IOException ioe = new IOException(se.toString());
|
||||
ioe.initCause(se);
|
||||
throw ioe;
|
||||
} finally {
|
||||
reset();
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ cant-diff-elems: Unable to differentiate between given package and class \
|
||||
elements for class arg parsing. No element can be a complete prefix of \
|
||||
another.
|
||||
class-arg: Error extracting class information from "{0}".
|
||||
restore-contextclassloader-failed: An error occurred restoring the Thread's \
|
||||
context classloader.
|
||||
parse-error: An error was encountered while parsing element "{0}". Make sure \
|
||||
the metadata file is correctly formatted.
|
||||
no-file: No source file found for "{0}".
|
||||
|
@ -280,6 +280,14 @@ public class XMLPersistenceMetaDataParser
|
||||
if (repos != null
|
||||
&& (repos.getValidate() & MetaDataRepository.VALIDATE_RUNTIME) != 0)
|
||||
setParseComments(false);
|
||||
|
||||
if (repos != null) {
|
||||
// Determine if the Thread Context Classloader needs to be temporally overridden to the Classloader
|
||||
// that loaded the OpenJPA classes, to avoid a potential deadlock issue with the way Xerces
|
||||
// handles parsers and classloaders.
|
||||
this.setOverrideContextClassloader(repos.getConfiguration().getCompatibilityInstance().
|
||||
getOverrideContextClassloader());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user