XStreamMarshaller.java 18.3 KB
Newer Older
A
Arjen Poutsma 已提交
1
/*
J
Juergen Hoeller 已提交
2
 * Copyright 2002-2011 the original author or authors.
A
Arjen Poutsma 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.oxm.xstream;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
26 27
import java.util.LinkedHashMap;
import java.util.List;
A
Arjen Poutsma 已提交
28 29 30 31 32 33 34 35
import java.util.Map;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import com.thoughtworks.xstream.XStream;
36
import com.thoughtworks.xstream.converters.ConversionException;
A
Arjen Poutsma 已提交
37 38 39 40 41 42
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterMatcher;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
43
import com.thoughtworks.xstream.io.StreamException;
A
Arjen Poutsma 已提交
44 45 46 47 48 49 50 51 52
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.DomReader;
import com.thoughtworks.xstream.io.xml.DomWriter;
import com.thoughtworks.xstream.io.xml.QNameMap;
import com.thoughtworks.xstream.io.xml.SaxWriter;
import com.thoughtworks.xstream.io.xml.StaxReader;
import com.thoughtworks.xstream.io.xml.StaxWriter;
import com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer;
import com.thoughtworks.xstream.io.xml.XppReader;
53
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
A
Arjen Poutsma 已提交
54 55 56 57 58 59 60 61
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;

62
import org.springframework.beans.factory.BeanClassLoaderAware;
63
import org.springframework.beans.factory.InitializingBean;
64 65 66
import org.springframework.oxm.MarshallingFailureException;
import org.springframework.oxm.UncategorizedMappingException;
import org.springframework.oxm.UnmarshallingFailureException;
A
Arjen Poutsma 已提交
67
import org.springframework.oxm.XmlMappingException;
68
import org.springframework.oxm.support.AbstractMarshaller;
A
Arjen Poutsma 已提交
69
import org.springframework.util.Assert;
70
import org.springframework.util.ClassUtils;
A
Arjen Poutsma 已提交
71 72
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
A
Arjen Poutsma 已提交
73
import org.springframework.util.xml.StaxUtils;
A
Arjen Poutsma 已提交
74 75

/**
76 77 78 79 80 81 82 83 84 85 86
 * Implementation of the <code>Marshaller</code> interface for XStream.
 *
 * <p>By default, XStream does not require any further configuration,
 * though class aliases can be used to have more control over the behavior of XStream.
 *
 * <p>Due to XStream's API, it is required to set the encoding used for writing to OutputStreams.
 * It defaults to <code>UTF-8</code>.
 *
 * <p><b>NOTE:</b> 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.
A
Arjen Poutsma 已提交
87 88 89
 *
 * @author Peter Meijer
 * @author Arjen Poutsma
A
Arjen Poutsma 已提交
90
 * @since 3.0
91 92 93
 * @see #setAliases
 * @see #setConverters
 * @see #setEncoding
A
Arjen Poutsma 已提交
94
 */
95
public class XStreamMarshaller extends AbstractMarshaller implements InitializingBean, BeanClassLoaderAware {
A
Arjen Poutsma 已提交
96

97 98 99
	/**
	 * The default encoding used for stream access: UTF-8.
	 */
A
Arjen Poutsma 已提交
100 101 102
	public static final String DEFAULT_ENCODING = "UTF-8";


103
	private final XStream xstream = new XStream();
A
Arjen Poutsma 已提交
104 105 106

	private HierarchicalStreamDriver streamDriver;

107 108 109 110
	private String encoding = DEFAULT_ENCODING;

	private Class[] supportedClasses;

111 112
	private ClassLoader classLoader;

J
Juergen Hoeller 已提交
113

A
Arjen Poutsma 已提交
114
	/**
115
	 * Returns the XStream instance used by this marshaller.
A
Arjen Poutsma 已提交
116
	 */
117
	public XStream getXStream() {
J
Juergen Hoeller 已提交
118
		return this.xstream;
A
Arjen Poutsma 已提交
119 120 121
	}

