Jaxb2Marshaller has non-synchronized access to the JAXBContext once initialized
Also backporting "checkForXmlRootElement" property from 3.2 M2 Issue: SPR-9867 Issue: SPR-9757
This commit is contained in:
@@ -101,11 +101,12 @@ import org.springframework.util.xml.StaxUtils;
|
|||||||
/**
|
/**
|
||||||
* Implementation of the <code>Marshaller</code> interface for JAXB 2.0.
|
* Implementation of the <code>Marshaller</code> interface for JAXB 2.0.
|
||||||
*
|
*
|
||||||
* <p>The typical usage will be to set either the <code>contextPath</code> or the <code>classesToBeBound</code> property
|
* <p>The typical usage will be to set either the "contextPath" or the "classesToBeBound"
|
||||||
* on this bean, possibly customize the marshaller and unmarshaller by setting properties, schemas, adapters, and
|
* property on this bean, possibly customize the marshaller and unmarshaller by setting
|
||||||
* listeners, and to refer to it.
|
* properties, schemas, adapters, and listeners, and to refer to it.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see #setContextPath(String)
|
* @see #setContextPath(String)
|
||||||
* @see #setClassesToBeBound(Class[])
|
* @see #setClassesToBeBound(Class[])
|
||||||
@@ -125,9 +126,7 @@ public class Jaxb2Marshaller
|
|||||||
private static final String CID = "cid:";
|
private static final String CID = "cid:";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/** Logger available to subclasses */
|
||||||
* Logger available to subclasses.
|
|
||||||
*/
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
private String contextPath;
|
private String contextPath;
|
||||||
@@ -154,21 +153,25 @@ public class Jaxb2Marshaller
|
|||||||
|
|
||||||
private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
private String schemaLanguage = XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
||||||
|
|
||||||
|
private LSResourceResolver schemaResourceResolver;
|
||||||
|
|
||||||
private boolean mtomEnabled = false;
|
private boolean mtomEnabled = false;
|
||||||
|
|
||||||
private ClassLoader beanClassLoader;
|
|
||||||
|
|
||||||
private ResourceLoader resourceLoader;
|
|
||||||
|
|
||||||
private JAXBContext jaxbContext;
|
|
||||||
|
|
||||||
private Schema schema;
|
|
||||||
|
|
||||||
private boolean lazyInit = false;
|
private boolean lazyInit = false;
|
||||||
|
|
||||||
private boolean supportJaxbElementClass = false;
|
private boolean supportJaxbElementClass = false;
|
||||||
|
|
||||||
private LSResourceResolver schemaResourceResolver;
|
private boolean checkForXmlRootElement = true;
|
||||||
|
|
||||||
|
private ClassLoader beanClassLoader;
|
||||||
|
|
||||||
|
private ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
private final Object jaxbContextMonitor = new Object();
|
||||||
|
|
||||||
|
private volatile JAXBContext jaxbContext;
|
||||||
|
|
||||||
|
private Schema schema;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -358,6 +361,21 @@ public class Jaxb2Marshaller
|
|||||||
this.supportJaxbElementClass = supportJaxbElementClass;
|
this.supportJaxbElementClass = supportJaxbElementClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify whether the {@link #supports(Class)} should check for
|
||||||
|
* {@link XmlRootElement @XmlRootElement} annotations.
|
||||||
|
* <p>Default is {@code true}, meaning that {@code supports(Class)} will check for
|
||||||
|
* this annotation. However, some JAXB implementations (i.e. EclipseLink MOXy) allow
|
||||||
|
* for defining the bindings in an external definition file, thus keeping the classes
|
||||||
|
* annotations free. Setting this property to {@code false} supports these
|
||||||
|
* JAXB implementations.
|
||||||
|
* @see #supports(Class)
|
||||||
|
* @see #supports(Type)
|
||||||
|
*/
|
||||||
|
public void setCheckForXmlRootElement(boolean checkForXmlRootElement) {
|
||||||
|
this.checkForXmlRootElement = checkForXmlRootElement;
|
||||||
|
}
|
||||||
|
|
||||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||||
this.beanClassLoader = classLoader;
|
this.beanClassLoader = classLoader;
|
||||||
}
|
}
|
||||||
@@ -388,24 +406,29 @@ public class Jaxb2Marshaller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized JAXBContext getJaxbContext() {
|
protected JAXBContext getJaxbContext() {
|
||||||
if (this.jaxbContext == null) {
|
if (this.jaxbContext != null) {
|
||||||
try {
|
return this.jaxbContext;
|
||||||
if (StringUtils.hasLength(this.contextPath)) {
|
}
|
||||||
this.jaxbContext = createJaxbContextFromContextPath();
|
synchronized (this.jaxbContextMonitor) {
|
||||||
}
|
if (this.jaxbContext == null) {
|
||||||
else if (!ObjectUtils.isEmpty(this.classesToBeBound)) {
|
try {
|
||||||
this.jaxbContext = createJaxbContextFromClasses();
|
if (StringUtils.hasLength(this.contextPath)) {
|
||||||
}
|
this.jaxbContext = createJaxbContextFromContextPath();
|
||||||
else if (!ObjectUtils.isEmpty(this.packagesToScan)) {
|
}
|
||||||
this.jaxbContext = createJaxbContextFromPackages();
|
else if (!ObjectUtils.isEmpty(this.classesToBeBound)) {
|
||||||
}
|
this.jaxbContext = createJaxbContextFromClasses();
|
||||||
}
|
}
|
||||||
catch (JAXBException ex) {
|
else if (!ObjectUtils.isEmpty(this.packagesToScan)) {
|
||||||
throw convertJaxbException(ex);
|
this.jaxbContext = createJaxbContextFromPackages();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (JAXBException ex) {
|
||||||
|
throw convertJaxbException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.jaxbContext;
|
||||||
}
|
}
|
||||||
return this.jaxbContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JAXBContext createJaxbContextFromContextPath() throws JAXBException {
|
private JAXBContext createJaxbContextFromContextPath() throws JAXBException {
|
||||||
@@ -417,7 +440,9 @@ public class Jaxb2Marshaller
|
|||||||
return JAXBContext.newInstance(this.contextPath, this.beanClassLoader, this.jaxbContextProperties);
|
return JAXBContext.newInstance(this.contextPath, this.beanClassLoader, this.jaxbContextProperties);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return JAXBContext.newInstance(this.contextPath, ClassUtils.getDefaultClassLoader(), this.jaxbContextProperties);
|
// analogous to the JAXBContext.newInstance(String) implementation
|
||||||
|
return JAXBContext.newInstance(this.contextPath, Thread.currentThread().getContextClassLoader(),
|
||||||
|
this.jaxbContextProperties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -492,7 +517,7 @@ public class Jaxb2Marshaller
|
|||||||
if (this.supportJaxbElementClass && JAXBElement.class.isAssignableFrom(clazz)) {
|
if (this.supportJaxbElementClass && JAXBElement.class.isAssignableFrom(clazz)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return supportsInternal(clazz, true);
|
return supportsInternal(clazz, this.checkForXmlRootElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supports(Type genericType) {
|
public boolean supports(Type genericType) {
|
||||||
@@ -521,7 +546,7 @@ public class Jaxb2Marshaller
|
|||||||
}
|
}
|
||||||
else if (genericType instanceof Class) {
|
else if (genericType instanceof Class) {
|
||||||
Class<?> clazz = (Class<?>) genericType;
|
Class<?> clazz = (Class<?>) genericType;
|
||||||
return supportsInternal(clazz, true);
|
return supportsInternal(clazz, this.checkForXmlRootElement);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user