Author: jgrassel
Date: Fri May 6 20:22:23 2011
New Revision: 1100363
URL: http://svn.apache.org/viewvc?rev=1100363&view=rev
Log:
OPENJPA-1993: Deadlock Potential with XML ORM Processing
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
openjpa/trunk/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java?rev=1100363&r1=1100362&r2=1100363&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
Fri May 6 20:22:23 2011
@@ -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;
+ }
}
Modified:
openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java?rev=1100363&r1=1100362&r2=1100363&view=diff
==============================================================================
---
openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
(original)
+++
openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
Fri May 6 20:22:23 2011
@@ -107,6 +107,16 @@ public abstract class XMLMetaDataParser
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
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);
- }
+ 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;
+ 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"));
+ }
+ }
+ }
+ }
} finally {
reset();
}
Modified:
openjpa/trunk/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties?rev=1100363&r1=1100362&r2=1100363&view=diff
==============================================================================
---
openjpa/trunk/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
(original)
+++
openjpa/trunk/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
Fri May 6 20:22:23 2011
@@ -25,6 +25,8 @@ cant-diff-elems: Unable to differentiate
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}".
Modified:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java?rev=1100363&r1=1100362&r2=1100363&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
(original)
+++
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
Fri May 6 20:22:23 2011
@@ -280,6 +280,14 @@ public class XMLPersistenceMetaDataParse
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());
+ }
}
/**