	/**
122
	 * Set the XStream mode.
A
Arjen Poutsma 已提交
123 124 125 126 127
	 * @see XStream#XPATH_REFERENCES
	 * @see XStream#ID_REFERENCES
	 * @see XStream#NO_REFERENCES
	 */
	public void setMode(int mode) {
128
		this.getXStream().setMode(mode);
A
Arjen Poutsma 已提交
129 130 131
	}

	/**
132 133
	 * Set the <code>Converters</code> or <code>SingleValueConverters</code> to be registered
	 * with the <code>XStream</code> instance.
A
Arjen Poutsma 已提交
134 135 136 137 138 139
	 * @see Converter
	 * @see SingleValueConverter
	 */
	public void setConverters(ConverterMatcher[] converters) {
		for (int i = 0; i < converters.length; i++) {
			if (converters[i] instanceof Converter) {
140
				this.getXStream().registerConverter((Converter) converters[i], i);
A
Arjen Poutsma 已提交
141 142
			}
			else if (converters[i] instanceof SingleValueConverter) {
143
				this.getXStream().registerConverter((SingleValueConverter) converters[i], i);
A
Arjen Poutsma 已提交
144 145 146 147 148 149 150 151
			}
			else {
				throw new IllegalArgumentException("Invalid ConverterMatcher [" + converters[i] + "]");
			}
		}
	}

	/**
152 153 154 155 156
	 * Sets an alias/type map, consisting of string aliases mapped to classes. Keys are aliases; values are either
	 * {@code Class} instances, or String class names.
	 * @see XStream#alias(String, Class)
	 */
	public void setAliases(Map<String, ?> aliases) throws ClassNotFoundException {
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
		Map<String, Class<?>> classMap = toClassMap(aliases);

		for (Map.Entry<String, Class<?>> entry : classMap.entrySet()) {
			this.getXStream().alias(entry.getKey(), entry.getValue());
		}
	}

	/**
	 * Sets the aliases by type map, consisting of string aliases mapped to classes. Any class that is assignable to
	 * this type will be aliased to the same name. Keys are aliases; values are either
	 * {@code Class} instances, or String class names.
	 * @see XStream#aliasType(String, Class)
	 */
	public void setAliasesByType(Map<String, ?> aliases) throws ClassNotFoundException {
		Map<String, Class<?>> classMap = toClassMap(aliases);

		for (Map.Entry<String, Class<?>> entry : classMap.entrySet()) {
			this.getXStream().aliasType(entry.getKey(), entry.getValue());
		}
	}

	private Map<String, Class<?>> toClassMap(Map<String, ?> map) throws ClassNotFoundException {
		Map<String, Class<?>> result = new LinkedHashMap<String, Class<?>>(map.size());

		for (Map.Entry<String, ?> entry : map.entrySet()) {
			String key = entry.getKey();
183 184 185 186
			Object value = entry.getValue();
			Class type;
			if (value instanceof Class) {
				type = (Class) value;
187 188
			}
			else if (value instanceof String) {
189 190
				String s = (String) value;
				type = ClassUtils.forName(s, classLoader);
191 192
			}
			else {
193 194
				throw new IllegalArgumentException("Unknown value [" + value + "], expected String or Class");
			}
195
			result.put(key, type);
196
		}
197
		return result;
198 199 200 201 202 203 204 205
	}

