0
# XStream Implementation
1
2
The XStream implementation provides XML marshalling and unmarshalling using the XStream library. It offers an alternative to JAXB with different configuration options, security controls, and converter-based customization.
3
4
## Core Class
5
6
### XStreamMarshaller
7
8
The main XStream implementation class that extends AbstractMarshaller and provides XStream-based XML processing.
9
10
```java { .api }
11
public class XStreamMarshaller extends AbstractMarshaller implements BeanClassLoaderAware, InitializingBean {
12
13
// Configuration Methods
14
public void setSupportedClasses(Class<?>... supportedClasses);
15
public void setTypePermissions(TypePermission... typePermissions);
16
public void setConverters(ConverterMatcher... converters);
17
public void setMarshallingStrategy(MarshallingStrategy marshallingStrategy);
18
public void setMode(int mode);
19
public void setAliases(Map<String, ?> aliases);
20
public void setAliasesByType(Map<Class<?>, String> aliasesByType);
21
public void setFieldAliases(Map<String, String> fieldAliases);
22
public void setUseAttributeFor(Map<?, ?> useAttributeFor);
23
public void setUseAttributeForTypes(Class<?>... useAttributeForTypes);
24
public void setImplicitCollections(Map<Class<?>, String> implicitCollections);
25
public void setOmittedFields(Map<Class<?>, String> omittedFields);
26
public void setStreamDriver(HierarchicalStreamDriver streamDriver);
27
public void setEncoding(String encoding);
28
public void setClassLoader(ClassLoader classLoader);
29
public void setAutodetectAnnotations(boolean autodetectAnnotations);
30
public void setReflectionProvider(ReflectionProvider reflectionProvider);
31
public void setMapperWrappers(Class<? extends MapperWrapper>... mapperWrappers);
32
33
// Security Methods - Type permissions and supported classes provide security controls
34
35
// Inherited methods
36
public boolean supports(Class<?> clazz);
37
public void marshal(Object graph, Result result) throws IOException, XmlMappingException;
38
public Object unmarshal(Source source) throws IOException, XmlMappingException;
39
}
40
```
41
42
## Configuration Options
43
44
### Basic Configuration
45
46
```java
47
import org.springframework.oxm.xstream.XStreamMarshaller;
48
49
XStreamMarshaller marshaller = new XStreamMarshaller();
50
51
// Specify supported classes for security
52
marshaller.setSupportedClasses(Customer.class, Order.class, Product.class);
53
54
// Initialize the marshaller
55
marshaller.afterPropertiesSet();
56
```
57
58
### Security Configuration
59
60
XStream requires explicit security configuration to prevent deserialization vulnerabilities:
61
62
```java
63
import com.thoughtworks.xstream.security.TypePermission;
64
import com.thoughtworks.xstream.security.WildcardTypePermission;
65
66
XStreamMarshaller marshaller = new XStreamMarshaller();
67
68
// Option 1: Use supported classes (recommended)
69
marshaller.setSupportedClasses(Customer.class, Order.class);
70
71
// Option 2: Use type permissions for more granular control
72
TypePermission[] permissions = {
73
new WildcardTypePermission(new String[]{"com.example.model.**"}),
74
new WildcardTypePermission(new String[]{"java.util.**"})
75
};
76
marshaller.setTypePermissions(permissions);
77
78
// Security is handled through type permissions and supported classes
79
80
marshaller.afterPropertiesSet();
81
```
82
83
### Aliases and Field Mapping
84
85
Customize XML element names and structure:
86
87
```java
88
import java.util.HashMap;
89
import java.util.Map;
90
91
XStreamMarshaller marshaller = new XStreamMarshaller();
92
marshaller.setSupportedClasses(Customer.class, Order.class);
93
94
// Class aliases (changes root element name)
95
Map<String, Class<?>> aliases = new HashMap<>();
96
aliases.put("customer", Customer.class);
97
aliases.put("order", Order.class);
98
marshaller.setAliases(aliases);
99
100
// Type-based aliases
101
Map<Class<?>, String> aliasesByType = new HashMap<>();
102
aliasesByType.put(Customer.class, "customer");
103
marshaller.setAliasesByType(aliasesByType);
104
105
// Field aliases (changes property names)
106
Map<String, String> fieldAliases = new HashMap<>();
107
fieldAliases.put("Customer.firstName", "fname");
108
fieldAliases.put("Customer.lastName", "lname");
109
marshaller.setFieldAliases(fieldAliases);
110
111
marshaller.afterPropertiesSet();
112
```
113
114
### Attribute Mapping
115
116
Configure which fields should be XML attributes instead of elements:
117
118
```java
119
Map<String, Class<?>> useAttributeFor = new HashMap<>();
120
useAttributeFor.put("Customer.id", String.class);
121
useAttributeFor.put("Order.status", String.class);
122
marshaller.setUseAttributeFor(useAttributeFor);
123
124
// Or specify by type
125
marshaller.setUseAttributeForTypes(Long.class, Integer.class);
126
```
127
128
### Collection Handling
129
130
Configure implicit collections to avoid wrapper elements:
131
132
```java
133
Map<Class<?>, String> implicitCollections = new HashMap<>();
134
implicitCollections.put(Order.class, "items");
135
implicitCollections.put(Customer.class, "addresses");
136
marshaller.setImplicitCollections(implicitCollections);
137
```
138
139
### Custom Converters
140
141
Implement custom conversion logic for specific types:
142
143
```java
144
import com.thoughtworks.xstream.converters.Converter;
145
import com.thoughtworks.xstream.converters.MarshallingContext;
146
import com.thoughtworks.xstream.converters.UnmarshallingContext;
147
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
148
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
149
150
public class DateConverter implements Converter {
151
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
152
153
@Override
154
public boolean canConvert(Class type) {
155
return Date.class.isAssignableFrom(type);
156
}
157
158
@Override
159
public void marshal(Object source, HierarchicalStreamWriter writer,
160
MarshallingContext context) {
161
Date date = (Date) source;
162
writer.setValue(dateFormat.format(date));
163
}
164
165
@Override
166
public Object unmarshal(HierarchicalStreamReader reader,
167
UnmarshallingContext context) {
168
try {
169
return dateFormat.parse(reader.getValue());
170
} catch (ParseException e) {
171
throw new ConversionException("Cannot parse date", e);
172
}
173
}
174
}
175
176
// Configure marshaller with custom converter
177
XStreamMarshaller marshaller = new XStreamMarshaller();
178
marshaller.setSupportedClasses(Customer.class);
179
marshaller.setConverters(new DateConverter());
180
marshaller.afterPropertiesSet();
181
```
182
183
### Stream Drivers
184
185
Configure different XML processing drivers:
186
187
```java
188
import com.thoughtworks.xstream.io.xml.StaxDriver;
189
import com.thoughtworks.xstream.io.xml.DomDriver;
190
191
// Use StAX driver for better performance
192
marshaller.setStreamDriver(new StaxDriver());
193
194
// Or use DOM driver for DOM processing
195
marshaller.setStreamDriver(new DomDriver());
196
```
197
198
## Usage Examples
199
200
### Basic Usage
201
202
```java
203
import org.springframework.oxm.xstream.XStreamMarshaller;
204
import javax.xml.transform.stream.StreamResult;
205
import javax.xml.transform.stream.StreamSource;
206
import java.io.StringWriter;
207
import java.io.StringReader;
208
209
// Configure marshaller
210
XStreamMarshaller marshaller = new XStreamMarshaller();
211
marshaller.setSupportedClasses(Customer.class);
212
marshaller.afterPropertiesSet();
213
214
// Marshal object to XML
215
Customer customer = new Customer("John", "Doe");
216
StringWriter writer = new StringWriter();
217
marshaller.marshal(customer, new StreamResult(writer));
218
String xml = writer.toString();
219
220
// Unmarshal XML to object
221
StringReader reader = new StringReader(xml);
222
Customer unmarshalled = (Customer) marshaller.unmarshal(new StreamSource(reader));
223
```
224
225
### With Custom Configuration
226
227
```java
228
import java.util.HashMap;
229
import java.util.Map;
230
231
XStreamMarshaller marshaller = new XStreamMarshaller();
232
marshaller.setSupportedClasses(Customer.class, Order.class);
233
234
// Configure aliases
235
Map<String, Class<?>> aliases = new HashMap<>();
236
aliases.put("customer", Customer.class);
237
aliases.put("order", Order.class);
238
marshaller.setAliases(aliases);
239
240
// Configure attributes
241
Map<String, Class<?>> useAttributeFor = new HashMap<>();
242
useAttributeFor.put("Customer.id", Long.class);
243
marshaller.setUseAttributeFor(useAttributeFor);
244
245
// Configure encoding
246
marshaller.setEncoding("UTF-8");
247
248
marshaller.afterPropertiesSet();
249
250
// Use marshaller
251
Customer customer = new Customer();
252
customer.setId(123L);
253
customer.setFirstName("John");
254
255
StringWriter writer = new StringWriter();
256
marshaller.marshal(customer, new StreamResult(writer));
257
// Results in: <customer id="123"><firstName>John</firstName></customer>
258
```
259
260
### Error Handling
261
262
```java
263
try {
264
Customer customer = new Customer();
265
StringWriter writer = new StringWriter();
266
marshaller.marshal(customer, new StreamResult(writer));
267
} catch (MarshallingFailureException e) {
268
System.err.println("Marshalling failed: " + e.getMessage());
269
Throwable cause = e.getCause();
270
if (cause instanceof ConversionException) {
271
System.err.println("XStream conversion error: " + cause.getMessage());
272
}
273
}
274
```
275
276
## Helper Classes
277
278
### CatchAllConverter
279
280
Utility converter for handling unregistered types:
281
282
```java { .api }
283
public class CatchAllConverter implements Converter {
284
public boolean canConvert(Class type);
285
public void marshal(Object source, HierarchicalStreamWriter writer,
286
MarshallingContext context);
287
public Object unmarshal(HierarchicalStreamReader reader,
288
UnmarshallingContext context);
289
}
290
```
291
292
## Security Considerations
293
294
XStream has known security vulnerabilities when deserializing untrusted XML. Always:
295
296
1. Use `setSupportedClasses()` to whitelist allowed classes
297
2. Use `setTypePermissions()` for granular control
298
3. Configure appropriate type permissions
299
4. Never deserialize XML from untrusted sources without proper security configuration
300
301
```java
302
// Secure configuration example
303
XStreamMarshaller marshaller = new XStreamMarshaller();
304
305
// Explicitly allow only specific classes
306
marshaller.setSupportedClasses(
307
Customer.class,
308
Order.class,
309
String.class,
310
java.util.Date.class,
311
java.util.ArrayList.class
312
);
313
314
// Security is handled through type permissions and supported classes
315
316
marshaller.afterPropertiesSet();
317
```
318
319
## Required Imports
320
321
```java
322
import org.springframework.oxm.xstream.XStreamMarshaller;
323
import org.springframework.oxm.xstream.CatchAllConverter;
324
import org.springframework.oxm.MarshallingFailureException;
325
import org.springframework.oxm.UnmarshallingFailureException;
326
327
import com.thoughtworks.xstream.converters.Converter;
328
import com.thoughtworks.xstream.converters.SingleValueConverter;
329
import com.thoughtworks.xstream.converters.MarshallingContext;
330
import com.thoughtworks.xstream.converters.UnmarshallingContext;
331
import com.thoughtworks.xstream.converters.ConversionException;
332
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
333
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
334
import com.thoughtworks.xstream.io.xml.StaxDriver;
335
import com.thoughtworks.xstream.io.xml.DomDriver;
336
import com.thoughtworks.xstream.security.TypePermission;
337
import com.thoughtworks.xstream.security.WildcardTypePermission;
338
import com.thoughtworks.xstream.MarshallingStrategy;
339
340
import javax.xml.transform.stream.StreamResult;
341
import javax.xml.transform.stream.StreamSource;
342
import java.util.Map;
343
import java.util.HashMap;
344
```
345
346
## Spring Configuration
347
348
### XML Configuration
349
350
```xml
351
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
352
<property name="supportedClasses">
353
<list>
354
<value>com.example.Customer</value>
355
<value>com.example.Order</value>
356
</list>
357
</property>
358
<property name="aliases">
359
<map>
360
<entry key="customer" value="com.example.Customer"/>
361
<entry key="order" value="com.example.Order"/>
362
</map>
363
</property>
364
<property name="secureProcessing" value="true"/>
365
</bean>
366
```
367
368
### Java Configuration
369
370
```java
371
@Configuration
372
public class XStreamConfig {
373
374
@Bean
375
public XStreamMarshaller xstreamMarshaller() {
376
XStreamMarshaller marshaller = new XStreamMarshaller();
377
marshaller.setSupportedClasses(Customer.class, Order.class);
378
379
Map<String, Class<?>> aliases = new HashMap<>();
380
aliases.put("customer", Customer.class);
381
marshaller.setAliases(aliases);
382
383
marshaller.setSecureProcessing(true);
384
return marshaller;
385
}
386
}
387
```