diff --git a/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java b/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java index dd36d17b8bf..d7d615e2792 100644 --- a/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java +++ b/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java @@ -75,22 +75,28 @@ import org.springframework.util.xml.StaxUtils; /** * Implementation of the {@code Marshaller} interface for XStream. * - *
By default, XStream does not require any further configuration, - * though class aliases can be used to have more control over the behavior of XStream. + *
By default, XStream does not require any further configuration and can (un)marshal + * any class on the classpath. As such, it is not recommended to use the + * {@code XStreamMarshaller} to unmarshal XML from external sources (i.e. the Web), + * as this can result in security vulnerabilities. If you do use the + * {@code XStreamMarshaller} to unmarshal external XML, set the + * {@link #setConverters(ConverterMatcher[]) converters} and + * {@link #setSupportedClasses(Class[]) supportedClasses} properties or override the + * {@link #customizeXStream(XStream)} method to make sure it only accepts the classes + * you want it to support. * *
Due to XStream's API, it is required to set the encoding used for writing to OutputStreams. * It defaults to {@code UTF-8}. * *
NOTE: XStream is an XML serialization library, not a data binding library. * Therefore, it has limited namespace support. As such, it is rather unsuitable for - * usage within Web services. + * usage within Web Services. + * + *
This marshaller is compatible with XStream 1.3 and 1.4. * * @author Peter Meijer * @author Arjen Poutsma * @since 3.0 - * @see #setAliases - * @see #setConverters - * @see #setEncoding */ public class XStreamMarshaller extends AbstractMarshaller implements InitializingBean, BeanClassLoaderAware { @@ -106,15 +112,19 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin private String encoding = DEFAULT_ENCODING; - private Class[] supportedClasses; + private Class>[] supportedClasses; - private ClassLoader classLoader; + private ClassLoader beanClassLoader; /** - * Returns the XStream instance used by this marshaller. + * Return the XStream instance used by this marshaller. + *
NOTE: While this method can be overridden in Spring 3.x,
+ * it wasn't originally meant to be. As of Spring 4.0, it will be
+ * marked as final, with all of XStream 1.4's configurable strategies
+ * to be exposed on XStreamMarshaller itself.
*/
- public final XStream getXStream() {
+ public XStream getXStream() {
return this.xstream;
}
@@ -125,7 +135,7 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
* @see XStream#NO_REFERENCES
*/
public void setMode(int mode) {
- this.xstream.setMode(mode);
+ getXStream().setMode(mode);
}
/**
@@ -137,10 +147,10 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
public void setConverters(ConverterMatcher[] converters) {
for (int i = 0; i < converters.length; i++) {
if (converters[i] instanceof Converter) {
- this.xstream.registerConverter((Converter) converters[i], i);
+ getXStream().registerConverter((Converter) converters[i], i);
}
else if (converters[i] instanceof SingleValueConverter) {
- this.xstream.registerConverter((SingleValueConverter) converters[i], i);
+ getXStream().registerConverter((SingleValueConverter) converters[i], i);
}
else {
throw new IllegalArgumentException("Invalid ConverterMatcher [" + converters[i] + "]");
@@ -156,7 +166,7 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
public void setAliases(Map Note that auto-detection implies that the XStream is configured while
+ * Activate XStream's autodetection mode.
+ * Note: Autodetection implies that the XStream instance is being configured while
* it is processing the XML streams, and thus introduces a potential concurrency problem.
* @see XStream#autodetectAnnotations(boolean)
*/
public void setAutodetectAnnotations(boolean autodetectAnnotations) {
- this.xstream.autodetectAnnotations(autodetectAnnotations);
+ getXStream().autodetectAnnotations(autodetectAnnotations);
}
/**
@@ -348,17 +355,18 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
* If this property is empty (the default), all classes are supported.
* @see #supports(Class)
*/
- public void setSupportedClasses(Class[] supportedClasses) {
+ public void setSupportedClasses(Class>[] supportedClasses) {
this.supportedClasses = supportedClasses;
}
public void setBeanClassLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
+ this.beanClassLoader = classLoader;
+ getXStream().setClassLoader(classLoader);
}
public final void afterPropertiesSet() throws Exception {
- customizeXStream(this.xstream);
+ customizeXStream(getXStream());
}
/**
@@ -370,12 +378,12 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
}
- public boolean supports(Class clazz) {
+ public boolean supports(Class> clazz) {
if (ObjectUtils.isEmpty(this.supportedClasses)) {
return true;
}
else {
- for (Class supportedClass : this.supportedClasses) {
+ for (Class> supportedClass : this.supportedClasses) {
if (supportedClass.isAssignableFrom(clazz)) {
return true;
}
@@ -453,7 +461,7 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
*/
private void marshal(Object graph, HierarchicalStreamWriter streamWriter) {
try {
- this.xstream.marshal(graph, streamWriter);
+ getXStream().marshal(graph, streamWriter);
}
catch (Exception ex) {
throw convertXStreamException(ex, true);
@@ -536,7 +544,7 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
*/
private Object unmarshal(HierarchicalStreamReader streamReader) {
try {
- return this.xstream.unmarshal(streamReader);
+ return getXStream().unmarshal(streamReader);
}
catch (Exception ex) {
throw convertXStreamException(ex, false);