	/**
	 * Sets a field alias/type map, consiting of field names
	 * @param aliases
	 * @throws ClassNotFoundException
	 * @throws NoSuchFieldException
	 * @see XStream#aliasField(String, Class, String) 
A
Arjen Poutsma 已提交
206
	 */
207 208 209 210 211 212 213 214 215 216 217 218 219
	public void setFieldAliases(Map<String, String> aliases) throws ClassNotFoundException, NoSuchFieldException {
		for (Map.Entry<String, String> entry : aliases.entrySet()) {
			String alias = entry.getValue();
			String field = entry.getKey();
			int idx = field.lastIndexOf('.');
			if (idx != -1) {
				String className = field.substring(0, idx);
				Class clazz = ClassUtils.forName(className, classLoader);
				String fieldName = field.substring(idx + 1);
				this.getXStream().aliasField(alias, clazz, fieldName);
			} else {
				throw new IllegalArgumentException("Field name [" + field + "] does not contain '.'");
			}
A
Arjen Poutsma 已提交
220 221 222 223
		}
	}

	/**
224
	 * Set types to use XML attributes for.
A
Arjen Poutsma 已提交
225 226 227 228
	 * @see XStream#useAttributeFor(Class)
	 */
	public void setUseAttributeForTypes(Class[] types) {
		for (Class type : types) {
229
			this.getXStream().useAttributeFor(type);
A
Arjen Poutsma 已提交
230 231 232 233
		}
	}

	/**
234
	 * Set the types to use XML attributes for. The given map can contain
235 236 237 238
	 * either {@code <String, Class>} pairs, in which case
	 * {@link XStream#useAttributeFor(String, Class)} is called.
	 * Alternatively, the map can contain {@code <Class, String>}
	 * or {@code <Class, List<String>>} pairs, which results in
239
	 * {@link XStream#useAttributeFor(Class, String)} calls.
A
Arjen Poutsma 已提交
240
	 */
241 242
	public void setUseAttributeFor(Map<?, ?> attributes) {
		for (Map.Entry<?, ?> entry : attributes.entrySet()) {
243 244 245 246 247 248 249 250 251
			if (entry.getKey() instanceof String) {
				if (entry.getValue() instanceof Class) {
					this.getXStream().useAttributeFor((String) entry.getKey(), (Class) entry.getValue());
				}
				else {
					throw new IllegalArgumentException(
							"Invalid argument 'attributes'. 'useAttributesFor' property takes map of <String, Class>," +
									" when using a map key of type String");
				}
A
Arjen Poutsma 已提交
252
			}
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
			else if (entry.getKey() instanceof Class) {
				Class<?> key = (Class<?>) entry.getKey();
				if (entry.getValue() instanceof String) {
					this.getXStream().useAttributeFor(key, (String) entry.getValue());
				}
				else if (entry.getValue() instanceof List) {
					List list = (List) entry.getValue();

					for (Object o : list) {
						if (o instanceof String) {
							this.getXStream().useAttributeFor(key, (String) o);
						}
					}
				}
				else {
					throw new IllegalArgumentException("Invalid argument 'attributes'. " +
							"'useAttributesFor' property takes either <Class, String> or <Class, List<String>> map," +
							" when using a map key of type Class");
				}
A
Arjen Poutsma 已提交
272 273
			}
			else {
274 275
				throw new IllegalArgumentException("Invalid argument 'attributes. " +
						"'useAttributesFor' property takes either a map key of type String or Class");
A
Arjen Poutsma 已提交
276 277 278 279 280
			}
		}
	}

	/**
281 282 283
	 * Specify implicit collection fields, as a Map consisting of <code>Class</code> instances
	 * mapped to comma separated collection field names.
	 *@see XStream#addImplicitCollection(Class, String)
A
Arjen Poutsma 已提交
284
	 */
285 286 287 288 289 290
	public void setImplicitCollections(Map<Class<?>, String> implicitCollections) {
		for (Map.Entry<Class<?>, String> entry : implicitCollections.entrySet()) {
			String[] collectionFields = StringUtils.commaDelimitedListToStringArray(entry.getValue());
			for (String collectionField : collectionFields) {
				this.getXStream().addImplicitCollection(entry.getKey(), collectionField);
			}
291
		}
A
Arjen Poutsma 已提交
292 293 294
	}

