[activemq] 01/02: Import Debian changes 5.6.0+dfsg-1+deb7u2
Markus Koschany
apo at moszumanska.debian.org
Tue Apr 25 18:57:42 UTC 2017
This is an automated email from the git hooks/post-receive script.
apo pushed a commit to branch wheezy
in repository activemq.
commit e1811fcab3a951cda2950bf22e9f8906976eb718
Author: Markus Koschany <apo at debian.org>
Date: Fri Mar 18 22:47:35 2016 +0100
Import Debian changes 5.6.0+dfsg-1+deb7u2
activemq (5.6.0+dfsg-1+deb7u2) wheezy-security; urgency=high
* Team upload.
* Fix CVE-2015-5254:
Apache ActiveMQ 5.x before 5.13.0 does not restrict the classes that can be
serialized in the broker, which allows remote attackers to execute
arbitrary code via a crafted serialized Java Message Service (JMS)
ObjectMessage object.
---
.gitignore | 1 -
debian/changelog | 11 +
debian/patches/CVE-2015-5254.patch | 3034 ++++++++++++++++++++++++++++++++++++
debian/patches/series | 1 +
debian/source/local-options | 1 -
5 files changed, 3046 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 60b9923..1af5e76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
-.pc
*~
*.swp
.idea
diff --git a/debian/changelog b/debian/changelog
index b262759..5aec11b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,14 @@
+activemq (5.6.0+dfsg-1+deb7u2) wheezy-security; urgency=high
+
+ * Team upload.
+ * Fix CVE-2015-5254:
+ Apache ActiveMQ 5.x before 5.13.0 does not restrict the classes that can be
+ serialized in the broker, which allows remote attackers to execute
+ arbitrary code via a crafted serialized Java Message Service (JMS)
+ ObjectMessage object.
+
+ -- Markus Koschany <apo at debian.org> Fri, 18 Mar 2016 22:47:35 +0100
+
activemq (5.6.0+dfsg-1+deb7u1) wheezy-security; urgency=high
* Team upload.
diff --git a/debian/patches/CVE-2015-5254.patch b/debian/patches/CVE-2015-5254.patch
new file mode 100644
index 0000000..2e653e6
--- /dev/null
+++ b/debian/patches/CVE-2015-5254.patch
@@ -0,0 +1,3034 @@
+From: Markus Koschany <apo at debian.org>
+Date: Wed, 16 Mar 2016 18:35:42 +0100
+Subject: CVE-2015-5254
+
+Apache ActiveMQ 5.x before 5.13.0 does not restrict the classes that can be
+serialized in the broker, which allows remote attackers to execute arbitrary
+code via a crafted serialized Java Message Service (JMS) ObjectMessage object.
+
+Origin: https://git-wip-us.apache.org/repos/asf?p=activemq.git;h=6f03921b31d9fefeddb0f4fa63150ed1f94a14b1
+Origin: https://git-wip-us.apache.org/repos/asf?p=activemq.git;h=73a0caf758f9e4916783a205c7e422b4db27905c
+Origin: http://pkgs.fedoraproject.org/cgit/activemq.git/diff/activemq-5.6.0-CVE-2015-5254.patch?id=e3ef8a1b62d10273a814090be9168aa3019ace72
+Debian-Bug: https://bugs.debian.org/809733
+---
+ .../java/com/thoughtworks/xstream/XStream.java | 1928 ++++++++++++++++++++
+ .../xstream/mapper/FieldAliasingMapper.java | 99 +
+ .../xstream/mapper/SecurityMapper.java | 79 +
+ .../xstream/security/AnyTypePermission.java | 32 +
+ .../xstream/security/ArrayTypePermission.java | 32 +
+ .../xstream/security/ExplicitTypePermission.java | 54 +
+ .../xstream/security/ForbiddenClassException.java | 27 +
+ .../xstream/security/InterfaceTypePermission.java | 33 +
+ .../xstream/security/NoPermission.java | 39 +
+ .../xstream/security/NoTypePermission.java | 36 +
+ .../xstream/security/NullPermission.java | 26 +
+ .../xstream/security/PrimitiveTypePermission.java | 34 +
+ .../xstream/security/ProxyTypePermission.java | 37 +
+ .../xstream/security/RegExpTypePermission.java | 48 +
+ .../xstream/security/TypeHierarchyPermission.java | 32 +
+ .../xstream/security/TypePermission.java | 25 +
+ .../xstream/security/WildcardTypePermission.java | 84 +
+ .../transport/stomp/JmsFrameTranslator.java | 5 +-
+ .../activemq/transport/stomp/XStreamSupport.java | 47 +
+ .../util/ClassLoadingAwareObjectInputStream.java | 48 +-
+ .../transport/xstream/XStreamWireFormat.java | 29 +-
+ .../java/org/apache/activemq/web/MessageQuery.java | 4 +-
+ 22 files changed, 2769 insertions(+), 9 deletions(-)
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java
+ create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java
+ create mode 100644 activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java
+
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java b/activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java
+new file mode 100644
+index 0000000..29c047a
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java
+@@ -0,0 +1,1928 @@
++/*
++ * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes.
++ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 XStream Committers.
++ * All rights reserved.
++ *
++ * The software in this package is published under the terms of the BSD
++ * style license a copy of which has been included with this distribution in
++ * the LICENSE.txt file.
++ *
++ * Created on 26. September 2003 by Joe Walnes
++ */
++package com.thoughtworks.xstream;
++
++import java.io.EOFException;
++import java.io.File;
++import java.io.IOException;
++import java.io.InputStream;
++import java.io.NotActiveException;
++import java.io.ObjectInputStream;
++import java.io.ObjectInputValidation;
++import java.io.ObjectOutputStream;
++import java.io.OutputStream;
++import java.io.Reader;
++import java.io.StringReader;
++import java.io.StringWriter;
++import java.io.Writer;
++import java.lang.reflect.Constructor;
++import java.lang.reflect.Field;
++import java.lang.reflect.Method;
++import java.math.BigDecimal;
++import java.math.BigInteger;
++import java.net.URI;
++import java.net.URL;
++import java.util.ArrayList;
++import java.util.BitSet;
++import java.util.Calendar;
++import java.util.Collections;
++import java.util.Date;
++import java.util.GregorianCalendar;
++import java.util.HashMap;
++import java.util.HashSet;
++import java.util.Hashtable;
++import java.util.LinkedList;
++import java.util.List;
++import java.util.Locale;
++import java.util.Map;
++import java.util.Properties;
++import java.util.Set;
++import java.util.SortedSet;
++import java.util.TreeMap;
++import java.util.TreeSet;
++import java.util.Vector;
++import java.util.regex.Pattern;
++
++import com.thoughtworks.xstream.converters.ConversionException;
++import com.thoughtworks.xstream.converters.Converter;
++import com.thoughtworks.xstream.converters.ConverterLookup;
++import com.thoughtworks.xstream.converters.ConverterRegistry;
++import com.thoughtworks.xstream.converters.DataHolder;
++import com.thoughtworks.xstream.converters.SingleValueConverter;
++import com.thoughtworks.xstream.converters.SingleValueConverterWrapper;
++import com.thoughtworks.xstream.converters.basic.BigDecimalConverter;
++import com.thoughtworks.xstream.converters.basic.BigIntegerConverter;
++import com.thoughtworks.xstream.converters.basic.BooleanConverter;
++import com.thoughtworks.xstream.converters.basic.ByteConverter;
++import com.thoughtworks.xstream.converters.basic.CharConverter;
++import com.thoughtworks.xstream.converters.basic.DateConverter;
++import com.thoughtworks.xstream.converters.basic.DoubleConverter;
++import com.thoughtworks.xstream.converters.basic.FloatConverter;
++import com.thoughtworks.xstream.converters.basic.IntConverter;
++import com.thoughtworks.xstream.converters.basic.LongConverter;
++import com.thoughtworks.xstream.converters.basic.NullConverter;
++import com.thoughtworks.xstream.converters.basic.ShortConverter;
++import com.thoughtworks.xstream.converters.basic.StringBufferConverter;
++import com.thoughtworks.xstream.converters.basic.StringConverter;
++import com.thoughtworks.xstream.converters.basic.URIConverter;
++import com.thoughtworks.xstream.converters.basic.URLConverter;
++import com.thoughtworks.xstream.converters.collections.ArrayConverter;
++import com.thoughtworks.xstream.converters.collections.BitSetConverter;
++import com.thoughtworks.xstream.converters.collections.CharArrayConverter;
++import com.thoughtworks.xstream.converters.collections.CollectionConverter;
++import com.thoughtworks.xstream.converters.collections.MapConverter;
++import com.thoughtworks.xstream.converters.collections.PropertiesConverter;
++import com.thoughtworks.xstream.converters.collections.SingletonCollectionConverter;
++import com.thoughtworks.xstream.converters.collections.SingletonMapConverter;
++import com.thoughtworks.xstream.converters.collections.TreeMapConverter;
++import com.thoughtworks.xstream.converters.collections.TreeSetConverter;
++import com.thoughtworks.xstream.converters.extended.ColorConverter;
++import com.thoughtworks.xstream.converters.extended.DynamicProxyConverter;
++import com.thoughtworks.xstream.converters.extended.EncodedByteArrayConverter;
++import com.thoughtworks.xstream.converters.extended.FileConverter;
++import com.thoughtworks.xstream.converters.extended.FontConverter;
++import com.thoughtworks.xstream.converters.extended.GregorianCalendarConverter;
++import com.thoughtworks.xstream.converters.extended.JavaClassConverter;
++import com.thoughtworks.xstream.converters.extended.JavaFieldConverter;
++import com.thoughtworks.xstream.converters.extended.JavaMethodConverter;
++import com.thoughtworks.xstream.converters.extended.LocaleConverter;
++import com.thoughtworks.xstream.converters.extended.LookAndFeelConverter;
++import com.thoughtworks.xstream.converters.extended.SqlDateConverter;
++import com.thoughtworks.xstream.converters.extended.SqlTimeConverter;
++import com.thoughtworks.xstream.converters.extended.SqlTimestampConverter;
++import com.thoughtworks.xstream.converters.extended.TextAttributeConverter;
++import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter;
++import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
++import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
++import com.thoughtworks.xstream.converters.reflection.SelfStreamingInstanceChecker;
++import com.thoughtworks.xstream.converters.reflection.SerializableConverter;
++import com.thoughtworks.xstream.core.DefaultConverterLookup;
++import com.thoughtworks.xstream.core.JVM;
++import com.thoughtworks.xstream.core.MapBackedDataHolder;
++import com.thoughtworks.xstream.core.ReferenceByIdMarshallingStrategy;
++import com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy;
++import com.thoughtworks.xstream.core.TreeMarshallingStrategy;
++import com.thoughtworks.xstream.core.util.ClassLoaderReference;
++import com.thoughtworks.xstream.core.util.CompositeClassLoader;
++import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
++import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
++import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
++import com.thoughtworks.xstream.io.HierarchicalStreamReader;
++import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
++import com.thoughtworks.xstream.io.StatefulWriter;
++import com.thoughtworks.xstream.io.xml.XppDriver;
++import com.thoughtworks.xstream.mapper.AnnotationConfiguration;
++import com.thoughtworks.xstream.mapper.ArrayMapper;
++import com.thoughtworks.xstream.mapper.AttributeAliasingMapper;
++import com.thoughtworks.xstream.mapper.AttributeMapper;
++import com.thoughtworks.xstream.mapper.CachingMapper;
++import com.thoughtworks.xstream.mapper.ClassAliasingMapper;
++import com.thoughtworks.xstream.mapper.DefaultImplementationsMapper;
++import com.thoughtworks.xstream.mapper.DefaultMapper;
++import com.thoughtworks.xstream.mapper.DynamicProxyMapper;
++import com.thoughtworks.xstream.mapper.FieldAliasingMapper;
++import com.thoughtworks.xstream.mapper.ImmutableTypesMapper;
++import com.thoughtworks.xstream.mapper.ImplicitCollectionMapper;
++import com.thoughtworks.xstream.mapper.LocalConversionMapper;
++import com.thoughtworks.xstream.mapper.Mapper;
++import com.thoughtworks.xstream.mapper.MapperWrapper;
++import com.thoughtworks.xstream.mapper.OuterClassMapper;
++import com.thoughtworks.xstream.mapper.PackageAliasingMapper;
++import com.thoughtworks.xstream.mapper.SystemAttributeAliasingMapper;
++import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper;
++import com.thoughtworks.xstream.security.AnyTypePermission;
++import com.thoughtworks.xstream.security.ExplicitTypePermission;
++import com.thoughtworks.xstream.security.NoPermission;
++import com.thoughtworks.xstream.security.NoTypePermission;
++import com.thoughtworks.xstream.security.RegExpTypePermission;
++import com.thoughtworks.xstream.security.TypeHierarchyPermission;
++import com.thoughtworks.xstream.security.TypePermission;
++import com.thoughtworks.xstream.security.WildcardTypePermission;
++import com.thoughtworks.xstream.mapper.SecurityMapper;
++
++
++/**
++ * Simple facade to XStream library, a Java-XML serialization tool. <p/>
++ * <p>
++ * <hr>
++ * <b>Example</b><blockquote>
++ *
++ * <pre>
++ * XStream xstream = new XStream();
++ * String xml = xstream.toXML(myObject); // serialize to XML
++ * Object myObject2 = xstream.fromXML(xml); // deserialize from XML
++ * </pre>
++ *
++ * </blockquote>
++ * <hr>
++ * <p/>
++ * <h3>Aliasing classes</h3>
++ * <p/>
++ * <p>
++ * To create shorter XML, you can specify aliases for classes using the <code>alias()</code>
++ * method. For example, you can shorten all occurrences of element
++ * <code><com.blah.MyThing></code> to <code><my-thing></code> by registering an
++ * alias for the class.
++ * <p>
++ * <hr>
++ * <blockquote>
++ *
++ * <pre>
++ * xstream.alias("my-thing", MyThing.class);
++ * </pre>
++ *
++ * </blockquote>
++ * <hr>
++ * <p/>
++ * <h3>Converters</h3>
++ * <p/>
++ * <p>
++ * XStream contains a map of {@link com.thoughtworks.xstream.converters.Converter} instances, each
++ * of which acts as a strategy for converting a particular type of class to XML and back again. Out
++ * of the box, XStream contains converters for most basic types (String, Date, int, boolean, etc)
++ * and collections (Map, List, Set, Properties, etc). For other objects reflection is used to
++ * serialize each field recursively.
++ * </p>
++ * <p/>
++ * <p>
++ * Extra converters can be registered using the <code>registerConverter()</code> method. Some
++ * non-standard converters are supplied in the {@link com.thoughtworks.xstream.converters.extended}
++ * package and you can create your own by implementing the
++ * {@link com.thoughtworks.xstream.converters.Converter} interface.
++ * </p>
++ * <p/>
++ * <p>
++ * <hr>
++ * <b>Example</b><blockquote>
++ *
++ * <pre>
++ * xstream.registerConverter(new SqlTimestampConverter());
++ * xstream.registerConverter(new DynamicProxyConverter());
++ * </pre>
++ *
++ * </blockquote>
++ * <hr>
++ * <p>
++ * The converters can be registered with an explicit priority. By default they are registered with
++ * XStream.PRIORITY_NORMAL. Converters of same priority will be used in the reverse sequence
++ * they have been registered. The default converter, i.e. the converter which will be used if
++ * no other registered converter is suitable, can be registered with priority
++ * XStream.PRIORITY_VERY_LOW. XStream uses by default the
++ * {@link com.thoughtworks.xstream.converters.reflection.ReflectionConverter} as the fallback
++ * converter.
++ * </p>
++ * <p/>
++ * <p>
++ * <hr>
++ * <b>Example</b><blockquote>
++ *
++ * <pre>
++ * xstream.registerConverter(new CustomDefaultConverter(), XStream.PRIORITY_VERY_LOW);
++ * </pre>
++ *
++ * </blockquote>
++ * <hr>
++ * <p/>
++ * <h3>Object graphs</h3>
++ * <p/>
++ * <p>
++ * XStream has support for object graphs; a deserialized object graph will keep references intact,
++ * including circular references.
++ * </p>
++ * <p/>
++ * <p>
++ * XStream can signify references in XML using either relative/absolute XPath or IDs. The mode can be changed using
++ * <code>setMode()</code>:
++ * </p>
++ * <p/>
++ * <table border='1'>
++ * <tr>
++ * <td><code>xstream.setMode(XStream.XPATH_RELATIVE_REFERENCES);</code></td>
++ * <td><i>(Default)</i> Uses XPath relative references to signify duplicate references. This produces XML
++ * with the least clutter.</td>
++ * </tr>
++ * <tr>
++ * <td><code>xstream.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);</code></td>
++ * <td>Uses XPath absolute references to signify duplicate
++ * references. This produces XML with the least clutter.</td>
++ * </tr>
++ * <tr>
++ * <td><code>xstream.setMode(XStream.SINGLE_NODE_XPATH_RELATIVE_REFERENCES);</code></td>
++ * <td>Uses XPath relative references to signify duplicate references. The XPath expression ensures that
++ * a single node only is selected always.</td>
++ * </tr>
++ * <tr>
++ * <td><code>xstream.setMode(XStream.SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES);</code></td>
++ * <td>Uses XPath absolute references to signify duplicate references. The XPath expression ensures that
++ * a single node only is selected always.</td>
++ * </tr>
++ * <tr>
++ * <td><code>xstream.setMode(XStream.ID_REFERENCES);</code></td>
++ * <td>Uses ID references to signify duplicate references. In some scenarios, such as when using
++ * hand-written XML, this is easier to work with.</td>
++ * </tr>
++ * <tr>
++ * <td><code>xstream.setMode(XStream.NO_REFERENCES);</code></td>
++ * <td>This disables object graph support and treats the object structure like a tree. Duplicate
++ * references are treated as two separate objects and circular references cause an exception. This
++ * is slightly faster and uses less memory than the other two modes.</td>
++ * </tr>
++ * </table>
++ * <h3>Thread safety</h3>
++ * <p>
++ * The XStream instance is thread-safe. That is, once the XStream instance has been created and
++ * configured, it may be shared across multiple threads allowing objects to be
++ * serialized/deserialized concurrently. <em>Note, that this only applies if annotations are not
++ * auto-detected on -the-fly.</em>
++ * </p>
++ * <h3>Implicit collections</h3>
++ * <p/>
++ * <p>
++ * To avoid the need for special tags for collections, you can define implicit collections using one
++ * of the <code>addImplicitCollection</code> methods.
++ * </p>
++ *
++ * @author Joe Walnes
++ * @author Jörg Schaible
++ * @author Mauro Talevi
++ * @author Guilherme Silveira
++ */
++public class XStream {
++
++ // CAUTION: The sequence of the fields is intentional for an optimal XML output of a
++ // self-serialization!
++ private ReflectionProvider reflectionProvider;
++ private HierarchicalStreamDriver hierarchicalStreamDriver;
++ private ClassLoaderReference classLoaderReference;
++ private MarshallingStrategy marshallingStrategy;
++ private ConverterLookup converterLookup;
++ private ConverterRegistry converterRegistry;
++ private Mapper mapper;
++
++ private PackageAliasingMapper packageAliasingMapper;
++ private ClassAliasingMapper classAliasingMapper;
++ private FieldAliasingMapper fieldAliasingMapper;
++ private AttributeAliasingMapper attributeAliasingMapper;
++ private SystemAttributeAliasingMapper systemAttributeAliasingMapper;
++ private AttributeMapper attributeMapper;
++ private DefaultImplementationsMapper defaultImplementationsMapper;
++ private ImmutableTypesMapper immutableTypesMapper;
++ private ImplicitCollectionMapper implicitCollectionMapper;
++ private LocalConversionMapper localConversionMapper;
++ private AnnotationConfiguration annotationConfiguration;
++ private SecurityMapper securityMapper;
++
++ private transient JVM jvm = new JVM();
++
++ public static final int NO_REFERENCES = 1001;
++ public static final int ID_REFERENCES = 1002;
++ public static final int XPATH_RELATIVE_REFERENCES = 1003;
++ public static final int XPATH_ABSOLUTE_REFERENCES = 1004;
++ public static final int SINGLE_NODE_XPATH_RELATIVE_REFERENCES = 1005;
++ public static final int SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES = 1006;
++
++ public static final int PRIORITY_VERY_HIGH = 10000;
++ public static final int PRIORITY_NORMAL = 0;
++ public static final int PRIORITY_LOW = -10;
++ public static final int PRIORITY_VERY_LOW = -20;
++
++ private static final String ANNOTATION_MAPPER_TYPE = "com.thoughtworks.xstream.mapper.AnnotationMapper";
++ private static final Pattern IGNORE_ALL = Pattern.compile(".*");
++
++ /**
++ * Constructs a default XStream. The instance will use the {@link XppDriver} as default and
++ * tries to determine the best match for the {@link ReflectionProvider} on its own.
++ *
++ * @throws InitializationException in case of an initialization problem
++ */
++ public XStream() {
++ this(null, (Mapper)null, new XppDriver());
++ }
++
++ /**
++ * Constructs an XStream with a special {@link ReflectionProvider}. The instance will use
++ * the {@link XppDriver} as default.
++ *
++ * @throws InitializationException in case of an initialization problem
++ */
++ public XStream(ReflectionProvider reflectionProvider) {
++ this(reflectionProvider, (Mapper)null, new XppDriver());
++ }
++
++ /**
++ * Constructs an XStream with a special {@link HierarchicalStreamDriver}. The instance will
++ * tries to determine the best match for the {@link ReflectionProvider} on its own.
++ *
++ * @throws InitializationException in case of an initialization problem
++ */
++ public XStream(HierarchicalStreamDriver hierarchicalStreamDriver) {
++ this(null, (Mapper)null, hierarchicalStreamDriver);
++ }
++
++ /**
++ * Constructs an XStream with a special {@link HierarchicalStreamDriver} and
++ * {@link ReflectionProvider}.
++ *
++ * @throws InitializationException in case of an initialization problem
++ */
++ public XStream(
++ ReflectionProvider reflectionProvider, HierarchicalStreamDriver hierarchicalStreamDriver) {
++ this(reflectionProvider, (Mapper)null, hierarchicalStreamDriver);
++ }
++
++ /**
++ * Constructs an XStream with a special {@link HierarchicalStreamDriver} and
++ * {@link ReflectionProvider} and additionally with a prepared {@link Mapper}.
++ *
++ * @throws InitializationException in case of an initialization problem
++ * @deprecated As of 1.3, use
++ * {@link #XStream(ReflectionProvider, HierarchicalStreamDriver, ClassLoader, Mapper)}
++ * instead
++ */
++ public XStream(
++ ReflectionProvider reflectionProvider, Mapper mapper, HierarchicalStreamDriver driver) {
++ this(
++ reflectionProvider, driver, new ClassLoaderReference(new CompositeClassLoader()),
++ mapper, new DefaultConverterLookup(), null);
++ }
++
++ /**
++ * Constructs an XStream with a special {@link HierarchicalStreamDriver} and
++ * {@link ReflectionProvider} and additionally with a prepared {@link ClassLoader} to use.
++ *
++ * @throws InitializationException in case of an initialization problem
++ * @since 1.3
++ */
++ public XStream(
++ ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver,
++ ClassLoader classLoader) {
++ this(reflectionProvider, driver, classLoader, null);
++ }
++
++ /**
++ * Constructs an XStream with a special {@link HierarchicalStreamDriver} and
++ * {@link ReflectionProvider} and additionally with a prepared {@link Mapper} and the
++ * {@link ClassLoader} in use.
++ * <p>
++ * Note, if the class loader should be changed later again, you should provide a
++ * {@link ClassLoaderReference} as {@link ClassLoader} that is also use in the
++ * {@link Mapper} chain.
++ * </p>
++ *
++ * @throws InitializationException in case of an initialization problem
++ * @since 1.3
++ */
++ public XStream(
++ ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver,
++ ClassLoader classLoader, Mapper mapper) {
++ this(
++ reflectionProvider, driver, classLoader, mapper, new DefaultConverterLookup(), null);
++ }
++
++ /**
++ * Constructs an XStream with a special {@link HierarchicalStreamDriver},
++ * {@link ReflectionProvider}, a prepared {@link Mapper} and the {@link ClassLoader} in use
++ * and an own {@link ConverterRegistry}.
++ * <p>
++ * Note, if the class loader should be changed later again, you should provide a
++ * {@link ClassLoaderReference} as {@link ClassLoader} that is also use in the
++ * {@link Mapper} chain.
++ * </p>
++ *
++ * @throws InitializationException in case of an initialization problem
++ * @since 1.3
++ */
++ public XStream(
++ ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver,
++ ClassLoader classLoader, Mapper mapper, ConverterLookup converterLookup,
++ ConverterRegistry converterRegistry) {
++ jvm = new JVM();
++ if (reflectionProvider == null) {
++ reflectionProvider = jvm.bestReflectionProvider();
++ }
++ this.reflectionProvider = reflectionProvider;
++ this.hierarchicalStreamDriver = driver;
++ this.classLoaderReference = classLoader instanceof ClassLoaderReference
++ ? (ClassLoaderReference)classLoader
++ : new ClassLoaderReference(classLoader);
++ this.converterLookup = converterLookup;
++ this.converterRegistry = converterRegistry != null
++ ? converterRegistry
++ : (converterLookup instanceof ConverterRegistry
++ ? (ConverterRegistry)converterLookup
++ : null);
++ this.mapper = mapper == null ? buildMapper() : mapper;
++
++ setupMappers();
++ setupAliases();
++ setupDefaultImplementations();
++ setupConverters();
++ setupImmutableTypes();
++ setMode(XPATH_RELATIVE_REFERENCES);
++ }
++
++ private Mapper buildMapper() {
++ Mapper mapper = new DefaultMapper(classLoaderReference);
++ if (useXStream11XmlFriendlyMapper()) {
++ mapper = new XStream11XmlFriendlyMapper(mapper);
++ }
++ mapper = new DynamicProxyMapper(mapper);
++ mapper = new PackageAliasingMapper(mapper);
++ mapper = new ClassAliasingMapper(mapper);
++ mapper = new FieldAliasingMapper(mapper);
++ mapper = new AttributeAliasingMapper(mapper);
++ mapper = new SystemAttributeAliasingMapper(mapper);
++ mapper = new ImplicitCollectionMapper(mapper);
++ mapper = new OuterClassMapper(mapper);
++ mapper = new ArrayMapper(mapper);
++ mapper = new DefaultImplementationsMapper(mapper);
++ mapper = new AttributeMapper(mapper, converterLookup, reflectionProvider);
++ if (JVM.is15()) {
++ mapper = buildMapperDynamically(
++ "com.thoughtworks.xstream.mapper.EnumMapper", new Class[]{Mapper.class},
++ new Object[]{mapper});
++ }
++ mapper = new LocalConversionMapper(mapper);
++ mapper = new ImmutableTypesMapper(mapper);
++ if (JVM.is15()) {
++ mapper = buildMapperDynamically(ANNOTATION_MAPPER_TYPE, new Class[]{
++ Mapper.class, ConverterRegistry.class, ConverterLookup.class,
++ ClassLoader.class, ReflectionProvider.class, JVM.class}, new Object[]{
++ mapper, converterLookup, converterLookup, classLoaderReference,
++ reflectionProvider, jvm});
++ }
++ mapper = wrapMapper((MapperWrapper)mapper);
++ mapper = new CachingMapper(mapper);
++ return mapper;
++ }
++
++ private Mapper buildMapperDynamically(String className, Class[] constructorParamTypes,
++ Object[] constructorParamValues) {
++ try {
++ Class type = Class.forName(className, false, classLoaderReference.getReference());
++ Constructor constructor = type.getConstructor(constructorParamTypes);
++ return (Mapper)constructor.newInstance(constructorParamValues);
++ } catch (Exception e) {
++ throw new com.thoughtworks.xstream.InitializationException(
++ "Could not instantiate mapper : " + className, e);
++ }
++ }
++
++ protected MapperWrapper wrapMapper(MapperWrapper next) {
++ return next;
++ }
++
++ protected boolean useXStream11XmlFriendlyMapper() {
++ return false;
++ }
++
++ private void setupMappers() {
++ packageAliasingMapper = (PackageAliasingMapper)this.mapper
++ .lookupMapperOfType(PackageAliasingMapper.class);
++ classAliasingMapper = (ClassAliasingMapper)this.mapper
++ .lookupMapperOfType(ClassAliasingMapper.class);
++ fieldAliasingMapper = (FieldAliasingMapper)this.mapper
++ .lookupMapperOfType(FieldAliasingMapper.class);
++ attributeMapper = (AttributeMapper)this.mapper
++ .lookupMapperOfType(AttributeMapper.class);
++ attributeAliasingMapper = (AttributeAliasingMapper)this.mapper
++ .lookupMapperOfType(AttributeAliasingMapper.class);
++ systemAttributeAliasingMapper = (SystemAttributeAliasingMapper)this.mapper
++ .lookupMapperOfType(SystemAttributeAliasingMapper.class);
++ implicitCollectionMapper = (ImplicitCollectionMapper)this.mapper
++ .lookupMapperOfType(ImplicitCollectionMapper.class);
++ defaultImplementationsMapper = (DefaultImplementationsMapper)this.mapper
++ .lookupMapperOfType(DefaultImplementationsMapper.class);
++ immutableTypesMapper = (ImmutableTypesMapper)this.mapper
++ .lookupMapperOfType(ImmutableTypesMapper.class);
++ localConversionMapper = (LocalConversionMapper)this.mapper
++ .lookupMapperOfType(LocalConversionMapper.class);
++ annotationConfiguration = (AnnotationConfiguration)this.mapper
++ .lookupMapperOfType(AnnotationConfiguration.class);
++ }
++
++ protected void setupAliases() {
++ if (classAliasingMapper == null) {
++ return;
++ }
++
++ alias("null", Mapper.Null.class);
++ alias("int", Integer.class);
++ alias("float", Float.class);
++ alias("double", Double.class);
++ alias("long", Long.class);
++ alias("short", Short.class);
++ alias("char", Character.class);
++ alias("byte", Byte.class);
++ alias("boolean", Boolean.class);
++ alias("number", Number.class);
++ alias("object", Object.class);
++ alias("big-int", BigInteger.class);
++ alias("big-decimal", BigDecimal.class);
++
++ alias("string-buffer", StringBuffer.class);
++ alias("string", String.class);
++ alias("java-class", Class.class);
++ alias("method", Method.class);
++ alias("constructor", Constructor.class);
++ alias("field", Field.class);
++ alias("date", Date.class);
++ alias("uri", URI.class);
++ alias("url", URL.class);
++ alias("bit-set", BitSet.class);
++
++ alias("map", Map.class);
++ alias("entry", Map.Entry.class);
++ alias("properties", Properties.class);
++ alias("list", List.class);
++ alias("set", Set.class);
++ alias("sorted-set", SortedSet.class);
++
++ alias("linked-list", LinkedList.class);
++ alias("vector", Vector.class);
++ alias("tree-map", TreeMap.class);
++ alias("tree-set", TreeSet.class);
++ alias("hashtable", Hashtable.class);
++
++ alias("empty-list", Collections.EMPTY_LIST.getClass());
++ alias("empty-map", Collections.EMPTY_MAP.getClass());
++ alias("empty-set", Collections.EMPTY_SET.getClass());
++ alias("singleton-list", Collections.singletonList(this).getClass());
++ alias("singleton-map", Collections.singletonMap(this, null).getClass());
++ alias("singleton-set", Collections.singleton(this).getClass());
++
++ if (jvm.supportsAWT()) {
++ // Instantiating these two classes starts the AWT system, which is undesirable.
++ // Calling loadClass ensures a reference to the class is found but they are not
++ // instantiated.
++ alias("awt-color", jvm.loadClass("java.awt.Color"));
++ alias("awt-font", jvm.loadClass("java.awt.Font"));
++ alias("awt-text-attribute", jvm.loadClass("java.awt.font.TextAttribute"));
++ }
++
++ if (jvm.supportsSQL()) {
++ alias("sql-timestamp", jvm.loadClass("java.sql.Timestamp"));
++ alias("sql-time", jvm.loadClass("java.sql.Time"));
++ alias("sql-date", jvm.loadClass("java.sql.Date"));
++ }
++
++ alias("file", File.class);
++ alias("locale", Locale.class);
++ alias("gregorian-calendar", Calendar.class);
++
++ if (JVM.is14()) {
++ aliasDynamically("auth-subject", "javax.security.auth.Subject");
++ alias("linked-hash-map", jvm.loadClass("java.util.LinkedHashMap"));
++ alias("linked-hash-set", jvm.loadClass("java.util.LinkedHashSet"));
++ alias("trace", jvm.loadClass("java.lang.StackTraceElement"));
++ alias("currency", jvm.loadClass("java.util.Currency"));
++ aliasType("charset", jvm.loadClass("java.nio.charset.Charset"));
++ }
++
++ if (JVM.is15()) {
++ aliasDynamically("duration", "javax.xml.datatype.Duration");
++ alias("enum-set", jvm.loadClass("java.util.EnumSet"));
++ alias("enum-map", jvm.loadClass("java.util.EnumMap"));
++ alias("string-builder", jvm.loadClass("java.lang.StringBuilder"));
++ alias("uuid", jvm.loadClass("java.util.UUID"));
++ }
++ }
++
++ private void aliasDynamically(String alias, String className) {
++ Class type = jvm.loadClass(className);
++ if (type != null) {
++ alias(alias, type);
++ }
++ }
++
++ protected void setupDefaultImplementations() {
++ if (defaultImplementationsMapper == null) {
++ return;
++ }
++ addDefaultImplementation(HashMap.class, Map.class);
++ addDefaultImplementation(ArrayList.class, List.class);
++ addDefaultImplementation(HashSet.class, Set.class);
++ addDefaultImplementation(TreeSet.class, SortedSet.class);
++ addDefaultImplementation(GregorianCalendar.class, Calendar.class);
++ }
++
++ protected void setupConverters() {
++ final ReflectionConverter reflectionConverter = new ReflectionConverter(
++ mapper, reflectionProvider);
++ registerConverter(reflectionConverter, PRIORITY_VERY_LOW);
++
++ registerConverter(
++ new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW);
++ registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW);
++
++ registerConverter(new NullConverter(), PRIORITY_VERY_HIGH);
++ registerConverter(new IntConverter(), PRIORITY_NORMAL);
++ registerConverter(new FloatConverter(), PRIORITY_NORMAL);
++ registerConverter(new DoubleConverter(), PRIORITY_NORMAL);
++ registerConverter(new LongConverter(), PRIORITY_NORMAL);
++ registerConverter(new ShortConverter(), PRIORITY_NORMAL);
++ registerConverter((Converter)new CharConverter(), PRIORITY_NORMAL);
++ registerConverter(new BooleanConverter(), PRIORITY_NORMAL);
++ registerConverter(new ByteConverter(), PRIORITY_NORMAL);
++
++ registerConverter(new StringConverter(), PRIORITY_NORMAL);
++ registerConverter(new StringBufferConverter(), PRIORITY_NORMAL);
++ registerConverter(new DateConverter(), PRIORITY_NORMAL);
++ registerConverter(new BitSetConverter(), PRIORITY_NORMAL);
++ registerConverter(new URIConverter(), PRIORITY_NORMAL);
++ registerConverter(new URLConverter(), PRIORITY_NORMAL);
++ registerConverter(new BigIntegerConverter(), PRIORITY_NORMAL);
++ registerConverter(new BigDecimalConverter(), PRIORITY_NORMAL);
++
++ registerConverter(new ArrayConverter(mapper), PRIORITY_NORMAL);
++ registerConverter(new CharArrayConverter(), PRIORITY_NORMAL);
++ registerConverter(new CollectionConverter(mapper), PRIORITY_NORMAL);
++ registerConverter(new MapConverter(mapper), PRIORITY_NORMAL);
++ registerConverter(new TreeMapConverter(mapper), PRIORITY_NORMAL);
++ registerConverter(new TreeSetConverter(mapper), PRIORITY_NORMAL);
++ registerConverter(new SingletonCollectionConverter(mapper), PRIORITY_NORMAL);
++ registerConverter(new SingletonMapConverter(mapper), PRIORITY_NORMAL);
++ registerConverter(new PropertiesConverter(), PRIORITY_NORMAL);
++ registerConverter((Converter)new EncodedByteArrayConverter(), PRIORITY_NORMAL);
++
++ registerConverter(new FileConverter(), PRIORITY_NORMAL);
++ if (jvm.supportsSQL()) {
++ registerConverter(new SqlTimestampConverter(), PRIORITY_NORMAL);
++ registerConverter(new SqlTimeConverter(), PRIORITY_NORMAL);
++ registerConverter(new SqlDateConverter(), PRIORITY_NORMAL);
++ }
++ registerConverter(
++ new DynamicProxyConverter(mapper, classLoaderReference), PRIORITY_NORMAL);
++ registerConverter(new JavaClassConverter(classLoaderReference), PRIORITY_NORMAL);
++ registerConverter(new JavaMethodConverter(classLoaderReference), PRIORITY_NORMAL);
++ registerConverter(new JavaFieldConverter(classLoaderReference), PRIORITY_NORMAL);
++ if (jvm.supportsAWT()) {
++ registerConverter(new FontConverter(), PRIORITY_NORMAL);
++ registerConverter(new ColorConverter(), PRIORITY_NORMAL);
++ registerConverter(new TextAttributeConverter(), PRIORITY_NORMAL);
++ }
++ if (jvm.supportsSwing()) {
++ registerConverter(
++ new LookAndFeelConverter(mapper, reflectionProvider), PRIORITY_NORMAL);
++ }
++ registerConverter(new LocaleConverter(), PRIORITY_NORMAL);
++ registerConverter(new GregorianCalendarConverter(), PRIORITY_NORMAL);
++
++ if (JVM.is14()) {
++ // late bound converters - allows XStream to be compiled on earlier JDKs
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.extended.SubjectConverter",
++ PRIORITY_NORMAL, new Class[]{Mapper.class}, new Object[]{mapper});
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.extended.ThrowableConverter",
++ PRIORITY_NORMAL, new Class[]{Converter.class},
++ new Object[]{reflectionConverter});
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.extended.StackTraceElementConverter",
++ PRIORITY_NORMAL, null, null);
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.extended.CurrencyConverter",
++ PRIORITY_NORMAL, null, null);
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.extended.RegexPatternConverter",
++ PRIORITY_NORMAL, new Class[]{Converter.class},
++ new Object[]{reflectionConverter});
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.extended.CharsetConverter",
++ PRIORITY_NORMAL, null, null);
++ }
++
++ if (JVM.is15()) {
++ // late bound converters - allows XStream to be compiled on earlier JDKs
++ if (jvm.loadClass("javax.xml.datatype.Duration") != null) {
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.extended.DurationConverter",
++ PRIORITY_NORMAL, null, null);
++ }
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.enums.EnumConverter", PRIORITY_NORMAL,
++ null, null);
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.enums.EnumSetConverter", PRIORITY_NORMAL,
++ new Class[]{Mapper.class}, new Object[]{mapper});
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.enums.EnumMapConverter", PRIORITY_NORMAL,
++ new Class[]{Mapper.class}, new Object[]{mapper});
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.basic.StringBuilderConverter",
++ PRIORITY_NORMAL, null, null);
++ registerConverterDynamically(
++ "com.thoughtworks.xstream.converters.basic.UUIDConverter", PRIORITY_NORMAL,
++ null, null);
++ }
++
++ registerConverter(
++ new SelfStreamingInstanceChecker(reflectionConverter, this), PRIORITY_NORMAL);
++ }
++
++ private void registerConverterDynamically(String className, int priority,
++ Class[] constructorParamTypes, Object[] constructorParamValues) {
++ try {
++ Class type = Class.forName(className, false, classLoaderReference.getReference());
++ Constructor constructor = type.getConstructor(constructorParamTypes);
++ Object instance = constructor.newInstance(constructorParamValues);
++ if (instance instanceof Converter) {
++ registerConverter((Converter)instance, priority);
++ } else if (instance instanceof SingleValueConverter) {
++ registerConverter((SingleValueConverter)instance, priority);
++ }
++ } catch (Exception e) {
++ throw new com.thoughtworks.xstream.InitializationException(
++ "Could not instantiate converter : " + className, e);
++ }
++ }
++
++ protected void setupImmutableTypes() {
++ if (immutableTypesMapper == null) {
++ return;
++ }
++
++ // primitives are always immutable
++ addImmutableType(boolean.class);
++ addImmutableType(Boolean.class);
++ addImmutableType(byte.class);
++ addImmutableType(Byte.class);
++ addImmutableType(char.class);
++ addImmutableType(Character.class);
++ addImmutableType(double.class);
++ addImmutableType(Double.class);
++ addImmutableType(float.class);
++ addImmutableType(Float.class);
++ addImmutableType(int.class);
++ addImmutableType(Integer.class);
++ addImmutableType(long.class);
++ addImmutableType(Long.class);
++ addImmutableType(short.class);
++ addImmutableType(Short.class);
++
++ // additional types
++ addImmutableType(Mapper.Null.class);
++ addImmutableType(BigDecimal.class);
++ addImmutableType(BigInteger.class);
++ addImmutableType(String.class);
++ addImmutableType(URI.class);
++ addImmutableType(URL.class);
++ addImmutableType(File.class);
++ addImmutableType(Class.class);
++
++ addImmutableType(Collections.EMPTY_LIST.getClass());
++ addImmutableType(Collections.EMPTY_SET.getClass());
++ addImmutableType(Collections.EMPTY_MAP.getClass());
++
++ if (jvm.supportsAWT()) {
++ addImmutableTypeDynamically("java.awt.font.TextAttribute");
++ }
++
++ if (JVM.is14()) {
++ // late bound types - allows XStream to be compiled on earlier JDKs
++ addImmutableTypeDynamically("java.nio.charset.Charset");
++ addImmutableTypeDynamically("java.util.Currency");
++ }
++ }
++
++ private void addImmutableTypeDynamically(String className) {
++ Class type = jvm.loadClass(className);
++ if (type != null) {
++ addImmutableType(type);
++ }
++ }
++
++ public void setMarshallingStrategy(MarshallingStrategy marshallingStrategy) {
++ this.marshallingStrategy = marshallingStrategy;
++ }
++
++ /**
++ * Serialize an object to a pretty-printed XML String.
++ *
++ * @throws XStreamException if the object cannot be serialized
++ */
++ public String toXML(Object obj) {
++ Writer writer = new StringWriter();
++ toXML(obj, writer);
++ return writer.toString();
++ }
++
++ /**
++ * Serialize an object to the given Writer as pretty-printed XML. The Writer will be flushed
++ * afterwards and in case of an exception.
++ *
++ * @throws XStreamException if the object cannot be serialized
++ */
++ public void toXML(Object obj, Writer out) {
++ HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out);
++ try {
++ marshal(obj, writer);
++ } finally {
++ writer.flush();
++ }
++ }
++
++ /**
++ * Serialize an object to the given OutputStream as pretty-printed XML. The OutputStream
++ * will be flushed afterwards and in case of an exception.
++ *
++ * @throws XStreamException if the object cannot be serialized
++ */
++ public void toXML(Object obj, OutputStream out) {
++ HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out);
++ try {
++ marshal(obj, writer);
++ } finally {
++ writer.flush();
++ }
++ }
++
++ /**
++ * Serialize and object to a hierarchical data structure (such as XML).
++ *
++ * @throws XStreamException if the object cannot be serialized
++ */
++ public void marshal(Object obj, HierarchicalStreamWriter writer) {
++ marshal(obj, writer, null);
++ }
++
++ /**
++ * Serialize and object to a hierarchical data structure (such as XML).
++ *
++ * @param dataHolder Extra data you can use to pass to your converters. Use this as you
++ * want. If not present, XStream shall create one lazily as needed.
++ * @throws XStreamException if the object cannot be serialized
++ */
++ public void marshal(Object obj, HierarchicalStreamWriter writer, DataHolder dataHolder) {
++ marshallingStrategy.marshal(writer, obj, converterLookup, mapper, dataHolder);
++ }
++
++ /**
++ * Deserialize an object from an XML String.
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object fromXML(String xml) {
++ return fromXML(new StringReader(xml));
++ }
++
++ /**
++ * Deserialize an object from an XML Reader.
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object fromXML(Reader reader) {
++ return unmarshal(hierarchicalStreamDriver.createReader(reader), null);
++ }
++
++ /**
++ * Deserialize an object from an XML InputStream.
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object fromXML(InputStream input) {
++ return unmarshal(hierarchicalStreamDriver.createReader(input), null);
++ }
++
++ /**
++ * Deserialize an object from a URL.
++ *
++ * Depending on the parser implementation, some might take the file path as SystemId to
++ * resolve additional references.
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ * @since 1.4
++ */
++ public Object fromXML(URL url) {
++ return unmarshal(hierarchicalStreamDriver.createReader(url), null);
++ }
++
++ /**
++ * Deserialize an object from a file.
++ *
++ * Depending on the parser implementation, some might take the file path as SystemId to
++ * resolve additional references.
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ * @since 1.4
++ */
++ public Object fromXML(File file) {
++ return unmarshal(hierarchicalStreamDriver.createReader(file), null);
++ }
++
++ /**
++ * Deserialize an object from an XML String, populating the fields of the given root object
++ * instead of instantiating a new one. Note, that this is a special use case! With the
++ * ReflectionConverter XStream will write directly into the raw memory area of the existing
++ * object. Use with care!
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object fromXML(String xml, Object root) {
++ return fromXML(new StringReader(xml), root);
++ }
++
++ /**
++ * Deserialize an object from an XML Reader, populating the fields of the given root object
++ * instead of instantiating a new one. Note, that this is a special use case! With the
++ * ReflectionConverter XStream will write directly into the raw memory area of the existing
++ * object. Use with care!
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object fromXML(Reader xml, Object root) {
++ return unmarshal(hierarchicalStreamDriver.createReader(xml), root);
++ }
++
++ /**
++ * Deserialize an object from a URL, populating the fields of the given root
++ * object instead of instantiating a new one. Note, that this is a special use case! With
++ * the ReflectionConverter XStream will write directly into the raw memory area of the
++ * existing object. Use with care!
++ *
++ * Depending on the parser implementation, some might take the file path as SystemId to
++ * resolve additional references.
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ * @since 1.4
++ */
++ public Object fromXML(URL url, Object root) {
++ return unmarshal(hierarchicalStreamDriver.createReader(url), root);
++ }
++
++ /**
++ * Deserialize an object from a file, populating the fields of the given root
++ * object instead of instantiating a new one. Note, that this is a special use case! With
++ * the ReflectionConverter XStream will write directly into the raw memory area of the
++ * existing object. Use with care!
++ *
++ * Depending on the parser implementation, some might take the file path as SystemId to
++ * resolve additional references.
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ * @since 1.4
++ */
++ public Object fromXML(File file, Object root) {
++ return unmarshal(hierarchicalStreamDriver.createReader(file), root);
++ }
++
++ /**
++ * Deserialize an object from an XML InputStream, populating the fields of the given root
++ * object instead of instantiating a new one. Note, that this is a special use case! With
++ * the ReflectionConverter XStream will write directly into the raw memory area of the
++ * existing object. Use with care!
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object fromXML(InputStream input, Object root) {
++ return unmarshal(hierarchicalStreamDriver.createReader(input), root);
++ }
++
++ /**
++ * Deserialize an object from a hierarchical data structure (such as XML).
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object unmarshal(HierarchicalStreamReader reader) {
++ return unmarshal(reader, null, null);
++ }
++
++ /**
++ * Deserialize an object from a hierarchical data structure (such as XML), populating the
++ * fields of the given root object instead of instantiating a new one. Note, that this is a
++ * special use case! With the ReflectionConverter XStream will write directly into the raw
++ * memory area of the existing object. Use with care!
++ *
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object unmarshal(HierarchicalStreamReader reader, Object root) {
++ return unmarshal(reader, root, null);
++ }
++
++ /**
++ * Deserialize an object from a hierarchical data structure (such as XML).
++ *
++ * @param root If present, the passed in object will have its fields populated, as opposed
++ * to XStream creating a new instance. Note, that this is a special use case!
++ * With the ReflectionConverter XStream will write directly into the raw memory
++ * area of the existing object. Use with care!
++ * @param dataHolder Extra data you can use to pass to your converters. Use this as you
++ * want. If not present, XStream shall create one lazily as needed.
++ * @throws XStreamException if the object cannot be deserialized
++ */
++ public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) {
++ try {
++ return marshallingStrategy.unmarshal(
++ root, reader, dataHolder, converterLookup, mapper);
++
++ } catch (ConversionException e) {
++ Package pkg = getClass().getPackage();
++ e.add("version", pkg != null ? pkg.getImplementationVersion() : "not available");
++ throw e;
++ }
++ }
++
++ /**
++ * Alias a Class to a shorter name to be used in XML elements.
++ *
++ * @param name Short name
++ * @param type Type to be aliased
++ * @throws InitializationException if no {@link ClassAliasingMapper} is available
++ */
++ public void alias(String name, Class type) {
++ if (classAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + ClassAliasingMapper.class.getName()
++ + " available");
++ }
++ classAliasingMapper.addClassAlias(name, type);
++ }
++
++ /**
++ * Alias a type to a shorter name to be used in XML elements. Any class that is assignable
++ * to this type will be aliased to the same name.
++ *
++ * @param name Short name
++ * @param type Type to be aliased
++ * @since 1.2
++ * @throws InitializationException if no {@link ClassAliasingMapper} is available
++ */
++ public void aliasType(String name, Class type) {
++ if (classAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + ClassAliasingMapper.class.getName()
++ + " available");
++ }
++ classAliasingMapper.addTypeAlias(name, type);
++ }
++
++ /**
++ * Alias a Class to a shorter name to be used in XML elements.
++ *
++ * @param name Short name
++ * @param type Type to be aliased
++ * @param defaultImplementation Default implementation of type to use if no other specified.
++ * @throws InitializationException if no {@link DefaultImplementationsMapper} or no
++ * {@link ClassAliasingMapper} is available
++ */
++ public void alias(String name, Class type, Class defaultImplementation) {
++ alias(name, type);
++ addDefaultImplementation(defaultImplementation, type);
++ }
++
++ /**
++ * Alias a package to a shorter name to be used in XML elements.
++ *
++ * @param name Short name
++ * @param pkgName package to be aliased
++ * @throws InitializationException if no {@link DefaultImplementationsMapper} or no
++ * {@link PackageAliasingMapper} is available
++ * @since 1.3.1
++ */
++ public void aliasPackage(String name, String pkgName) {
++ if (packageAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + PackageAliasingMapper.class.getName()
++ + " available");
++ }
++ packageAliasingMapper.addPackageAlias(name, pkgName);
++ }
++
++ /**
++ * Create an alias for a field name.
++ *
++ * @param alias the alias itself
++ * @param definedIn the type that declares the field
++ * @param fieldName the name of the field
++ * @throws InitializationException if no {@link FieldAliasingMapper} is available
++ */
++ public void aliasField(String alias, Class definedIn, String fieldName) {
++ if (fieldAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + FieldAliasingMapper.class.getName()
++ + " available");
++ }
++ fieldAliasingMapper.addFieldAlias(alias, definedIn, fieldName);
++ }
++
++ /**
++ * Create an alias for an attribute
++ *
++ * @param alias the alias itself
++ * @param attributeName the name of the attribute
++ * @throws InitializationException if no {@link AttributeAliasingMapper} is available
++ */
++ public void aliasAttribute(String alias, String attributeName) {
++ if (attributeAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + AttributeAliasingMapper.class.getName()
++ + " available");
++ }
++ attributeAliasingMapper.addAliasFor(attributeName, alias);
++ }
++
++ /**
++ * Create an alias for a system attribute. XStream will not write a system attribute if its
++ * alias is set to <code>null</code>. However, this is not reversible, i.e. deserialization
++ * of the result is likely to fail afterwards and will not produce an object equal to the
++ * originally written one.
++ *
++ * @param alias the alias itself (may be <code>null</code>)
++ * @param systemAttributeName the name of the system attribute
++ * @throws InitializationException if no {@link SystemAttributeAliasingMapper} is available
++ * @since 1.3.1
++ */
++ public void aliasSystemAttribute(String alias, String systemAttributeName) {
++ if (systemAttributeAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + SystemAttributeAliasingMapper.class.getName()
++ + " available");
++ }
++ systemAttributeAliasingMapper.addAliasFor(systemAttributeName, alias);
++ }
++
++ /**
++ * Create an alias for an attribute.
++ *
++ * @param definedIn the type where the attribute is defined
++ * @param attributeName the name of the attribute
++ * @param alias the alias itself
++ * @throws InitializationException if no {@link AttributeAliasingMapper} is available
++ * @since 1.2.2
++ */
++ public void aliasAttribute(Class definedIn, String attributeName, String alias) {
++ aliasField(alias, definedIn, attributeName);
++ useAttributeFor(definedIn, attributeName);
++ }
++
++ /**
++ * Use an attribute for a field or a specific type.
++ *
++ * @param fieldName the name of the field
++ * @param type the Class of the type to be rendered as XML attribute
++ * @throws InitializationException if no {@link AttributeMapper} is available
++ * @since 1.2
++ */
++ public void useAttributeFor(String fieldName, Class type) {
++ if (attributeMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + AttributeMapper.class.getName()
++ + " available");
++ }
++ attributeMapper.addAttributeFor(fieldName, type);
++ }
++
++ /**
++ * Use an attribute for a field declared in a specific type.
++ *
++ * @param fieldName the name of the field
++ * @param definedIn the Class containing such field
++ * @throws InitializationException if no {@link AttributeMapper} is available
++ * @since 1.2.2
++ */
++ public void useAttributeFor(Class definedIn, String fieldName) {
++ if (attributeMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + AttributeMapper.class.getName()
++ + " available");
++ }
++ attributeMapper.addAttributeFor(definedIn, fieldName);
++ }
++
++ /**
++ * Use an attribute for an arbitrary type.
++ *
++ * @param type the Class of the type to be rendered as XML attribute
++ * @throws InitializationException if no {@link AttributeMapper} is available
++ * @since 1.2
++ */
++ public void useAttributeFor(Class type) {
++ if (attributeMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + AttributeMapper.class.getName()
++ + " available");
++ }
++ attributeMapper.addAttributeFor(type);
++ }
++
++ /**
++ * Associate a default implementation of a class with an object. Whenever XStream encounters
++ * an instance of this type, it will use the default implementation instead. For example,
++ * java.util.ArrayList is the default implementation of java.util.List.
++ *
++ * @param defaultImplementation
++ * @param ofType
++ * @throws InitializationException if no {@link DefaultImplementationsMapper} is available
++ */
++ public void addDefaultImplementation(Class defaultImplementation, Class ofType) {
++ if (defaultImplementationsMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + DefaultImplementationsMapper.class.getName()
++ + " available");
++ }
++ defaultImplementationsMapper.addDefaultImplementation(defaultImplementation, ofType);
++ }
++
++ /**
++ * Add immutable types. The value of the instances of these types will always be written
++ * into the stream even if they appear multiple times.
++ *
++ * @throws InitializationException if no {@link ImmutableTypesMapper} is available
++ */
++ public void addImmutableType(Class type) {
++ if (immutableTypesMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + ImmutableTypesMapper.class.getName()
++ + " available");
++ }
++ immutableTypesMapper.addImmutableType(type);
++ }
++
++ public void registerConverter(Converter converter) {
++ registerConverter(converter, PRIORITY_NORMAL);
++ }
++
++ public void registerConverter(Converter converter, int priority) {
++ if (converterRegistry != null) {
++ converterRegistry.registerConverter(converter, priority);
++ }
++ }
++
++ public void registerConverter(SingleValueConverter converter) {
++ registerConverter(converter, PRIORITY_NORMAL);
++ }
++
++ public void registerConverter(SingleValueConverter converter, int priority) {
++ if (converterRegistry != null) {
++ converterRegistry.registerConverter(
++ new SingleValueConverterWrapper(converter), priority);
++ }
++ }
++
++ /**
++ * Register a local {@link Converter} for a field.
++ *
++ * @param definedIn the class type the field is defined in
++ * @param fieldName the field name
++ * @param converter the converter to use
++ * @since 1.3
++ */
++ public void registerLocalConverter(Class definedIn, String fieldName, Converter converter) {
++ if (localConversionMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + LocalConversionMapper.class.getName()
++ + " available");
++ }
++ localConversionMapper.registerLocalConverter(definedIn, fieldName, converter);
++ }
++
++ /**
++ * Register a local {@link SingleValueConverter} for a field.
++ *
++ * @param definedIn the class type the field is defined in
++ * @param fieldName the field name
++ * @param converter the converter to use
++ * @since 1.3
++ */
++ public void registerLocalConverter(Class definedIn, String fieldName,
++ SingleValueConverter converter) {
++ registerLocalConverter(
++ definedIn, fieldName, (Converter)new SingleValueConverterWrapper(converter));
++ }
++
++ /**
++ * Retrieve the {@link Mapper}. This is by default a chain of {@link MapperWrapper
++ * MapperWrappers}.
++ *
++ * @return the mapper
++ * @since 1.2
++ */
++ public Mapper getMapper() {
++ return mapper;
++ }
++
++ /**
++ * Retrieve the {@link ReflectionProvider} in use.
++ *
++ * @return the mapper
++ * @since 1.2.1
++ */
++ public ReflectionProvider getReflectionProvider() {
++ return reflectionProvider;
++ }
++
++ public ConverterLookup getConverterLookup() {
++ return converterLookup;
++ }
++
++ /**
++ * Change mode for dealing with duplicate references. Valid values are
++ * <code>XPATH_ABSOLUTE_REFERENCES</code>, <code>XPATH_RELATIVE_REFERENCES</code>,
++ * <code>XStream.ID_REFERENCES</code> and <code>XStream.NO_REFERENCES</code>.
++ *
++ * @throws IllegalArgumentException if the mode is not one of the declared types
++ * @see #XPATH_ABSOLUTE_REFERENCES
++ * @see #XPATH_RELATIVE_REFERENCES
++ * @see #ID_REFERENCES
++ * @see #NO_REFERENCES
++ */
++ public void setMode(int mode) {
++ switch (mode) {
++ case NO_REFERENCES:
++ setMarshallingStrategy(new TreeMarshallingStrategy());
++ break;
++ case ID_REFERENCES:
++ setMarshallingStrategy(new ReferenceByIdMarshallingStrategy());
++ break;
++ case XPATH_RELATIVE_REFERENCES:
++ setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
++ ReferenceByXPathMarshallingStrategy.RELATIVE));
++ break;
++ case XPATH_ABSOLUTE_REFERENCES:
++ setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
++ ReferenceByXPathMarshallingStrategy.ABSOLUTE));
++ break;
++ case SINGLE_NODE_XPATH_RELATIVE_REFERENCES:
++ setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
++ ReferenceByXPathMarshallingStrategy.RELATIVE
++ | ReferenceByXPathMarshallingStrategy.SINGLE_NODE));
++ break;
++ case SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES:
++ setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy(
++ ReferenceByXPathMarshallingStrategy.ABSOLUTE
++ | ReferenceByXPathMarshallingStrategy.SINGLE_NODE));
++ break;
++ default:
++ throw new IllegalArgumentException("Unknown mode : " + mode);
++ }
++ }
++
++ /**
++ * Adds a default implicit collection which is used for any unmapped XML tag.
++ *
++ * @param ownerType class owning the implicit collection
++ * @param fieldName name of the field in the ownerType. This field must be a concrete
++ * collection type or matching the default implementation type of the collection
++ * type.
++ */
++ public void addImplicitCollection(Class ownerType, String fieldName) {
++ addImplicitCollection(ownerType, fieldName, null, null);
++ }
++
++ /**
++ * Adds implicit collection which is used for all items of the given itemType.
++ *
++ * @param ownerType class owning the implicit collection
++ * @param fieldName name of the field in the ownerType. This field must be a concrete
++ * collection type or matching the default implementation type of the collection
++ * type.
++ * @param itemType type of the items to be part of this collection
++ * @throws InitializationException if no {@link ImplicitCollectionMapper} is available
++ */
++ public void addImplicitCollection(Class ownerType, String fieldName, Class itemType) {
++ addImplicitCollection(ownerType, fieldName, null, itemType);
++ }
++
++ /**
++ * Adds implicit collection which is used for all items of the given element name defined by
++ * itemFieldName.
++ *
++ * @param ownerType class owning the implicit collection
++ * @param fieldName name of the field in the ownerType. This field must be a concrete
++ * collection type or matching the default implementation type of the collection
++ * type.
++ * @param itemFieldName element name of the implicit collection
++ * @param itemType item type to be aliases be the itemFieldName
++ * @throws InitializationException if no {@link ImplicitCollectionMapper} is available
++ */
++ public void addImplicitCollection(Class ownerType, String fieldName, String itemFieldName,
++ Class itemType) {
++ addImplicitMap(ownerType, fieldName, itemFieldName, itemType, null);
++ }
++
++ /**
++ * Adds an implicit array.
++ *
++ * @param ownerType class owning the implicit array
++ * @param fieldName name of the array field
++ * @since 1.4
++ */
++ public void addImplicitArray(Class ownerType, String fieldName) {
++ addImplicitCollection(ownerType, fieldName);
++ }
++
++ /**
++ * Adds an implicit array which is used for all items of the given itemType when the array
++ * type matches.
++ *
++ * @param ownerType class owning the implicit array
++ * @param fieldName name of the array field in the ownerType
++ * @param itemType type of the items to be part of this array
++ * @throws InitializationException if no {@link ImplicitCollectionMapper} is available or the
++ * array type does not match the itemType
++ * @since 1.4
++ */
++ public void addImplicitArray(Class ownerType, String fieldName, Class itemType) {
++ addImplicitCollection(ownerType, fieldName, itemType);
++ }
++
++ /**
++ * Adds an implicit array which is used for all items of the given element name defined by
++ * itemName.
++ *
++ * @param ownerType class owning the implicit array
++ * @param fieldName name of the array field in the ownerType
++ * @param itemName alias name of the items
++ * @throws InitializationException if no {@link ImplicitCollectionMapper} is available
++ * @since 1.4
++ */
++ public void addImplicitArray(Class ownerType, String fieldName, String itemName) {
++ addImplicitCollection(ownerType, fieldName, itemName, null);
++ }
++
++ /**
++ * Adds an implicit map.
++ *
++ * @param ownerType class owning the implicit map
++ * @param fieldName name of the field in the ownerType. This field must be a concrete
++ * map type or matching the default implementation type of the map
++ * type.
++ * @param itemType type of the items to be part of this map as value
++ * @param keyFieldName the name of the filed of the itemType that is used for the key in the map
++ * @since 1.4
++ */
++ public void addImplicitMap(Class ownerType, String fieldName, Class itemType, String keyFieldName) {
++ addImplicitMap(ownerType, fieldName, null, itemType, keyFieldName);
++ }
++
++ /**
++ * Adds an implicit map.
++ *
++ * @param ownerType class owning the implicit map
++ * @param fieldName name of the field in the ownerType. This field must be a concrete
++ * map type or matching the default implementation type of the map
++ * type.
++ * @param itemType type of the items to be part of this map as value
++ * @param keyFieldName the name of the filed of the itemType that is used for the key in the map
++ * @since 1.4
++ */
++ public void addImplicitMap(Class ownerType, String fieldName, String itemFieldName,
++ Class itemType, String keyFieldName) {
++ if (implicitCollectionMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + ImplicitCollectionMapper.class.getName()
++ + " available");
++ }
++ implicitCollectionMapper.add(ownerType, fieldName, itemFieldName, itemType, keyFieldName);
++ }
++
++ /**
++ * Create a DataHolder that can be used to pass data to the converters. The DataHolder is
++ * provided with a call to {@link #marshal(Object, HierarchicalStreamWriter, DataHolder)} or
++ * {@link #unmarshal(HierarchicalStreamReader, Object, DataHolder)}.
++ *
++ * @return a new {@link DataHolder}
++ */
++ public DataHolder newDataHolder() {
++ return new MapBackedDataHolder();
++ }
++
++ /**
++ * Creates an ObjectOutputStream that serializes a stream of objects to the writer using
++ * XStream.
++ * <p>
++ * To change the name of the root element (from <object-stream>), use
++ * {@link #createObjectOutputStream(java.io.Writer, String)}.
++ * </p>
++ *
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @since 1.0.3
++ */
++ public ObjectOutputStream createObjectOutputStream(Writer writer) throws IOException {
++ return createObjectOutputStream(
++ hierarchicalStreamDriver.createWriter(writer), "object-stream");
++ }
++
++ /**
++ * Creates an ObjectOutputStream that serializes a stream of objects to the writer using
++ * XStream.
++ * <p>
++ * To change the name of the root element (from <object-stream>), use
++ * {@link #createObjectOutputStream(java.io.Writer, String)}.
++ * </p>
++ *
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @since 1.0.3
++ */
++ public ObjectOutputStream createObjectOutputStream(HierarchicalStreamWriter writer)
++ throws IOException {
++ return createObjectOutputStream(writer, "object-stream");
++ }
++
++ /**
++ * Creates an ObjectOutputStream that serializes a stream of objects to the writer using
++ * XStream.
++ *
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @since 1.0.3
++ */
++ public ObjectOutputStream createObjectOutputStream(Writer writer, String rootNodeName)
++ throws IOException {
++ return createObjectOutputStream(
++ hierarchicalStreamDriver.createWriter(writer), rootNodeName);
++ }
++
++ /**
++ * Creates an ObjectOutputStream that serializes a stream of objects to the OutputStream
++ * using XStream.
++ * <p>
++ * To change the name of the root element (from <object-stream>), use
++ * {@link #createObjectOutputStream(java.io.Writer, String)}.
++ * </p>
++ *
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @since 1.3
++ */
++ public ObjectOutputStream createObjectOutputStream(OutputStream out) throws IOException {
++ return createObjectOutputStream(
++ hierarchicalStreamDriver.createWriter(out), "object-stream");
++ }
++
++ /**
++ * Creates an ObjectOutputStream that serializes a stream of objects to the OutputStream
++ * using XStream.
++ *
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @since 1.3
++ */
++ public ObjectOutputStream createObjectOutputStream(OutputStream out, String rootNodeName)
++ throws IOException {
++ return createObjectOutputStream(
++ hierarchicalStreamDriver.createWriter(out), rootNodeName);
++ }
++
++ /**
++ * Creates an ObjectOutputStream that serializes a stream of objects to the writer using
++ * XStream.
++ * <p>
++ * Because an ObjectOutputStream can contain multiple items and XML only allows a single
++ * root node, the stream must be written inside an enclosing node.
++ * </p>
++ * <p>
++ * It is necessary to call ObjectOutputStream.close() when done, otherwise the stream will
++ * be incomplete.
++ * </p>
++ * <h3>Example</h3>
++ *
++ * <pre>
++ * ObjectOutputStream out = xstream.createObjectOutputStream(aWriter, "things");
++ * out.writeInt(123);
++ * out.writeObject("Hello");
++ * out.writeObject(someObject)
++ * out.close();
++ * </pre>
++ *
++ * @param writer The writer to serialize the objects to.
++ * @param rootNodeName The name of the root node enclosing the stream of objects.
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @since 1.0.3
++ */
++ public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer,
++ String rootNodeName) throws IOException {
++ final StatefulWriter statefulWriter = new StatefulWriter(writer);
++ statefulWriter.startNode(rootNodeName, null);
++ return new CustomObjectOutputStream(new CustomObjectOutputStream.StreamCallback() {
++ public void writeToStream(Object object) {
++ marshal(object, statefulWriter);
++ }
++
++ public void writeFieldsToStream(Map fields) throws NotActiveException {
++ throw new NotActiveException("not in call to writeObject");
++ }
++
++ public void defaultWriteObject() throws NotActiveException {
++ throw new NotActiveException("not in call to writeObject");
++ }
++
++ public void flush() {
++ statefulWriter.flush();
++ }
++
++ public void close() {
++ if (statefulWriter.state() != StatefulWriter.STATE_CLOSED) {
++ statefulWriter.endNode();
++ statefulWriter.close();
++ }
++ }
++ });
++ }
++
++ /**
++ * Creates an ObjectInputStream that deserializes a stream of objects from a reader using
++ * XStream.
++ *
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @since 1.0.3
++ */
++ public ObjectInputStream createObjectInputStream(Reader xmlReader) throws IOException {
++ return createObjectInputStream(hierarchicalStreamDriver.createReader(xmlReader));
++ }
++
++ /**
++ * Creates an ObjectInputStream that deserializes a stream of objects from an InputStream
++ * using XStream.
++ *
++ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @since 1.3
++ */
++ public ObjectInputStream createObjectInputStream(InputStream in) throws IOException {
++ return createObjectInputStream(hierarchicalStreamDriver.createReader(in));
++ }
++
++ /**
++ * Creates an ObjectInputStream that deserializes a stream of objects from a reader using
++ * XStream. <h3>Example</h3>
++ *
++ * <pre>
++ * ObjectInputStream in = xstream.createObjectOutputStream(aReader);
++ * int a = out.readInt();
++ * Object b = out.readObject();
++ * Object c = out.readObject();
++ * </pre>
++ *
++ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter,
++ * String)
++ * @since 1.0.3
++ */
++ public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader)
++ throws IOException {
++ return new CustomObjectInputStream(new CustomObjectInputStream.StreamCallback() {
++ public Object readFromStream() throws EOFException {
++ if (!reader.hasMoreChildren()) {
++ throw new EOFException();
++ }
++ reader.moveDown();
++ Object result = unmarshal(reader);
++ reader.moveUp();
++ return result;
++ }
++
++ public Map readFieldsFromStream() throws IOException {
++ throw new NotActiveException("not in call to readObject");
++ }
++
++ public void defaultReadObject() throws NotActiveException {
++ throw new NotActiveException("not in call to readObject");
++ }
++
++ public void registerValidation(ObjectInputValidation validation, int priority)
++ throws NotActiveException {
++ throw new NotActiveException("stream inactive");
++ }
++
++ public void close() {
++ reader.close();
++ }
++ }, classLoaderReference);
++ }
++
++ /**
++ * Change the ClassLoader XStream uses to load classes. Creating an XStream instance it will
++ * register for all kind of classes and types of the current JDK, but not for any 3rd party
++ * type. To ensure that all other types are loaded with your class loader, you should call
++ * this method as early as possible - or consider to provide the class loader directly in
++ * the constructor.
++ *
++ * @since 1.1.1
++ */
++ public void setClassLoader(ClassLoader classLoader) {
++ classLoaderReference.setReference(classLoader);
++ }
++
++ /**
++ * Retrieve the ClassLoader XStream uses to load classes.
++ *
++ * @since 1.1.1
++ */
++ public ClassLoader getClassLoader() {
++ return classLoaderReference.getReference();
++ }
++
++ /**
++ * Add pattern for unknown element names to ignore.
++ *
++ * @param pattern the name pattern as regular expression
++ * @since 1.4.5
++ */
++ private void ignoreUnknownElements(Pattern pattern) {
++ if (fieldAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + FieldAliasingMapper.class.getName()
++ + " available");
++ }
++ fieldAliasingMapper.addFieldsToIgnore(pattern);
++ }
++
++ /**
++ * Process the annotations of the given types and configure the XStream.
++ *
++ * @param types the types with XStream annotations
++ * @since 1.3
++ */
++ public void processAnnotations(final Class[] types) {
++ if (annotationConfiguration == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + ANNOTATION_MAPPER_TYPE
++ + " available");
++ }
++ annotationConfiguration.processAnnotations(types);
++ }
++
++ /**
++ * Process the annotations of the given type and configure the XStream. A call of this
++ * method will automatically turn the auto-detection mode for annotations off.
++ *
++ * @param type the type with XStream annotations
++ * @since 1.3
++ */
++ public void processAnnotations(final Class type) {
++ processAnnotations(new Class[]{type});
++ }
++
++ /**
++ * Set the auto-detection mode of the AnnotationMapper. Note that auto-detection implies
++ * that the XStream is configured while it is processing the XML steams. This is a potential
++ * concurrency problem. Also is it technically not possible to detect all class aliases at
++ * deserialization. You have been warned!
++ *
++ * @param mode <code>true</code> if annotations are auto-detected
++ * @since 1.3
++ */
++ public void autodetectAnnotations(boolean mode) {
++ if (annotationConfiguration != null) {
++ annotationConfiguration.autodetectAnnotations(mode);
++ }
++ }
++
++ /**
++ * Add a new security permission.
++ *
++ * <p>
++ * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or
++ * {@link AnyTypePermission} will implicitly wipe any existing permission.
++ * </p>
++ *
++ * @param permission the permission to add
++ * @since 1.4.7
++ */
++ public void addPermission(TypePermission permission) {
++ if (securityMapper != null) {
++ securityMapper.addPermission(permission);
++ }
++ }
++
++ public void allowTypesByWildcard(String[] patterns) {
++ addPermission(new WildcardTypePermission(patterns));
++ }
++
++ /**
++ * Add security permission for explicit types by name.
++ *
++ * @param names the type names to allow
++ * @since 1.4.7
++ */
++ public void allowTypes(String[] names) {
++ addPermission(new ExplicitTypePermission(names));
++ }
++
++ /**
++ * Add security permission for explicit types.
++ *
++ * @param types the types to allow
++ * @since 1.4.7
++ */
++ public void allowTypes(Class[] types) {
++ addPermission(new ExplicitTypePermission(types));
++ }
++ /**
++ * Prevents a field from being serialized. To omit a field you must always provide the
++ * declaring type and not necessarily the type that is converted.
++ *
++ * @since 1.1.3
++ * @throws InitializationException if no {@link FieldAliasingMapper} is available
++ */
++ public void omitField(Class definedIn, String fieldName) {
++ if (fieldAliasingMapper == null) {
++ throw new com.thoughtworks.xstream.InitializationException("No "
++ + FieldAliasingMapper.class.getName()
++ + " available");
++ }
++ fieldAliasingMapper.omitField(definedIn, fieldName);
++ }
++
++ /**
++ * Add security permission for a type hierarchy.
++ *
++ * @param type the base type to allow
++ * @since 1.4.7
++ */
++ public void allowTypeHierarchy(Class type) {
++ addPermission(new TypeHierarchyPermission(type));
++ }
++ /**
++ * Ignore all unknown elements.
++ *
++ * @since 1.4.5
++ */
++ public void ignoreUnknownElements() {
++ ignoreUnknownElements(IGNORE_ALL);
++ }
++
++ /**
++ * @deprecated As of 1.3, use {@link InitializationException} instead
++ */
++ public static class InitializationException extends XStreamException {
++ /**
++ * @deprecated As of 1.3, use {@link InitializationException} instead
++ */
++ public InitializationException(String message, Throwable cause) {
++ super(message, cause);
++ }
++
++ /**
++ * @deprecated As of 1.3, use {@link InitializationException} instead
++ */
++ public InitializationException(String message) {
++ super(message);
++ }
++ }
++
++ private Object readResolve() {
++ jvm = new JVM();
++ return this;
++ }
++
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java
+new file mode 100644
+index 0000000..7e627c2
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java
+@@ -0,0 +1,99 @@
++/*
++ * Copyright (C) 2005 Joe Walnes.
++ * Copyright (C) 2006, 2007, 2008, 2009, 2013, 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * The software in this package is published under the terms of the BSD
++ * style license a copy of which has been included with this distribution in
++ * the LICENSE.txt file.
++ *
++ * Created on 09. April 2005 by Joe Walnes
++ */
++package com.thoughtworks.xstream.mapper;
++
++import com.thoughtworks.xstream.core.util.FastField;
++
++import java.util.HashMap;
++import java.util.HashSet;
++import java.util.Iterator;
++import java.util.LinkedHashSet;
++import java.util.Map;
++import java.util.Set;
++import java.util.regex.Pattern;
++
++/**
++ * Mapper that allows a field of a specific class to be replaced with a shorter alias, or omitted
++ * entirely.
++ *
++ * @author Joe Walnes
++ */
++public class FieldAliasingMapper extends MapperWrapper {
++
++ protected final Map fieldToAliasMap = new HashMap();
++ protected final Map aliasToFieldMap = new HashMap();
++ protected final Set fieldsToOmit = new HashSet();
++ protected final Set unknownFieldsToIgnore = new LinkedHashSet();
++
++ public FieldAliasingMapper(Mapper wrapped) {
++ super(wrapped);
++ }
++
++ public void addFieldAlias(String alias, Class type, String fieldName) {
++ fieldToAliasMap.put(key(type, fieldName), alias);
++ aliasToFieldMap.put(key(type, alias), fieldName);
++ }
++
++ public void addFieldsToIgnore(final Pattern pattern) {
++ unknownFieldsToIgnore.add(pattern);
++ }
++
++ private Object key(Class type, String name) {
++ return new FastField(type, name);
++ }
++
++ public String serializedMember(Class type, String memberName) {
++ String alias = getMember(type, memberName, fieldToAliasMap);
++ if (alias == null) {
++ return super.serializedMember(type, memberName);
++ } else {
++ return alias;
++ }
++ }
++
++ public String realMember(Class type, String serialized) {
++ String real = getMember(type, serialized, aliasToFieldMap);
++ if (real == null) {
++ return super.realMember(type, serialized);
++ } else {
++ return real;
++ }
++ }
++
++ private String getMember(Class type, String name, Map map) {
++ String member = null;
++ for (Class declaringType = type;
++ member == null && declaringType != Object.class && declaringType != null;
++ declaringType = declaringType.getSuperclass()) {
++ member = (String) map.get(key(declaringType, name));
++ }
++ return member;
++ }
++
++ public boolean shouldSerializeMember(Class definedIn, String fieldName) {
++ if (fieldsToOmit.contains(key(definedIn, fieldName))) {
++ return false;
++ } else if (definedIn == Object.class && !unknownFieldsToIgnore.isEmpty()) {
++ for(Iterator iter = unknownFieldsToIgnore.iterator(); iter.hasNext();) {
++ Pattern pattern = (Pattern)iter.next();
++ if (pattern.matcher(fieldName).matches()) {
++ return false;
++ }
++ }
++ }
++ return true;
++ }
++
++ public void omitField(Class definedIn, String fieldName) {
++ fieldsToOmit.add(key(definedIn, fieldName));
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java
+new file mode 100644
+index 0000000..d650c92
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 08. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.mapper;
++
++import java.util.ArrayList;
++import java.util.Arrays;
++import java.util.List;
++
++import com.thoughtworks.xstream.security.AnyTypePermission;
++import com.thoughtworks.xstream.security.ForbiddenClassException;
++import com.thoughtworks.xstream.security.NoTypePermission;
++import com.thoughtworks.xstream.security.TypePermission;
++
++
++/**
++ * A Mapper implementation injecting a security layer based on permission rules for any type required in the
++ * unmarshalling process.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class SecurityMapper extends MapperWrapper {
++
++ private final List permissions;
++
++ /**
++ * Construct a SecurityMapper.
++ *
++ * @param wrapped the mapper chain
++ * @since 1.4.7
++ */
++ public SecurityMapper(final Mapper wrapped) {
++ this(wrapped, (TypePermission[])null);
++ }
++
++ /**
++ * Construct a SecurityMapper.
++ *
++ * @param wrapped the mapper chain
++ * @param permissions the predefined permissions
++ * @since 1.4.7
++ */
++ public SecurityMapper(final Mapper wrapped, final TypePermission[] permissions) {
++ super(wrapped);
++ this.permissions = permissions == null //
++ ? new ArrayList()
++ : new ArrayList(Arrays.asList(permissions));
++ }
++
++ /**
++ * Add a new permission.
++ * <p>
++ * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or
++ * {@link AnyTypePermission} will implicitly wipe any existing permission.
++ * </p>
++ *
++ * @param permission the permission to add.
++ * @since 1.4.7
++ */
++ public void addPermission(final TypePermission permission) {
++ if (permission.equals(NoTypePermission.NONE) || permission.equals(AnyTypePermission.ANY))
++ permissions.clear();
++ permissions.add(0, permission);
++ }
++
++ public Class realClass(final String elementName) {
++ final Class type = super.realClass(elementName);
++ for (int i = 0; i < permissions.size(); ++i) {
++ final TypePermission permission = (TypePermission)permissions.get(i);
++ if (permission.allows(type))
++ return type;
++ }
++ throw new ForbiddenClassException(type);
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java
+new file mode 100644
+index 0000000..d1524a9
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java
+@@ -0,0 +1,32 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 08. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * Permission for any type and <code>null</code>.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class AnyTypePermission implements TypePermission {
++ /**
++ * @since 1.4.7
++ */
++ public static final TypePermission ANY = new AnyTypePermission();
++
++ public boolean allows(Class type) {
++ return true;
++ }
++
++ public int hashCode() {
++ return 3;
++ }
++
++ public boolean equals(Object obj) {
++ return obj != null && obj.getClass() == AnyTypePermission.class;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java
+new file mode 100644
+index 0000000..1e856ec
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java
+@@ -0,0 +1,32 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 09. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * Permission for any array type.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class ArrayTypePermission implements TypePermission {
++ /**
++ * @since 1.4.7
++ */
++ public static final TypePermission ARRAYS = new ArrayTypePermission();
++
++ public boolean allows(Class type) {
++ return type != null && type.isArray();
++ }
++
++ public int hashCode() {
++ return 13;
++ }
++
++ public boolean equals(Object obj) {
++ return obj != null && obj.getClass() == ArrayTypePermission.class;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java
+new file mode 100644
+index 0000000..196380b
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 09. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++import java.util.Arrays;
++import java.util.Collections;
++import java.util.HashSet;
++import java.util.Set;
++
++
++/**
++ * Explicit permission for a type with a name matching one in the provided list.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class ExplicitTypePermission implements TypePermission {
++
++ final Set names;
++
++ /**
++ * @since 1.4.7
++ */
++ public ExplicitTypePermission(final Class[] types) {
++ this(new Object() {
++ public String[] getNames() {
++ if (types == null)
++ return null;
++ String[] names = new String[types.length];
++ for (int i = 0; i < types.length; ++i)
++ names[i] = types[i].getName();
++ return names;
++ }
++ }.getNames());
++ }
++
++ /**
++ * @since 1.4.7
++ */
++ public ExplicitTypePermission(String[] names) {
++ this.names = names == null ? Collections.EMPTY_SET : new HashSet(Arrays.asList(names));
++ }
++
++ public boolean allows(Class type) {
++ if (type == null)
++ return false;
++ return names.contains(type.getName());
++ }
++
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java
+new file mode 100644
+index 0000000..017fc30
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java
+@@ -0,0 +1,27 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 08. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++import com.thoughtworks.xstream.XStreamException;
++
++/**
++ * Exception thrown for a forbidden class.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class ForbiddenClassException extends XStreamException {
++
++ /**
++ * Construct a ForbiddenClassException.
++ * @param type the forbidden class
++ * @since 1.4.7
++ */
++ public ForbiddenClassException(Class type) {
++ super(type == null ? "null" : type.getName());
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java
+new file mode 100644
+index 0000000..c5b8002
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java
+@@ -0,0 +1,33 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 27. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * Permission for any interface type.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class InterfaceTypePermission implements TypePermission {
++ /**
++ * @since 1.4.7
++ */
++ public static final TypePermission INTERFACES = new InterfaceTypePermission();
++
++ public boolean allows(Class type) {
++ return type != null && type.isInterface();
++ }
++
++ public int hashCode() {
++ return 31;
++ }
++
++ public boolean equals(Object obj) {
++ return obj != null && obj.getClass() == InterfaceTypePermission.class;
++ }
++
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java
+new file mode 100644
+index 0000000..17115b0
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java
+@@ -0,0 +1,39 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 09. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * Wrapper to negate another type permission.
++ * <p>
++ * If the wrapped {@link TypePermission} allows the type, this instance will throw a {@link ForbiddenClassException}
++ * instead. An instance of this permission cannot be used to allow a type.
++ * </p>
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class NoPermission implements TypePermission {
++
++ private final TypePermission permission;
++
++ /**
++ * Construct a NoPermission.
++ *
++ * @param permission the permission to negate or <code>null</code> to forbid any type
++ * @since 1.4.7
++ */
++ public NoPermission(final TypePermission permission) {
++ this.permission = permission;
++ }
++
++ public boolean allows(final Class type) {
++ if (permission == null || permission.allows(type)) {
++ throw new ForbiddenClassException(type);
++ }
++ return false;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java
+new file mode 100644
+index 0000000..802537b
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 08. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * No permission for any type.
++ * <p>
++ * Can be used to skip any existing default permission.
++ * </p>
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class NoTypePermission implements TypePermission {
++
++ /**
++ * @since 1.4.7
++ */
++ public static final TypePermission NONE = new NoTypePermission();
++
++ public boolean allows(Class type) {
++ throw new ForbiddenClassException(type);
++ }
++
++ public int hashCode() {
++ return 1;
++ }
++
++ public boolean equals(Object obj) {
++ return obj != null && obj.getClass() == NoTypePermission.class;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java
+new file mode 100644
+index 0000000..d241641
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 09. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++import com.thoughtworks.xstream.mapper.Mapper;
++
++/**
++ * Permission for <code>null</code> or XStream's null replacement type.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class NullPermission implements TypePermission {
++ /**
++ * @since 1.4.7
++ */
++ public static final TypePermission NULL = new NullPermission();
++
++ public boolean allows(Class type) {
++ return type == null || type == Mapper.Null.class;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java
+new file mode 100644
+index 0000000..fb69b95
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 09. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++import com.thoughtworks.xstream.core.util.Primitives;
++
++/**
++ * Permission for any primitive type and its boxed counterpart (incl. void).
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class PrimitiveTypePermission implements TypePermission {
++ /**
++ * @since 1.4.7
++ */
++ public static final TypePermission PRIMITIVES = new PrimitiveTypePermission();
++
++ public boolean allows(Class type) {
++ return type != null && type.isPrimitive() || Primitives.isBoxed(type);
++ }
++
++ public int hashCode() {
++ return 7;
++ }
++
++ public boolean equals(Object obj) {
++ return obj != null && obj.getClass() == PrimitiveTypePermission.class;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java
+new file mode 100644
+index 0000000..1f3d3be
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 19. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++import java.lang.reflect.Proxy;
++
++import com.thoughtworks.xstream.mapper.DynamicProxyMapper;
++
++
++/**
++ * Permission for any array type.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class ProxyTypePermission implements TypePermission {
++ /**
++ * @since 1.4.7
++ */
++ public static final TypePermission PROXIES = new ProxyTypePermission();
++
++ public boolean allows(final Class type) {
++ return type != null && (Proxy.isProxyClass(type) || type == DynamicProxyMapper.DynamicProxy.class);
++ }
++
++ public int hashCode() {
++ return 17;
++ }
++
++ public boolean equals(final Object obj) {
++ return obj != null && obj.getClass() == ProxyTypePermission.class;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java
+new file mode 100644
+index 0000000..31ddbd6
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java
+@@ -0,0 +1,48 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 09. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++import java.util.regex.Pattern;
++
++
++/**
++ * Permission for any type with a name matching one of the provided regular expressions.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class RegExpTypePermission implements TypePermission {
++
++ private final Pattern[] patterns;
++
++ public RegExpTypePermission(final String[] patterns) {
++ this(getPatterns(patterns));
++ }
++
++ public RegExpTypePermission(final Pattern[] patterns) {
++ this.patterns = patterns == null ? new Pattern[0] : patterns;
++ }
++
++ public boolean allows(final Class type) {
++ if (type != null) {
++ final String name = type.getName();
++ for (int i = 0; i < patterns.length; ++i)
++ if (patterns[i].matcher(name).matches())
++ return true;
++ }
++ return false;
++ }
++
++ private static Pattern[] getPatterns(final String[] patterns) {
++ if (patterns == null)
++ return null;
++ final Pattern[] array = new Pattern[patterns.length];
++ for (int i = 0; i < array.length; ++i)
++ array[i] = Pattern.compile(patterns[i]);
++ return array;
++ }
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java
+new file mode 100644
+index 0000000..d476ddf
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java
+@@ -0,0 +1,32 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 23. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * Permission for a type hierarchy with a name matching one in the provided list.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class TypeHierarchyPermission implements TypePermission {
++
++ private Class type;
++
++ /**
++ * @since 1.4.7
++ */
++ public TypeHierarchyPermission(Class type) {
++ this.type = type;
++ }
++
++ public boolean allows(Class type) {
++ if (type == null)
++ return false;
++ return this.type.isAssignableFrom(type);
++ }
++
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java
+new file mode 100644
+index 0000000..03f02ec
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java
+@@ -0,0 +1,25 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 08. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * Definition of a type permission.
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public interface TypePermission {
++ /**
++ * Check permission for a provided type.
++ *
++ * @param type the type to check
++ * @return <code>true</code> if provided type is allowed, <code>false</code> if permission does not handle the type
++ * @throws ForbiddenClassException if provided type is explicitly forbidden
++ * @since 1.4.7
++ */
++ boolean allows(Class type);
++}
+diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java
+new file mode 100644
+index 0000000..9da8249
+--- /dev/null
++++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java
+@@ -0,0 +1,84 @@
++/*
++ * Copyright (C) 2014 XStream Committers.
++ * All rights reserved.
++ *
++ * Created on 09. January 2014 by Joerg Schaible
++ */
++package com.thoughtworks.xstream.security;
++
++/**
++ * Permission for any type with a name matching one of the provided wildcard expressions.
++ *
++ * <p>
++ * Supported are patterns with path expressions using dot as separator:
++ * </p>
++ * <ul>
++ * <li>?: one non-control character except separator, e.g. for 'java.net.Inet?Address'</li>
++ * <li>*: arbitrary number of non-control characters except separator, e.g. for types in a package like 'java.lang.*'</li>
++ * <li>**: arbitrary number of non-control characters including separator, e.g. for types in a package and subpackages like 'java.lang.**'</li>
++ * </ul>
++ * <p>
++ * The complete range of UTF-8 characters is supported except control characters.
++ * </p>
++ *
++ * @author Jörg Schaible
++ * @since 1.4.7
++ */
++public class WildcardTypePermission extends RegExpTypePermission {
++
++ /**
++ * @since 1.4.7
++ */
++ public WildcardTypePermission(final String[] patterns) {
++ super(getRegExpPatterns(patterns));
++ }
++
++ private static String[] getRegExpPatterns(final String[] wildcards) {
++ if (wildcards == null)
++ return null;
++ final String[] regexps = new String[wildcards.length];
++ for (int i = 0; i < wildcards.length; ++i) {
++ final String wildcardExpression = wildcards[i];
++ final StringBuffer result = new StringBuffer(wildcardExpression.length() * 2);
++ result.append("(?u)");
++ final int length = wildcardExpression.length();
++ for (int j = 0; j < length; j++) {
++ final char ch = wildcardExpression.charAt(j);
++ switch (ch) {
++ case '\\':
++ case '.':
++ case '+':
++ case '|':
++ case '[':
++ case ']':
++ case '(':
++ case ')':
++ case '^':
++ case '$':
++ result.append('\\').append(ch);
++ break;
++
++ case '?':
++ result.append('.');
++ break;
++
++ case '*':
++ // see "General Category Property" in http://www.unicode.org/reports/tr18/
++ if (j + 1 < length && wildcardExpression.charAt(j + 1) == '*') {
++ result.append("[\\P{C}]*");
++ j++;
++ } else {
++ result.append("[\\P{C}&&[^").append('.').append("]]*");
++ }
++ break;
++
++ default:
++ result.append(ch);
++ break;
++ }
++ }
++ regexps[i] = result.toString();
++ }
++ return regexps;
++ }
++}
+diff --git a/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java
+index 5274b34..4fd18b0 100644
+--- a/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java
++++ b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java
+@@ -84,7 +84,7 @@ public class JmsFrameTranslator extends LegacyFrameTranslator implements
+ msg = createMapMessage(in);
+ break;
+ default:
+- throw new Exception("Unkown transformation: " + transformation);
++ throw new Exception("Unknown transformation: " + transformation);
+ }
+ } catch (Throwable e) {
+ command.getHeaders().put(Stomp.Headers.TRANSFORMATION_ERROR, e.getMessage());
+@@ -243,7 +243,8 @@ public class JmsFrameTranslator extends LegacyFrameTranslator implements
+ }
+
+ if (xstream == null) {
+- xstream = new XStream();
++ xstream = XStreamSupport.createXStream();
++ xstream.ignoreUnknownElements();
+ }
+ return xstream;
+
+diff --git a/activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java
+new file mode 100644
+index 0000000..abcca72
+--- /dev/null
++++ b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java
+@@ -0,0 +1,47 @@
++/**
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements. See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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.apache.activemq.transport.stomp;
++
++import com.thoughtworks.xstream.XStream;
++import com.thoughtworks.xstream.security.AnyTypePermission;
++import com.thoughtworks.xstream.security.NoTypePermission;
++import com.thoughtworks.xstream.security.PrimitiveTypePermission;
++import org.apache.activemq.util.ClassLoadingAwareObjectInputStream;
++
++import java.util.Collection;
++import java.util.Map;
++
++public class XStreamSupport {
++
++ public static XStream createXStream() {
++ XStream stream = new XStream();
++ stream.addPermission(NoTypePermission.NONE);
++ stream.addPermission(PrimitiveTypePermission.PRIMITIVES);
++ stream.allowTypeHierarchy(Collection.class);
++ stream.allowTypeHierarchy(Map.class);
++ stream.allowTypes(new Class[]{String.class});
++ if (ClassLoadingAwareObjectInputStream.isAllAllowed()) {
++ stream.addPermission(AnyTypePermission.ANY);
++ } else {
++ for (String packageName : ClassLoadingAwareObjectInputStream.serializablePackages) {
++ stream.allowTypesByWildcard(new String[]{packageName + ".**"});
++ }
++ }
++ return stream;
++ }
++
++}
+diff --git a/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java b/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java
+index 82da30c..6a2864f 100644
+--- a/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java
++++ b/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java
+@@ -21,7 +21,10 @@ import java.io.InputStream;
+ import java.io.ObjectInputStream;
+ import java.io.ObjectStreamClass;
+ import java.lang.reflect.Proxy;
++import java.util.Arrays;
++import java.util.Collection;
+ import java.util.HashMap;
++import java.util.Map;
+
+ @SuppressWarnings("rawtypes")
+ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream {
+@@ -29,6 +32,12 @@ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream {
+ private static final ClassLoader FALLBACK_CLASS_LOADER =
+ ClassLoadingAwareObjectInputStream.class.getClassLoader();
+
++ public static final String[] serializablePackages;
++
++ static {
++ serializablePackages = System.getProperty("org.apache.activemq.SERIALIZABLE_PACKAGES", "java.lang,java.util,org.apache.activemq,org.fusesource.hawtbuf,com.thoughtworks.xstream.mapper").split(",");
++ }
++
+ /**
+ * Maps primitive type names to corresponding class objects.
+ */
+@@ -40,7 +49,9 @@ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream {
+
+ protected Class<?> resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+- return load(classDesc.getName(), cl);
++ Class clazz = load(classDesc.getName(), cl);
++ checkSecurity(clazz);
++ return clazz;
+ }
+
+ protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
+@@ -50,18 +61,47 @@ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream {
+ cinterfaces[i] = load(interfaces[i], cl);
+ }
+
++ Class clazz = null;
+ try {
+- return Proxy.getProxyClass(cl, cinterfaces);
++ clazz = Proxy.getProxyClass(cl, cinterfaces);
+ } catch (IllegalArgumentException e) {
+ try {
+- return Proxy.getProxyClass(FALLBACK_CLASS_LOADER, cinterfaces);
++ clazz = Proxy.getProxyClass(FALLBACK_CLASS_LOADER, cinterfaces);
+ } catch (IllegalArgumentException e1) {
+ }
+
+- throw new ClassNotFoundException(null, e);
++ }
++
++ if (clazz != null) {
++ checkSecurity(clazz);
++ return clazz;
++ } else {
++ throw new ClassNotFoundException(null);
+ }
+ }
+
++ public static boolean isAllAllowed() {
++ return serializablePackages.length == 1 && serializablePackages[0].equals("*");
++ }
++
++ private void checkSecurity(Class clazz) throws ClassNotFoundException {
++ if (!clazz.isPrimitive()) {
++ if (clazz.getPackage() != null && !isAllAllowed()) {
++ boolean found = false;
++ for (String packageName : serializablePackages) {
++ if (clazz.getPackage().getName().equals(packageName) || clazz.getPackage().getName().startsWith(packageName + ".")) {
++ found = true;
++ break;
++ }
++ }
++
++ if (!found) {
++ throw new ClassNotFoundException("Forbidden " + clazz + "! This class is not allowed to be serialized. Add package with 'org.apache.activemq.SERIALIZABLE_PACKAGES' system property.");
++ }
++ }
++ }
++ }
++
+ private Class<?> load(String className, ClassLoader cl) throws ClassNotFoundException {
+ try {
+ return Class.forName(className, false, cl);
+diff --git a/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java b/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java
+index 91ae036..1b83e2e 100755
+--- a/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java
++++ b/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java
+@@ -17,9 +17,15 @@
+ package org.apache.activemq.transport.xstream;
+
+ import com.thoughtworks.xstream.XStream;
++import com.thoughtworks.xstream.converters.Converter;
++import com.thoughtworks.xstream.converters.MarshallingContext;
++import com.thoughtworks.xstream.converters.UnmarshallingContext;
++import com.thoughtworks.xstream.io.HierarchicalStreamReader;
++import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+ import org.apache.activemq.command.Command;
+ import org.apache.activemq.command.MarshallAware;
+ import org.apache.activemq.command.MessageDispatch;
++import org.apache.activemq.transport.stomp.XStreamSupport;
+ import org.apache.activemq.transport.util.TextWireFormat;
+ import org.apache.activemq.wireformat.WireFormat;
+
+@@ -105,7 +111,28 @@ public class XStreamWireFormat extends TextWireFormat {
+ // Implementation methods
+ // -------------------------------------------------------------------------
+ protected XStream createXStream() {
+- return new XStream();
++ final XStream xstream = XStreamSupport.createXStream();
++ xstream.ignoreUnknownElements();
++ xstream.registerConverter(new Converter() {
++ final Converter delegate = xstream.getConverterLookup().lookupConverterForType(ByteSequence.class);
++ @Override
++ public void marshal(Object o, HierarchicalStreamWriter hierarchicalStreamWriter, MarshallingContext marshallingContext) {
++ ByteSequence byteSequence = (ByteSequence)o;
++ byteSequence.compact();
++ delegate.marshal(byteSequence, hierarchicalStreamWriter, marshallingContext);
++ }
++
++ @Override
++ public Object unmarshal(HierarchicalStreamReader hierarchicalStreamReader, UnmarshallingContext unmarshallingContext) {
++ return delegate.unmarshal(hierarchicalStreamReader, unmarshallingContext);
++ }
++
++ @Override
++ public boolean canConvert(Class aClass) {
++ return aClass == ByteSequence.class;
++ }
++ });
++ return xstream;
+ }
+
+ }
+diff --git a/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java
+index 1d0ec06..a6cbd51 100644
+--- a/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java
++++ b/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java
+@@ -80,9 +80,9 @@ public class MessageQuery extends QueueBrowseQuery {
+ if (message instanceof ObjectMessage) {
+ try {
+ return ((ObjectMessage) message).getObject();
+- } catch (JMSException e) {
++ } catch (Exception e) {
+ //message could not be parsed, make the reason available
+- return e;
++ return new String("Cannot display ObjectMessage body. Reason: " + e.getMessage());
+ }
+ }
+ if (message instanceof MapMessage) {
diff --git a/debian/patches/series b/debian/patches/series
index febce4e..87c90b0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -10,3 +10,4 @@ exclude_leveldb.diff
CVE-2014-3600.patch
CVE-2014-3612.patch
CVE-2014-3576.patch
+CVE-2015-5254.patch
diff --git a/debian/source/local-options b/debian/source/local-options
deleted file mode 100644
index 2ee6f0f..0000000
--- a/debian/source/local-options
+++ /dev/null
@@ -1 +0,0 @@
-abort-on-upstream-changes
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/activemq.git
More information about the pkg-java-commits
mailing list