Author: jgrassel
Date: Wed May 4 22:33:24 2011
New Revision: 1099630
URL: http://svn.apache.org/viewvc?rev=1099630&view=rev
Log:
OPENJPA-1993: Deadlock Potential with XML ORM Processing
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
openjpa/branches/1.0.x/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java?rev=1099630&r1=1099629&r2=1099630&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
Wed May 4 22:33:24 2011
@@ -31,6 +31,7 @@ public class Compatibility {
private boolean _quotedNumbers = false;
private boolean _nonOptimisticVersionCheck = false;
private boolean _flushBeforeDetach = true;
+ private boolean _overrideContextClassloader = false;
/**
* Whether to require exact identity value types when creating object
@@ -192,4 +193,22 @@ public class Compatibility {
_flushBeforeDetach = beforeDetach;
}
+ /**
+ * 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/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java?rev=1099630&r1=1099629&r2=1099630&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
(original)
+++
openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/XMLMetaDataParser.java
Wed May 4 22:33:24 2011
@@ -105,6 +105,16 @@ public abstract class XMLMetaDataParser
private LexicalHandler _lh = null;
private int _depth = -1;
private int _ignore = Integer.MAX_VALUE;
+
+ private boolean _overrideContextClassloader = false;
+
+ public boolean getOverrideContextClassloader() {
+ return _overrideContextClassloader;
+ }
+
+ public void setOverrideContextClassloader(boolean overrideCCL) {
+ _overrideContextClassloader = overrideCCL;
+ }
/**
* Whether to parse element text.
@@ -349,36 +359,61 @@ public abstract class XMLMetaDataParser
// parse the metadata with a SAX parser
try {
_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) {
- if (_parseComments || _lh != null)
- parser.setProperty
+ 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
+ if (schema != null) {
+ parser.setProperty
("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
- "http://www.w3.org/2001/XMLSchema");
- parser.setProperty
+ "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());
- JavaVersions.initCause(ioe, 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());
+ JavaVersions.initCause(ioe, 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/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java?rev=1099630&r1=1099629&r2=1099630&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
(original)
+++
openjpa/branches/1.0.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
Wed May 4 22:33:24 2011
@@ -788,6 +788,24 @@ public abstract class J2DoPrivHelper {
}
};
}
+
+ /**
+ * Return a PrivilegeAction object for Thread.currentThread
+ * .setContextClassLoader().
+ *
+ * Requires security policy:
+ * 'permission java.lang.RuntimePermission "setContextClassLoader";'
+ *
+ * @return ClassLoader
+ */
+ public static final PrivilegedAction setContextClassLoaderAction(final
ClassLoader loader) {
+ return new PrivilegedAction() {
+ public Object run() {
+ Thread.currentThread().setContextClassLoader(loader);
+ return Boolean.TRUE;
+ }
+ };
+ }
/**
* Return a PrivilegedAction object for new Thread().
Modified:
openjpa/branches/1.0.x/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties?rev=1099630&r1=1099629&r2=1099630&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
(original)
+++
openjpa/branches/1.0.x/openjpa-lib/src/main/resources/org/apache/openjpa/lib/meta/localizer.properties
Wed May 4 22:33:24 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/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java?rev=1099630&r1=1099629&r2=1099630&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
(original)
+++
openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
Wed May 4 22:33:24 2011
@@ -235,6 +235,14 @@ public class XMLPersistenceMetaDataParse
if (repos != null
&& (repos.getValidate() & repos.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());
+ }
}
/**