	/**
295 296
	 * Specify omitted fields, as a Map consisting of <code>Class</code> instances
	 * mapped to comma separated field names.
A
Arjen Poutsma 已提交
297 298
	 * @see XStream#omitField(Class, String)
	 */
299 300
	public void setOmittedFields(Map<Class<?>, String> omittedFields) {
		for (Map.Entry<Class<?>, String> entry : omittedFields.entrySet()) {
301 302
			String[] fields = StringUtils.commaDelimitedListToStringArray(entry.getValue());
			for (String field : fields) {
303
				this.getXStream().omitField(entry.getKey(), field);
304 305
			}
		}
A
Arjen Poutsma 已提交
306 307 308
	}

	/**
309
	 * Set the classes for which mappings will be read from class-level JDK 1.5+ annotation metadata.
310
	 * @see XStream#processAnnotations(Class)
A
Arjen Poutsma 已提交
311 312 313
	 */
	public void setAnnotatedClass(Class<?> annotatedClass) {
		Assert.notNull(annotatedClass, "'annotatedClass' must not be null");
314
		this.getXStream().processAnnotations(annotatedClass);
A
Arjen Poutsma 已提交
315 316 317
	}

	/**
318
	 * Set annotated classes for which aliases will be read from class-level JDK 1.5+ annotation metadata.
319
	 * @see XStream#processAnnotations(Class[])
A
Arjen Poutsma 已提交
320 321 322
	 */
	public void setAnnotatedClasses(Class<?>[] annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "'annotatedClasses' must not be empty");
323
		this.getXStream().processAnnotations(annotatedClasses);
324 325
	}

326
	/**
J
Juergen Hoeller 已提交
327 328 329
	 * Set the autodetection mode of XStream.
	 * <p><strong>Note</strong> that auto-detection implies that the XStream is configured while
	 * it is processing the XML streams, and thus introduces a potential concurrency problem.
330 331 332 333 334 335
	 * @see XStream#autodetectAnnotations(boolean)
	 */
	public void setAutodetectAnnotations(boolean autodetectAnnotations) {
		this.getXStream().autodetectAnnotations(autodetectAnnotations);
	}

336 337 338 339 340 341 342 343 344 345 346 347 348
	/**
	 * Set the XStream hierarchical stream driver to be used with stream readers and writers.
	 */
	public void setStreamDriver(HierarchicalStreamDriver streamDriver) {
		this.streamDriver = streamDriver;
	}

	/**
	 * Set the encoding to be used for stream access.
	 * @see #DEFAULT_ENCODING
	 */
	public void setEncoding(String encoding) {
		this.encoding = encoding;
A
Arjen Poutsma 已提交
349 350
	}

351 352 353 354 355 356 357 358 359
	/**
	 * Set the classes supported by this marshaller.
	 * <p>If this property is empty (the default), all classes are supported.
	 * @see #supports(Class)
	 */
	public void setSupportedClasses(Class[] supportedClasses) {
		this.supportedClasses = supportedClasses;
	}

360 361 362 363
	public void setBeanClassLoader(ClassLoader classLoader) {
		this.classLoader = classLoader;
	}

J
Juergen Hoeller 已提交
364 365 366 367 368

	public final void afterPropertiesSet() throws Exception {
		customizeXStream(getXStream());
	}

369 370
	/**
	 * Template to allow for customizing of the given {@link XStream}.
J
Juergen Hoeller 已提交
371
	 * <p>The default implementation is empty.
372 373 374 375
	 * @param xstream the {@code XStream} instance
	 */
	protected void customizeXStream(XStream xstream) {
	}
376

J
Juergen Hoeller 已提交
377

