Skip to content

Commit

Permalink
Convenient configuration of type permissions for XStream 1.4.18
Browse files Browse the repository at this point in the history
  • Loading branch information
jhoeller authored and lxbzmy committed Mar 26, 2022
1 parent a53f996 commit 90c7bc6
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 18 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -63,6 +63,8 @@
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.mapper.MapperWrapper;
import com.thoughtworks.xstream.security.ForbiddenClassException;
import com.thoughtworks.xstream.security.TypePermission;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
Expand Down Expand Up @@ -106,7 +108,7 @@
* Therefore, it has limited namespace support. As such, it is rather unsuitable for
* usage within Web Services.
*
* <p>This marshaller requires XStream 1.4.5 or higher, as of Spring 4.3.
* <p>This marshaller requires XStream 1.4.7 or higher, as of Spring 5.2.17.
* Note that {@link XStream} construction has been reworked in 4.0, with the
* stream driver and the class loader getting passed into XStream itself now.
*
Expand Down Expand Up @@ -146,6 +148,9 @@ public class XStreamMarshaller extends AbstractMarshaller implements BeanClassLo
@Nullable
private ConverterMatcher[] converters;

@Nullable
private TypePermission[] typePermissions;

@Nullable
private MarshallingStrategy marshallingStrategy;

Expand Down Expand Up @@ -268,6 +273,20 @@ public void setConverters(ConverterMatcher... converters) {
this.converters = converters;
}

/**
* Set XStream type permissions such as
* {@link com.thoughtworks.xstream.security.AnyTypePermission},
* {@link com.thoughtworks.xstream.security.ExplicitTypePermission} etc,
* as an alternative to overriding the {@link #customizeXStream} method.
* <p>Note: As of XStream 1.4.18, the default type permissions are
* restricted to well-known core JDK types. For any custom types,
* explicit type permissions need to be registered.
* @since 5.2.17
*/
public void setTypePermissions(TypePermission... typePermissions) {
this.typePermissions = typePermissions;
}

/**
* Set a custom XStream {@link MarshallingStrategy} to use.
* @since 4.0
Expand Down Expand Up @@ -407,7 +426,7 @@ public void setBeanClassLoader(ClassLoader classLoader) {

@Override
public void afterPropertiesSet() {
// no-op due to use of SingletonSupplier for the XStream field.
// no-op due to use of SingletonSupplier for the XStream field
}

/**
Expand Down Expand Up @@ -479,6 +498,12 @@ else if (this.converters[i] instanceof SingleValueConverter) {
}
}

if (this.typePermissions != null) {
for (TypePermission permission : this.typePermissions) {
xstream.addPermission(permission);
}
}

if (this.marshallingStrategy != null) {
xstream.setMarshallingStrategy(this.marshallingStrategy);
}
Expand Down Expand Up @@ -844,7 +869,7 @@ private Object doUnmarshal(HierarchicalStreamReader streamReader, @Nullable Data
*/
protected XmlMappingException convertXStreamException(Exception ex, boolean marshalling) {
if (ex instanceof StreamException || ex instanceof CannotResolveClassException ||
ex instanceof ConversionException) {
ex instanceof ForbiddenClassException || ex instanceof ConversionException) {
if (marshalling) {
return new MarshallingFailureException("XStream marshalling exception", ex);
}
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,6 +43,7 @@
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;
import com.thoughtworks.xstream.security.AnyTypePermission;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
Expand All @@ -67,18 +68,21 @@
/**
* @author Arjen Poutsma
* @author Sam Brannen
* @author Juergen Hoeller
*/
class XStreamMarshallerTests {

private static final String EXPECTED_STRING = "<flight><flightNumber>42</flightNumber></flight>";

private final XStreamMarshaller marshaller = new XStreamMarshaller();

private final Flight flight = new Flight();

private XStreamMarshaller marshaller;


@BeforeEach
void createMarshaller() {
marshaller = new XStreamMarshaller();
marshaller.setTypePermissions(AnyTypePermission.ANY);
marshaller.setAliases(Collections.singletonMap("flight", Flight.class.getName()));
flight.setFlightNumber(42L);
}
Expand Down Expand Up @@ -143,7 +147,7 @@ void marshalStreamResultOutputStream() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
StreamResult result = new StreamResult(os);
marshaller.marshal(flight, result);
String s = new String(os.toByteArray(), "UTF-8");
String s = os.toString("UTF-8");
assertThat(XmlContent.of(s)).isSimilarTo(EXPECTED_STRING);
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@

import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -29,6 +30,7 @@
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import com.thoughtworks.xstream.security.AnyTypePermission;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
Expand All @@ -40,28 +42,24 @@

/**
* @author Arjen Poutsma
* @author Juergen Hoeller
*/
public class XStreamUnmarshallerTests {

protected static final String INPUT_STRING = "<flight><flightNumber>42</flightNumber></flight>";

private XStreamMarshaller unmarshaller;


@BeforeEach
public void createUnmarshaller() throws Exception {
public void createUnmarshaller() {
unmarshaller = new XStreamMarshaller();
unmarshaller.setTypePermissions(AnyTypePermission.ANY);
Map<String, Class<?>> aliases = new HashMap<>();
aliases.put("flight", Flight.class);
unmarshaller.setAliases(aliases);
}

private void testFlight(Object o) {
boolean condition = o instanceof Flight;
assertThat(condition).as("Unmarshalled object is not Flights").isTrue();
Flight flight = (Flight) o;
assertThat(flight).as("Flight is null").isNotNull();
assertThat(flight.getFlightNumber()).as("Number is invalid").isEqualTo(42L);
}

@Test
public void unmarshalDomSource() throws Exception {
Expand All @@ -83,7 +81,7 @@ public void unmarshalStaxSourceXmlStreamReader() throws Exception {

@Test
public void unmarshalStreamSourceInputStream() throws Exception {
StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes("UTF-8")));
StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes(StandardCharsets.UTF_8)));
Object flights = unmarshaller.unmarshal(source);
testFlight(flights);
}
Expand All @@ -94,5 +92,15 @@ public void unmarshalStreamSourceReader() throws Exception {
Object flights = unmarshaller.unmarshal(source);
testFlight(flights);
}


private void testFlight(Object o) {
boolean condition = o instanceof Flight;
assertThat(condition).as("Unmarshalled object is not Flights").isTrue();
Flight flight = (Flight) o;
assertThat(flight).as("Flight is null").isNotNull();
assertThat(flight.getFlightNumber()).as("Number is invalid").isEqualTo(42L);
}

}

0 comments on commit 90c7bc6

Please sign in to comment.