A
Arjen Poutsma 已提交
378
	public boolean supports(Class clazz) {
379
		if (ObjectUtils.isEmpty(this.supportedClasses)) {
A
Arjen Poutsma 已提交
380 381 382
			return true;
		}
		else {
383
			for (Class supportedClass : this.supportedClasses) {
A
Arjen Poutsma 已提交
384 385 386 387 388 389 390 391 392 393 394 395
				if (supportedClass.isAssignableFrom(clazz)) {
					return true;
				}
			}
			return false;
		}
	}


	// Marshalling

	@Override
A
Arjen Poutsma 已提交
396
	protected void marshalDomNode(Object graph, Node node) throws XmlMappingException {
A
Arjen Poutsma 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410
		HierarchicalStreamWriter streamWriter;
		if (node instanceof Document) {
			streamWriter = new DomWriter((Document) node);
		}
		else if (node instanceof Element) {
			streamWriter = new DomWriter((Element) node, node.getOwnerDocument(), new XmlFriendlyReplacer());
		}
		else {
			throw new IllegalArgumentException("DOMResult contains neither Document nor Element");
		}
		marshal(graph, streamWriter);
	}

	@Override
A
Arjen Poutsma 已提交
411
	protected void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException {
A
Arjen Poutsma 已提交
412 413 414
		ContentHandler contentHandler = StaxUtils.createContentHandler(eventWriter);
		marshalSaxHandlers(graph, contentHandler, null);
	}
A
Arjen Poutsma 已提交
415

A
Arjen Poutsma 已提交
416
	@Override
A
Arjen Poutsma 已提交
417
	protected void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException {
A
Arjen Poutsma 已提交
418 419 420 421 422 423 424 425 426
		try {
			marshal(graph, new StaxWriter(new QNameMap(), streamWriter));
		}
		catch (XMLStreamException ex) {
			throw convertXStreamException(ex, true);
		}
	}

	@Override
427 428
	protected void marshalOutputStream(Object graph, OutputStream outputStream) throws XmlMappingException, IOException {
		marshalWriter(graph, new OutputStreamWriter(outputStream, this.encoding));
A
Arjen Poutsma 已提交
429
	}
A
Arjen Poutsma 已提交
430

A
Arjen Poutsma 已提交
431
	@Override
A
Arjen Poutsma 已提交
432
	protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
A
Arjen Poutsma 已提交
433
			throws XmlMappingException {
434

A
Arjen Poutsma 已提交
435 436 437 438
		SaxWriter saxWriter = new SaxWriter();
		saxWriter.setContentHandler(contentHandler);
		marshal(graph, saxWriter);
	}
A
Arjen Poutsma 已提交
439

A
Arjen Poutsma 已提交
440
	@Override
A
Arjen Poutsma 已提交
441
	protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
J
Juergen Hoeller 已提交
442 443
		if (this.streamDriver != null) {
			marshal(graph, this.streamDriver.createWriter(writer));
A
Arjen Poutsma 已提交
444 445 446 447 448 449
		}
		else {
			marshal(graph, new CompactWriter(writer));
		}
	}

450 451 452 453 454
	/**
	 * Marshals the given graph to the given XStream HierarchicalStreamWriter.
	 * Converts exceptions using {@link #convertXStreamException}.
	 */
	private void marshal(Object graph, HierarchicalStreamWriter streamWriter) {
A
Arjen Poutsma 已提交
455
		try {
456
			getXStream().marshal(graph, streamWriter);
A
Arjen Poutsma 已提交
457 458
		}
		catch (Exception ex) {
459
			throw convertXStreamException(ex, true);
A
Arjen Poutsma 已提交
460
		}
461 462 463 464 465 466 467 468
		finally {
			try {
				streamWriter.flush();
			}
			catch (Exception ex) {
				logger.debug("Could not flush HierarchicalStreamWriter", ex);
			}
		}
A
Arjen Poutsma 已提交
469 470
	}

J
Juergen Hoeller 已提交
471

472 473
	// Unmarshalling

A
Arjen Poutsma 已提交
474
	@Override
A
Arjen Poutsma 已提交
475
	protected Object unmarshalDomNode(Node node) throws XmlMappingException {
A
Arjen Poutsma 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489
		HierarchicalStreamReader streamReader;
		if (node instanceof Document) {
			streamReader = new DomReader((Document) node);
		}
		else if (node instanceof Element) {
			streamReader = new DomReader((Element) node);
		}
		else {
			throw new IllegalArgumentException("DOMSource contains neither Document nor Element");
		}
		return unmarshal(streamReader);
	}

	@Override
A
Arjen Poutsma 已提交
490
	protected Object unmarshalXmlEventReader(XMLEventReader eventReader) throws XmlMappingException {
A
Arjen Poutsma 已提交
491 492 493 494 495 496 497 498 499 500
		try {
			XMLStreamReader streamReader = StaxUtils.createEventStreamReader(eventReader);
			return unmarshalXmlStreamReader(streamReader);
		}
		catch (XMLStreamException ex) {
			throw convertXStreamException(ex, false);
		}
	}

	@Override
A
Arjen Poutsma 已提交
501
	protected Object unmarshalXmlStreamReader(XMLStreamReader streamReader) throws XmlMappingException {
A
Arjen Poutsma 已提交
502 503
		return unmarshal(new StaxReader(new QNameMap(), streamReader));
	}
A
Arjen Poutsma 已提交
504

A
Arjen Poutsma 已提交
505
	@Override
A
Arjen Poutsma 已提交
506
	protected Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException {
507
		return unmarshalReader(new InputStreamReader(inputStream, this.encoding));
A
Arjen Poutsma 已提交
508
	}
A
Arjen Poutsma 已提交
509

A
Arjen Poutsma 已提交
510
	@Override
A
Arjen Poutsma 已提交
511
	protected Object unmarshalReader(Reader reader) throws XmlMappingException, IOException {
A
Arjen Poutsma 已提交
512 513 514 515 516 517 518 519 520
		if (streamDriver != null) {
			return unmarshal(streamDriver.createReader(reader));
		}
		else {
			return unmarshal(new XppReader(reader));
		}
	}

	@Override
A
Arjen Poutsma 已提交
521
	protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
A
Arjen Poutsma 已提交
522
			throws XmlMappingException, IOException {
523

A
Arjen Poutsma 已提交
524 525 526
		throw new UnsupportedOperationException(
				"XStreamMarshaller does not support unmarshalling using SAX XMLReaders");
	}
A
Arjen Poutsma 已提交
527

528 529
	private Object unmarshal(HierarchicalStreamReader streamReader) {
		try {
530
			return this.getXStream().unmarshal(streamReader);
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
		}
		catch (Exception ex) {
			throw convertXStreamException(ex, false);
		}
	}


	/**
	 * Convert the given XStream exception to an appropriate exception from the
	 * <code>org.springframework.oxm</code> hierarchy.
	 * <p>A boolean flag is used to indicate whether this exception occurs during marshalling or
	 * unmarshalling, since XStream itself does not make this distinction in its exception hierarchy.
	 * @param ex XStream exception that occured
	 * @param marshalling indicates whether the exception occurs during marshalling (<code>true</code>),
	 * or unmarshalling (<code>false</code>)
	 * @return the corresponding <code>XmlMappingException</code>
	 */
	protected XmlMappingException convertXStreamException(Exception ex, boolean marshalling) {
		if (ex instanceof StreamException || ex instanceof CannotResolveClassException ||
				ex instanceof ConversionException) {
			if (marshalling) {
				return new MarshallingFailureException("XStream marshalling exception",  ex);
			}
			else {
				return new UnmarshallingFailureException("XStream unmarshalling exception", ex);
			}
		}
		else {
			// fallback
			return new UncategorizedMappingException("Unknown XStream exception", ex);
		}
	}
A
Arjen Poutsma 已提交
563
}