Index: 3rdParty_sources/versions.txt
===================================================================
diff -u -rf08f6c4324d6ce0ca8dc43b875a498d89dd91116 -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/versions.txt (.../versions.txt) (revision f08f6c4324d6ce0ca8dc43b875a498d89dd91116)
+++ 3rdParty_sources/versions.txt (.../versions.txt) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -48,4 +48,4 @@
xmltooling 1.4.0
-XStream 1.1.3
\ No newline at end of file
+XStream 1.5.0
\ No newline at end of file
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/InitializationException.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/InitializationException.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/InitializationException.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2007, 2008, 2013 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 22. October 2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream;
+
+/**
+ * Exception thrown configuring an XStream instance.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @since 1.3
+ */
+public class InitializationException extends XStreamException {
+ public InitializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InitializationException(String message) {
+ super(message);
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/MarshallingStrategy.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/MarshallingStrategy.java (.../MarshallingStrategy.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/MarshallingStrategy.java (.../MarshallingStrategy.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,15 +1,54 @@
+/*
+ * Copyright (C) 2004, 2006 Joe Walnes.
+ * Copyright (C) 2007, 2009, 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 16. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream;
+import com.thoughtworks.xstream.converters.ConverterLookup;
+import com.thoughtworks.xstream.converters.DataHolder;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
-import com.thoughtworks.xstream.core.DefaultConverterLookup;
-import com.thoughtworks.xstream.alias.ClassMapper;
-import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+/**
+ * Core interface for a marshalling strategy.
+ *
+ * An implementation dictates how an object graph is marshalled and unmarshalled. It is the implementation's
+ * responsibility to deal with references between the objects.
+ *
+ */
public interface MarshallingStrategy {
- Object unmarshal(Object root, HierarchicalStreamReader reader, DataHolder dataHolder, DefaultConverterLookup converterLookup, ClassMapper classMapper);
+ /**
+ * Marshal an object graph.
+ *
+ * @param writer the target for the marshalled data
+ * @param obj the object to marshal
+ * @param converterLookup the converter store
+ * @param mapper the mapper chain
+ * @param dataHolder the holder for additional data and state while marshalling
+ */
+ void marshal(HierarchicalStreamWriter writer, Object obj, ConverterLookup converterLookup, Mapper mapper,
+ DataHolder dataHolder);
- void marshal(HierarchicalStreamWriter writer, Object obj, DefaultConverterLookup converterLookup, ClassMapper classMapper, DataHolder dataHolder);
-
+ /**
+ * Unmarshal an object graph.
+ *
+ * @param root a possible root object (should be {@code null} in normal cases)
+ * @param reader the source for the unmarshalled object data
+ * @param dataHolder the holder for additional data and state while marshalling
+ * @param converterLookup the converter store
+ * @param mapper the mapper chain
+ * @return the unmarshalled object
+ */
+ Object unmarshal(Object root, HierarchicalStreamReader reader, DataHolder dataHolder, ConverterLookup converterLookup,
+ Mapper mapper);
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/XStream.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/XStream.java (.../XStream.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/XStream.java (.../XStream.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,242 +1,663 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 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 26. September 2003 by Joe Walnes
+ */
package com.thoughtworks.xstream;
-import com.thoughtworks.xstream.alias.ClassMapper;
+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.Member;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.text.DecimalFormatSymbols;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Currency;
+import java.util.Date;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+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.TimeZone;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
+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.basic.*;
-import com.thoughtworks.xstream.converters.collections.*;
-import com.thoughtworks.xstream.converters.extended.*;
+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.StringBuilderConverter;
+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.basic.UUIDConverter;
+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.enums.EnumConverter;
+import com.thoughtworks.xstream.converters.enums.EnumMapConverter;
+import com.thoughtworks.xstream.converters.enums.EnumSetConverter;
+import com.thoughtworks.xstream.converters.extended.CharsetConverter;
+import com.thoughtworks.xstream.converters.extended.ColorConverter;
+import com.thoughtworks.xstream.converters.extended.CurrencyConverter;
+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.RegexPatternConverter;
+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.StackTraceElementConverter;
+import com.thoughtworks.xstream.converters.extended.TextAttributeConverter;
+import com.thoughtworks.xstream.converters.extended.ThrowableConverter;
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.SerializableConverter;
-import com.thoughtworks.xstream.core.*;
-import com.thoughtworks.xstream.core.util.ClassLoaderReference;
+import com.thoughtworks.xstream.core.ClassLoaderReference;
+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.CompositeClassLoader;
import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
+import com.thoughtworks.xstream.core.util.SelfStreamingInstanceChecker;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
-import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
+import com.thoughtworks.xstream.io.StatefulWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
-import com.thoughtworks.xstream.mapper.*;
+import com.thoughtworks.xstream.mapper.AnnotationMapper;
+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.EnumMapper;
+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.SecurityMapper;
+import com.thoughtworks.xstream.mapper.SystemAttributeAliasingMapper;
+import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper;
+import com.thoughtworks.xstream.security.AnyTypePermission;
+import com.thoughtworks.xstream.security.ArrayTypePermission;
+import com.thoughtworks.xstream.security.ExplicitTypePermission;
+import com.thoughtworks.xstream.security.InterfaceTypePermission;
+import com.thoughtworks.xstream.security.NoPermission;
+import com.thoughtworks.xstream.security.NoTypePermission;
+import com.thoughtworks.xstream.security.NullPermission;
+import com.thoughtworks.xstream.security.PrimitiveTypePermission;
+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 java.io.*;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.URL;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.*;
/**
* Simple facade to XStream library, a Java-XML serialization tool.
- *
- * Example
+ *
+ *
+ * Example
+ *
+ *
* XStream xstream = new XStream();
* String xml = xstream.toXML(myObject); // serialize to XML
* Object myObject2 = xstream.fromXML(xml); // deserialize from XML
- *
- *
+ *
+ *
+ *
+ *
*
Aliasing classes
- *
- *
To create shorter XML, you can specify aliases for classes using
- * the alias() method.
- * For example, you can shorten all occurences of element
- * <com.blah.MyThing> to
- * <my-thing> by registering an alias for the class.
- *
- * xstream.alias("my-thing", MyThing.class);
- *
- *
+ *
+ * To create shorter XML, you can specify aliases for classes using the alias() method. For example, you
+ * can shorten all occurrences of element <com.blah.MyThing> to <my-thing> by
+ * registering an alias for the class.
+ *
+ *
+ *
+ *
+ *
+ * xstream.alias("my-thing", MyThing.class);
+ *
+ *
+ *
+ *
*
Converters
- *
- *
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.
- *
- *
Extra converters can be registered using the registerConverter()
- * 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.
- *
- * Example
+ *
+ * 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.
+ *
+ *
+ * Extra converters can be registered using the registerConverter() 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.
+ *
The default converter, ie the converter which will be used if no other registered
- * converter is suitable, can be configured by either one of the constructors
- * or can be changed using the changeDefaultConverter() method.
- * If not set, XStream uses {@link com.thoughtworks.xstream.converters.reflection.ReflectionConverter}
- * as the initial default converter.
+ *
+ *
+ *
+ *
+ *
+ * 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.
*
Uses XPath absolute references to signify duplicate references. The XPath expression ensures that a single node
+ * only is selected always.
+ *
+ *
*
xstream.setMode(XStream.ID_REFERENCES);
- *
Uses ID references to signify duplicate references. In some
- * scenarios, such as when using hand-written XML, this is
- * easier to work with.
+ *
Uses ID references to signify duplicate references. In some scenarios, such as when using hand-written XML, this
+ * is easier to work with.
*
*
*
xstream.setMode(XStream.NO_REFERENCES);
- *
This disables object graph support and treats the object
- * structure like a tree. Duplicate references are treated
- * as two seperate objects and circular references cause an
- * exception. This is slightly faster and uses less memory
- * than the other two modes.
+ *
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.
*
*
- *
*
Thread safety
- *
- *
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.
- *
+ *
+ * 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.
+ * Note, that this only applies if annotations are not
+ * auto-detected on-the-fly.
+ *
*
Implicit collections
- *
- *
To avoid the need for special tags for collections, you can define implicit collections using one of the
- * addImplicitCollection methods.
- *
+ *
+ * To avoid the need for special tags for collections, you can define implicit collections using one of the
+ * addImplicitCollection methods.
+ *
+ *
* @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 final ReflectionProvider reflectionProvider;
+ private final HierarchicalStreamDriver hierarchicalStreamDriver;
+ private final ClassLoaderReference classLoaderReference;
+ private MarshallingStrategy marshallingStrategy;
+ private final ConverterLookup converterLookup;
+ private final ConverterRegistry converterRegistry;
+ private final 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 SecurityMapper securityMapper;
+ private AnnotationMapper annotationMapper;
- private ReflectionProvider reflectionProvider;
- private HierarchicalStreamDriver hierarchicalStreamDriver;
- private MarshallingStrategy marshallingStrategy;
- private ClassLoaderReference classLoaderReference; // TODO: Should be changeable
-
- private ClassMapper classMapper;
- private DefaultConverterLookup converterLookup;
- private JVM jvm = new JVM();
-
public static final int NO_REFERENCES = 1001;
public static final int ID_REFERENCES = 1002;
- public static final int XPATH_REFERENCES = 1003;
+ 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;
- private static final int PRIORITY_NORMAL = 0;
- private static final int PRIORITY_LOW = -10;
- private static final int PRIORITY_VERY_LOW = -20;
+ 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 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, null, new XppDriver());
+ this(new XppDriver());
}
/**
- * @deprecated As of XStream 1.1.1, a default Converter is unnecessary as you can register a Converter with an
- * associated priority. Use an alternate constructor.
+ * Constructs an XStream with a special {@link ReflectionProvider}.
+ *
+ * The instance will use the {@link XppDriver} as default.
+ *
+ *
+ * @param reflectionProvider the reflection provider to use or null for best matching reflection provider
+ * @throws InitializationException in case of an initialization problem
*/
- public XStream(Converter defaultConverter) {
- this(null, null, new XppDriver(), null);
- registerConverter(defaultConverter, PRIORITY_VERY_LOW);
+ public XStream(final ReflectionProvider reflectionProvider) {
+ this(reflectionProvider, new XppDriver());
}
- public XStream(HierarchicalStreamDriver hierarchicalStreamDriver) {
- this(null, null, hierarchicalStreamDriver);
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver}.
+ *
+ * The instance will tries to determine the best match for the {@link ReflectionProvider} on its own.
+ *
+ *
+ * @param hierarchicalStreamDriver the driver instance
+ * @throws InitializationException in case of an initialization problem
+ */
+ public XStream(final HierarchicalStreamDriver hierarchicalStreamDriver) {
+ this(null, hierarchicalStreamDriver);
}
- public XStream(ReflectionProvider reflectionProvider) {
- this(reflectionProvider, null, new XppDriver());
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver} and {@link ReflectionProvider}.
+ *
+ * @param reflectionProvider the reflection provider to use or null for best matching Provider
+ * @param hierarchicalStreamDriver the driver instance
+ * @throws InitializationException in case of an initialization problem
+ */
+ public XStream(final ReflectionProvider reflectionProvider, final HierarchicalStreamDriver hierarchicalStreamDriver) {
+ this(reflectionProvider, hierarchicalStreamDriver, new ClassLoaderReference(new CompositeClassLoader()));
}
- public XStream(ReflectionProvider reflectionProvider, HierarchicalStreamDriver hierarchicalStreamDriver) {
- this(reflectionProvider, null, hierarchicalStreamDriver);
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver}, {@link ReflectionProvider} and a
+ * {@link ClassLoaderReference}.
+ *
+ * @param reflectionProvider the reflection provider to use or null for best matching Provider
+ * @param driver the driver instance
+ * @param classLoaderReference the reference to the {@link ClassLoader} to use
+ * @throws InitializationException in case of an initialization problem
+ * @since 1.4.5
+ */
+ public XStream(
+ final ReflectionProvider reflectionProvider, final HierarchicalStreamDriver driver,
+ final ClassLoaderReference classLoaderReference) {
+ this(reflectionProvider, driver, classLoaderReference, null);
}
- public XStream(ReflectionProvider reflectionProvider, ClassMapper classMapper, HierarchicalStreamDriver driver) {
- this(reflectionProvider, classMapper, driver, null);
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver}, {@link ReflectionProvider} and the
+ * {@link ClassLoader} to use.
+ *
+ * @throws InitializationException in case of an initialization problem
+ * @since 1.3
+ * @deprecated As of 1.4.5 use {@link #XStream(ReflectionProvider, HierarchicalStreamDriver, ClassLoaderReference)}
+ */
+ @Deprecated
+ public XStream(
+ final ReflectionProvider reflectionProvider, final HierarchicalStreamDriver driver,
+ final ClassLoader classLoader) {
+ this(reflectionProvider, driver, classLoader, null);
}
- public XStream(ReflectionProvider reflectionProvider, ClassMapper classMapper, HierarchicalStreamDriver driver, String classAttributeIdentifier) {
- jvm = new JVM();
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver}, {@link ReflectionProvider}, a prepared
+ * {@link Mapper} chain and the {@link ClassLoader} to use.
+ *
+ * @param reflectionProvider the reflection provider to use or null for best matching Provider
+ * @param driver the driver instance
+ * @param classLoader the {@link ClassLoader} to use
+ * @param mapper the instance with the {@link Mapper} chain or null for the default chain
+ * @throws InitializationException in case of an initialization problem
+ * @since 1.3
+ * @deprecated As of 1.4.5 use
+ * {@link #XStream(ReflectionProvider, HierarchicalStreamDriver, ClassLoaderReference, Mapper)}
+ */
+ @Deprecated
+ public XStream(
+ final ReflectionProvider reflectionProvider, final HierarchicalStreamDriver driver,
+ final ClassLoader classLoader, final Mapper mapper) {
+ this(reflectionProvider, driver, new ClassLoaderReference(classLoader), mapper, new DefaultConverterLookup());
+ }
+
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver}, {@link ReflectionProvider}, a prepared
+ * {@link Mapper} chain and the {@link ClassLoaderReference}.
+ *
+ * The {@link ClassLoaderReference} should also be used for the {@link Mapper} chain.
+ *
+ *
+ * @param reflectionProvider the reflection provider to use or null for best matching Provider
+ * @param driver the driver instance
+ * @param classLoaderReference the reference to the {@link ClassLoader} to use
+ * @param mapper the instance with the {@link Mapper} chain or null for the default chain
+ * @throws InitializationException in case of an initialization problem
+ * @since 1.4.5
+ */
+ public XStream(
+ final ReflectionProvider reflectionProvider, final HierarchicalStreamDriver driver,
+ final ClassLoaderReference classLoaderReference, final Mapper mapper) {
+ this(reflectionProvider, driver, classLoaderReference, mapper, new DefaultConverterLookup());
+ }
+
+ private XStream(
+ final ReflectionProvider reflectionProvider, final HierarchicalStreamDriver driver,
+ final ClassLoaderReference classLoader, final Mapper mapper,
+ final DefaultConverterLookup defaultConverterLookup) {
+ this(reflectionProvider, driver, classLoader, mapper, new ConverterLookup() {
+ @Override
+ public Converter lookupConverterForType(final Class> type) {
+ return defaultConverterLookup.lookupConverterForType(type);
+ }
+ }, new ConverterRegistry() {
+ @Override
+ public void registerConverter(final Converter converter, final int priority) {
+ defaultConverterLookup.registerConverter(converter, priority);
+ }
+ });
+ }
+
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver}, {@link ReflectionProvider}, a prepared
+ * {@link Mapper} chain, the {@link ClassLoaderReference} and an own {@link ConverterLookup} and
+ * {@link ConverterRegistry}.
+ *
+ * @param reflectionProvider the reflection provider to use or null for best matching Provider
+ * @param driver the driver instance
+ * @param classLoader the {@link ClassLoader} to use
+ * @param mapper the instance with the {@link Mapper} chain or null for the default chain
+ * @param converterLookup the instance that is used to lookup the converters
+ * @param converterRegistry an instance to manage the converter instances
+ * @throws InitializationException in case of an initialization problem
+ * @since 1.3
+ * @deprecated As of 1.4.5 use
+ * {@link #XStream(ReflectionProvider, HierarchicalStreamDriver, ClassLoaderReference, Mapper, ConverterLookup, ConverterRegistry)}
+ */
+ @Deprecated
+ public XStream(
+ final ReflectionProvider reflectionProvider, final HierarchicalStreamDriver driver,
+ final ClassLoader classLoader, final Mapper mapper, final ConverterLookup converterLookup,
+ final ConverterRegistry converterRegistry) {
+ this(reflectionProvider, driver, new ClassLoaderReference(classLoader), mapper, converterLookup,
+ converterRegistry);
+ }
+
+ /**
+ * Constructs an XStream with a special {@link HierarchicalStreamDriver}, {@link ReflectionProvider}, a prepared
+ * {@link Mapper} chain, the {@link ClassLoaderReference} and an own {@link ConverterLookup} and
+ * {@link ConverterRegistry}.
+ *
+ * The ClassLoaderReference should also be used for the Mapper chain. The ConverterLookup should access the
+ * ConverterRegistry if you intent to register {@link Converter} instances with XStream facade or you are using
+ * annotations.
+ *
+ *
+ * @param reflectionProvider the reflection provider to use or null for best matching Provider
+ * @param driver the driver instance
+ * @param classLoaderReference the reference to the {@link ClassLoader} to use
+ * @param mapper the instance with the {@link Mapper} chain or null for the default chain
+ * @param converterLookup the instance that is used to lookup the converters
+ * @param converterRegistry an instance to manage the converter instances or null to prevent any further
+ * registry (including annotations)
+ * @throws InitializationException in case of an initialization problem
+ * @since 1.4.5
+ */
+ public XStream(
+ ReflectionProvider reflectionProvider, final HierarchicalStreamDriver driver,
+ final ClassLoaderReference classLoaderReference, final Mapper mapper,
+ final ConverterLookup converterLookup, final ConverterRegistry converterRegistry) {
if (reflectionProvider == null) {
- reflectionProvider = jvm.bestReflectionProvider();
+ reflectionProvider = JVM.newReflectionProvider();
}
this.reflectionProvider = reflectionProvider;
- this.hierarchicalStreamDriver = driver;
- this.classLoaderReference = new ClassLoaderReference(new CompositeClassLoader());
- this.classMapper = classMapper == null ? buildMapper(classAttributeIdentifier) : classMapper;
- converterLookup = new DefaultConverterLookup(this.classMapper);
+ hierarchicalStreamDriver = driver;
+ this.classLoaderReference = classLoaderReference;
+ this.converterLookup = converterLookup;
+ this.converterRegistry = converterRegistry;
+ this.mapper = mapper == null ? buildMapper() : mapper;
+
+ setupMappers();
+ setupSecurity();
setupAliases();
setupDefaultImplementations();
setupConverters();
setupImmutableTypes();
- setMode(XPATH_REFERENCES);
+ setMode(XPATH_RELATIVE_REFERENCES);
}
- /**
- * @deprecated As of XStream 1.1.1, a default Converter is unnecessary as you can register a Converter with an
- * associated priority. Use an alternate constructor.
- */
- public XStream(ReflectionProvider reflectionProvider, ClassMapper classMapper, HierarchicalStreamDriver driver, String classAttributeIdentifier, Converter defaultConverter) {
- this(reflectionProvider, classMapper, driver, classAttributeIdentifier);
- registerConverter(defaultConverter, PRIORITY_VERY_LOW);
- }
-
- private ClassMapper buildMapper(String classAttributeIdentifier) {
- MapperWrapper mapper = new DefaultMapper(classLoaderReference, classAttributeIdentifier);
- mapper = new XmlFriendlyMapper(mapper);
+ 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);
- classAliasingMapper = (ClassAliasingMapper) mapper; // need a reference to that one
mapper = new FieldAliasingMapper(mapper);
- fieldAliasingMapper = (FieldAliasingMapper) mapper; // need a reference to that one
+ mapper = new AttributeAliasingMapper(mapper);
+ mapper = new SystemAttributeAliasingMapper(mapper);
mapper = new ImplicitCollectionMapper(mapper);
- implicitCollectionMapper = (ImplicitCollectionMapper)mapper; // need a reference to this one
- mapper = new DynamicProxyMapper(mapper);
- if (JVM.is15()) {
- mapper = new EnumMapper(mapper);
- }
mapper = new OuterClassMapper(mapper);
mapper = new ArrayMapper(mapper);
mapper = new DefaultImplementationsMapper(mapper);
- defaultImplementationsMapper = (DefaultImplementationsMapper) mapper; // and that one
+ mapper = new AttributeMapper(mapper, converterLookup, reflectionProvider);
+ mapper = new EnumMapper(mapper);
+ mapper = new LocalConversionMapper(mapper);
mapper = new ImmutableTypesMapper(mapper);
- immutableTypesMapper = (ImmutableTypesMapper)mapper; // that one too
- mapper = wrapMapper(mapper);
+ mapper = new SecurityMapper(mapper);
+ mapper = new AnnotationMapper(mapper, converterRegistry, converterLookup, classLoaderReference,
+ reflectionProvider);
+ mapper = wrapMapper((MapperWrapper)mapper);
mapper = new CachingMapper(mapper);
return mapper;
}
- protected MapperWrapper wrapMapper(MapperWrapper next) {
+ @SuppressWarnings("unused")
+ private Mapper buildMapperDynamically(final String className, final Class>[] constructorParamTypes,
+ final Object[] constructorParamValues) {
+ try {
+ final Class> type = Class.forName(className, false, classLoaderReference.getReference());
+ final Constructor> constructor = type.getConstructor(constructorParamTypes);
+ return (Mapper)constructor.newInstance(constructorParamValues);
+ } catch (final Exception e) {
+ throw new InitializationException("Could not instantiate mapper : " + className, e);
+ } catch (final LinkageError e) {
+ throw new InitializationException("Could not instantiate mapper : " + className, e);
+ }
+ }
+
+ protected MapperWrapper wrapMapper(final MapperWrapper next) {
return next;
}
+ /**
+ * @deprecated As of upcoming
+ */
+ @Deprecated
+ protected boolean useXStream11XmlFriendlyMapper() {
+ return false;
+ }
+
+ private void setupMappers() {
+ packageAliasingMapper = mapper.lookupMapperOfType(PackageAliasingMapper.class);
+ classAliasingMapper = mapper.lookupMapperOfType(ClassAliasingMapper.class);
+ fieldAliasingMapper = mapper.lookupMapperOfType(FieldAliasingMapper.class);
+ attributeMapper = mapper.lookupMapperOfType(AttributeMapper.class);
+ attributeAliasingMapper = mapper.lookupMapperOfType(AttributeAliasingMapper.class);
+ systemAttributeAliasingMapper = mapper.lookupMapperOfType(SystemAttributeAliasingMapper.class);
+ implicitCollectionMapper = mapper.lookupMapperOfType(ImplicitCollectionMapper.class);
+ defaultImplementationsMapper = mapper.lookupMapperOfType(DefaultImplementationsMapper.class);
+ immutableTypesMapper = mapper.lookupMapperOfType(ImmutableTypesMapper.class);
+ localConversionMapper = mapper.lookupMapperOfType(LocalConversionMapper.class);
+ securityMapper = mapper.lookupMapperOfType(SecurityMapper.class);
+ annotationMapper = mapper.lookupMapperOfType(AnnotationMapper.class);
+ }
+
+ protected void setupSecurity() {
+ if (securityMapper == null) {
+ return;
+ }
+
+ addPermission(NullPermission.NULL);
+ addPermission(PrimitiveTypePermission.PRIMITIVES);
+ addPermission(ArrayTypePermission.ARRAYS);
+ addPermission(InterfaceTypePermission.INTERFACES);
+ allowTypeHierarchy(Calendar.class);
+ allowTypeHierarchy(Collection.class);
+ allowTypeHierarchy(Enum.class);
+ allowTypeHierarchy(Map.class);
+ allowTypeHierarchy(Map.Entry.class);
+ allowTypeHierarchy(Member.class);
+ allowTypeHierarchy(Number.class);
+ allowTypeHierarchy(Throwable.class);
+ allowTypeHierarchy(TimeZone.class);
+
+ final Set> types = new HashSet>();
+ types.addAll(Arrays.>asList(BitSet.class, Charset.class, Class.class, Currency.class, Date.class,
+ DecimalFormatSymbols.class, File.class, Locale.class, Object.class, Pattern.class, StackTraceElement.class,
+ String.class, StringBuffer.class, StringBuilder.class, URL.class, URI.class, UUID.class));
+ if (JVM.isSQLAvailable()) {
+ types.add(JVM.loadClassForName("java.sql.Timestamp"));
+ types.add(JVM.loadClassForName("java.sql.Time"));
+ types.add(JVM.loadClassForName("java.sql.Date"));
+ }
+ types.remove(null);
+ allowTypes(types.toArray(new Class[types.size()]));
+ }
+
protected void setupAliases() {
- alias("null", ClassMapper.Null.class);
+ if (classAliasingMapper == null) {
+ return;
+ }
+
+ alias("null", Mapper.Null.class);
alias("int", Integer.class);
alias("float", Float.class);
alias("double", Double.class);
@@ -250,153 +671,194 @@
alias("big-int", BigInteger.class);
alias("big-decimal", BigDecimal.class);
- alias("string-buffer", StringBuffer.class);
alias("string", String.class);
+ alias("string-buffer", StringBuffer.class);
+ alias("string-builder", StringBuilder.class);
+ alias("uuid", UUID.class);
alias("java-class", Class.class);
alias("method", Method.class);
alias("constructor", Constructor.class);
+ alias("field", Field.class);
alias("date", Date.class);
+ alias("gregorian-calendar", Calendar.class);
+ alias("uri", URI.class);
alias("url", URL.class);
+ alias("file", File.class);
+ alias("locale", Locale.class);
alias("bit-set", BitSet.class);
+ alias("trace", StackTraceElement.class);
+ alias("currency", Currency.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("linked-hash-map", LinkedHashMap.class);
+ alias("linked-hash-set", LinkedHashSet.class);
+ alias("concurrent-hash-map", ConcurrentHashMap.class);
- // 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("enum-set", EnumSet.class);
+ alias("enum-map", EnumMap.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());
- alias("sql-timestamp", Timestamp.class);
- alias("sql-time", Time.class);
- alias("sql-date", java.sql.Date.class);
- alias("file", File.class);
- alias("locale", Locale.class);
- alias("gregorian-calendar", Calendar.class);
+ if (JVM.isAWTAvailable()) {
+ // 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.loadClassForName("java.awt.Color", false));
+ alias("awt-font", JVM.loadClassForName("java.awt.Font", false));
+ alias("awt-text-attribute", JVM.loadClassForName("java.awt.font.TextAttribute"));
+ }
-
- if (JVM.is14()) {
- 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"));
- // since jdk 1.4 included, but previously available as separate package ...
- alias("auth-subject", jvm.loadClass("javax.security.auth.Subject"));
+ if (JVM.isSQLAvailable()) {
+ alias("sql-timestamp", JVM.loadClassForName("java.sql.Timestamp"));
+ alias("sql-time", JVM.loadClassForName("java.sql.Time"));
+ alias("sql-date", JVM.loadClassForName("java.sql.Date"));
}
- if (JVM.is15()) {
- alias("enum-set", jvm.loadClass("java.util.EnumSet"));
- alias("enum-map", jvm.loadClass("java.util.EnumMap"));
+ aliasType("charset", Charset.class);
+
+ if (JVM.loadClassForName("javax.security.auth.Subject") != null) {
+ aliasDynamically("auth-subject", "javax.security.auth.Subject");
}
+ if (JVM.loadClassForName("javax.xml.datatype.Duration") != null) {
+ aliasDynamically("duration", "javax.xml.datatype.Duration");
+ }
}
+ private void aliasDynamically(final String alias, final String className) {
+ final Class> type = JVM.loadClassForName(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() {
- ReflectionConverter reflectionConverter = new ReflectionConverter(classMapper, reflectionProvider);
- registerConverter(reflectionConverter, PRIORITY_VERY_LOW);
+ registerConverter(new ReflectionConverter(mapper, reflectionProvider), PRIORITY_VERY_LOW);
- registerConverter(new SerializableConverter(classMapper, reflectionProvider), PRIORITY_LOW);
- registerConverter(new ExternalizableConverter(classMapper), PRIORITY_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(new CharConverter(), 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 StringBuilderConverter(), PRIORITY_NORMAL);
+ registerConverter(new ThrowableConverter(converterLookup), PRIORITY_NORMAL);
+ registerConverter(new StackTraceElementConverter(), PRIORITY_NORMAL);
registerConverter(new DateConverter(), PRIORITY_NORMAL);
+ registerConverter(new GregorianCalendarConverter(), PRIORITY_NORMAL);
+ registerConverter(new RegexPatternConverter(), PRIORITY_NORMAL);
+ registerConverter(new CurrencyConverter(), PRIORITY_NORMAL);
+ registerConverter(new CharsetConverter(), PRIORITY_NORMAL);
+ registerConverter(new LocaleConverter(), PRIORITY_NORMAL);
registerConverter(new BitSetConverter(), PRIORITY_NORMAL);
+ registerConverter(new UUIDConverter(), 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(classMapper), PRIORITY_NORMAL);
+ registerConverter(new ArrayConverter(mapper), PRIORITY_NORMAL);
registerConverter(new CharArrayConverter(), PRIORITY_NORMAL);
- registerConverter(new CollectionConverter(classMapper), PRIORITY_NORMAL);
- registerConverter(new MapConverter(classMapper), PRIORITY_NORMAL);
- registerConverter(new TreeMapConverter(classMapper), PRIORITY_NORMAL);
- registerConverter(new TreeSetConverter(classMapper), 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(new EncodedByteArrayConverter(), PRIORITY_NORMAL);
+ registerConverter((Converter)new EncodedByteArrayConverter(), PRIORITY_NORMAL);
+ registerConverter(new EnumConverter(), PRIORITY_NORMAL);
+ registerConverter(new EnumSetConverter(mapper), PRIORITY_NORMAL);
+ registerConverter(new EnumMapConverter(mapper), PRIORITY_NORMAL);
registerConverter(new FileConverter(), PRIORITY_NORMAL);
- registerConverter(new SqlTimestampConverter(), PRIORITY_NORMAL);
- registerConverter(new SqlTimeConverter(), PRIORITY_NORMAL);
- registerConverter(new SqlDateConverter(), PRIORITY_NORMAL);
- registerConverter(new DynamicProxyConverter(classMapper, classLoaderReference), PRIORITY_NORMAL);
+ if (JVM.isSQLAvailable()) {
+ 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(), PRIORITY_NORMAL);
- registerConverter(new FontConverter(), PRIORITY_NORMAL);
- registerConverter(new ColorConverter(), 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
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.extended.ThrowableConverter", PRIORITY_NORMAL,
- new Class[] {Converter.class} , new Object[] { reflectionConverter} );
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.extended.StackTraceElementConverter", PRIORITY_NORMAL,
- null, null);
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.extended.CurrencyConverter", PRIORITY_NORMAL,
- null, null);
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.extended.RegexPatternConverter", PRIORITY_NORMAL,
- new Class[] {Converter.class} , new Object[] { reflectionConverter} );
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.extended.SubjectConverter", PRIORITY_NORMAL,
- new Class[] {Mapper.class}, new Object[] {classMapper});
+ registerConverter(new JavaMethodConverter(classLoaderReference), PRIORITY_NORMAL);
+ registerConverter(new JavaFieldConverter(classLoaderReference), PRIORITY_NORMAL);
+ if (JVM.isAWTAvailable()) {
+ registerConverter(new FontConverter(mapper), PRIORITY_NORMAL);
+ registerConverter(new ColorConverter(), PRIORITY_NORMAL);
+ registerConverter(new TextAttributeConverter(), PRIORITY_NORMAL);
}
+ if (JVM.isSwingAvailable()) {
+ registerConverter(new LookAndFeelConverter(mapper, reflectionProvider), PRIORITY_NORMAL);
+ }
- if (JVM.is15()) {
- // late bound converters - allows XStream to be compiled on earlier JDKs
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.enums.EnumConverter", PRIORITY_NORMAL,
- null, null);
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.enums.EnumSetConverter", PRIORITY_NORMAL,
- new Class[] {Mapper.class}, new Object[] {classMapper});
- dynamicallyRegisterConverter(
- "com.thoughtworks.xstream.converters.enums.EnumMapConverter", PRIORITY_NORMAL,
- new Class[] {Mapper.class}, new Object[] {classMapper});
+ if (JVM.loadClassForName("javax.security.auth.Subject") != null) {
+ registerConverterDynamically("com.thoughtworks.xstream.converters.extended.SubjectConverter",
+ PRIORITY_NORMAL, new Class[]{Mapper.class}, new Object[]{mapper});
}
+ if (JVM.loadClassForName("javax.xml.datatype.Duration") != null) {
+ registerConverterDynamically("com.thoughtworks.xstream.converters.extended.DurationConverter",
+ PRIORITY_NORMAL, null, null);
+ }
+
+ registerConverter(new SelfStreamingInstanceChecker(converterLookup, this), PRIORITY_NORMAL);
}
- private void dynamicallyRegisterConverter(String className, int priority,
- Class[] constructorParamTypes, Object[] constructorParamValues) {
+ private void registerConverterDynamically(final String className, final int priority,
+ final Class>[] constructorParamTypes, final Object[] constructorParamValues) {
try {
- Class type = Class.forName(className, false, classLoaderReference.getReference());
- Constructor constructor = type.getConstructor(constructorParamTypes);
- Converter converter = (Converter) constructor.newInstance(constructorParamValues);
- registerConverter(converter, priority);
- } catch (Exception e) {
- throw new InitializationException("Could not instatiate converter : " + className, e);
+ final Class> type = Class.forName(className, false, classLoaderReference.getReference());
+ final Constructor> constructor = type.getConstructor(constructorParamTypes);
+ final Object instance = constructor.newInstance(constructorParamValues);
+ if (instance instanceof Converter) {
+ registerConverter((Converter)instance, priority);
+ } else if (instance instanceof SingleValueConverter) {
+ registerConverter((SingleValueConverter)instance, priority);
+ }
+ } catch (final Exception e) {
+ throw new InitializationException("Could not instantiate converter : " + className, e);
+ } catch (final LinkageError e) {
+ throw new InitializationException("Could not instantiate converter : " + className, e);
}
}
protected void setupImmutableTypes() {
+ if (immutableTypesMapper == null) {
+ return;
+ }
+
// primitives are always immutable
addImmutableType(boolean.class);
addImmutableType(Boolean.class);
@@ -416,446 +878,1180 @@
addImmutableType(Short.class);
// additional types
- addImmutableType(ClassMapper.Null.class);
+ addImmutableType(Mapper.Null.class);
addImmutableType(BigDecimal.class);
addImmutableType(BigInteger.class);
addImmutableType(String.class);
+ addImmutableType(Charset.class);
+ addImmutableType(Currency.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.isAWTAvailable()) {
+ addImmutableTypeDynamically("java.awt.font.TextAttribute");
+ }
}
- public void setMarshallingStrategy(MarshallingStrategy marshallingStrategy) {
+ private void addImmutableTypeDynamically(final String className) {
+ final Class> type = JVM.loadClassForName(className);
+ if (type != null) {
+ addImmutableType(type);
+ }
+ }
+
+ /**
+ * Setter for an arbitrary marshalling strategy.
+ *
+ * @param marshallingStrategy the implementation to use
+ * @see #setMode(int)
+ */
+ public void setMarshallingStrategy(final 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 stringWriter = new StringWriter();
- HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(stringWriter);
- marshal(obj, writer);
- writer.flush();
- writer.close();
- return stringWriter.toString();
+ public String toXML(final Object obj) {
+ final Writer writer = new StringWriter();
+ toXML(obj, writer);
+ return writer.toString();
}
/**
- * Serialize an object to the given Writer as pretty-printed XML.
+ * 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);
- marshal(obj, writer);
- writer.flush();
+ public void toXML(final Object obj, final Writer out) {
+ @SuppressWarnings("resource")
+ final HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out);
+ try {
+ marshal(obj, writer);
+ } finally {
+ writer.flush();
+ }
}
/**
- * Serialize an object to the given OutputStream as pretty-printed XML.
+ * 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);
- marshal(obj, writer);
- writer.flush();
+ public void toXML(final Object obj, final OutputStream out) {
+ @SuppressWarnings("resource")
+ final 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) {
+ public void marshal(final Object obj, final 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.
+ *
+ * @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, classMapper, dataHolder);
+ public void marshal(final Object obj, final HierarchicalStreamWriter writer, final 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) {
+ public T fromXML(final 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 xml) {
- return unmarshal(hierarchicalStreamDriver.createReader(xml), null);
+ public T fromXML(final 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) {
+ public T fromXML(final InputStream input) {
return unmarshal(hierarchicalStreamDriver.createReader(input), null);
}
/**
- * Deserialize an object from an XML String,
- * populating the fields of the given root object instead of instantiating
- * a new one.
+ * 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(String xml, Object root) {
+ public T fromXML(final URL url) {
+ return fromXML(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 T fromXML(final File file) {
+ return fromXML(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 T fromXML(final String xml, final T 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.
+ * 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) {
+ public T fromXML(final Reader xml, final T root) {
return unmarshal(hierarchicalStreamDriver.createReader(xml), root);
}
/**
- * Deserialize an object from an XML InputStream,
- * populating the fields of the given root object instead of instantiating
- * a new one.
+ * 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(InputStream xml, Object root) {
- return unmarshal(hierarchicalStreamDriver.createReader(xml), root);
+ public T fromXML(final URL url, final T 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 T fromXML(final File file, final T root) {
+ final HierarchicalStreamReader reader = hierarchicalStreamDriver.createReader(file);
+ try {
+ return unmarshal(reader, root);
+ } finally {
+ reader.close();
+ }
+ }
+
+ /**
+ * 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 T fromXML(final InputStream input, final T 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) {
+ public T unmarshal(final 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.
+ * 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) {
+ public T unmarshal(final HierarchicalStreamReader reader, final T 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.
- * @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.
+ *
+ * @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) {
- return marshallingStrategy.unmarshal(root, reader, dataHolder, converterLookup, classMapper);
+ public T unmarshal(final HierarchicalStreamReader reader, final T root, final DataHolder dataHolder) {
+ try {
+ @SuppressWarnings("unchecked")
+ final T t = (T)marshallingStrategy.unmarshal(root, reader, dataHolder, converterLookup, mapper);
+ return t;
+
+ } catch (final ConversionException e) {
+ final Package pkg = getClass().getPackage();
+ final String version = pkg != null ? pkg.getImplementationVersion() : null;
+ e.add("version", version != null ? version : "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
+ * @param type Type to be aliased
+ * @throws InitializationException if no {@link ClassAliasingMapper} is available
*/
- public void alias(String name, Class type) {
+ public void alias(final String name, final Class> type) {
+ if (classAliasingMapper == null) {
+ throw new 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(final String name, final Class> type) {
+ if (classAliasingMapper == null) {
+ throw new 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 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) {
+ public void alias(final String name, final Class> type, final Class> defaultImplementation) {
alias(name, type);
addDefaultImplementation(defaultImplementation, type);
}
- public void aliasField(String alias, Class type, String fieldName) {
- fieldAliasingMapper.addFieldAlias(alias, type, fieldName);
+ /**
+ * 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(final String name, final String pkgName) {
+ if (packageAliasingMapper == null) {
+ throw new 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(final String alias, final Class> definedIn, final String fieldName) {
+ if (fieldAliasingMapper == null) {
+ throw new 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(final String alias, final String attributeName) {
+ if (attributeAliasingMapper == null) {
+ throw new 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
+ * null. 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 null)
+ * @param systemAttributeName the name of the system attribute
+ * @throws InitializationException if no {@link SystemAttributeAliasingMapper} is available
+ * @since 1.3.1
+ */
+ public void aliasSystemAttribute(final String alias, final String systemAttributeName) {
+ if (systemAttributeAliasingMapper == null) {
+ throw new 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(final Class> definedIn, final String attributeName, final 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(final String fieldName, final Class> type) {
+ if (attributeMapper == null) {
+ throw new 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(final Class> definedIn, final String fieldName) {
+ if (attributeMapper == null) {
+ throw new 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(final Class> type) {
+ if (attributeMapper == null) {
+ throw new 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.
+ * 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) {
+ public void addDefaultImplementation(final Class> defaultImplementation, final Class> ofType) {
+ if (defaultImplementationsMapper == null) {
+ throw new InitializationException("No " + DefaultImplementationsMapper.class.getName() + " available");
+ }
defaultImplementationsMapper.addDefaultImplementation(defaultImplementation, ofType);
}
- public void addImmutableType(Class type) {
+ /**
+ * 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(final Class> type) {
+ if (immutableTypesMapper == null) {
+ throw new InitializationException("No " + ImmutableTypesMapper.class.getName() + " available");
+ }
immutableTypesMapper.addImmutableType(type);
}
/**
- * @deprecated As of 1.1.1 you should register a converter with the appropriate priority.
+ * Register a converter with normal priority.
+ *
+ * @param converter the converter instance
*/
- public void changeDefaultConverter(Converter defaultConverter) {
- registerConverter(defaultConverter, PRIORITY_VERY_LOW);
+ public void registerConverter(final Converter converter) {
+ registerConverter(converter, PRIORITY_NORMAL);
}
- public void registerConverter(Converter converter) {
+ /**
+ * Register a converter with chosen priority.
+ *
+ * @param converter the converter instance
+ * @param priority the converter priority
+ */
+ public void registerConverter(final Converter converter, final int priority) {
+ if (converterRegistry != null) {
+ converterRegistry.registerConverter(converter, priority);
+ }
+ }
+
+ /**
+ * Register a single value converter with normal priority.
+ *
+ * @param converter the single value converter instance
+ */
+ public void registerConverter(final SingleValueConverter converter) {
registerConverter(converter, PRIORITY_NORMAL);
}
- public void registerConverter(Converter converter, int priority) {
- converterLookup.registerConverter(converter, priority);
+ /**
+ * Register a single converter with chosen priority.
+ *
+ * @param converter the single converter instance
+ * @param priority the converter priority
+ */
+ public void registerConverter(final SingleValueConverter converter, final int priority) {
+ if (converterRegistry != null) {
+ converterRegistry.registerConverter(new SingleValueConverterWrapper(converter), priority);
+ }
}
- public ClassMapper getClassMapper() {
- return classMapper;
+ /**
+ * 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(final Class> definedIn, final String fieldName, final Converter converter) {
+ if (localConversionMapper == null) {
+ throw new 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(final Class> definedIn, final String fieldName,
+ final SingleValueConverter converter) {
+ final Converter wrapper = new SingleValueConverterWrapper(converter);
+ registerLocalConverter(definedIn, fieldName, wrapper);
+ }
+
+ /**
+ * 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 valuse are XStream.XPATH_REFERENCES,
- * XStream.ID_REFERENCES and XStream.NO_REFERENCES.
- *
- * @see #XPATH_REFERENCES
+ * Change mode for dealing with duplicate references. Valid values are XPATH_ABSOLUTE_REFERENCES,
+ * XPATH_RELATIVE_REFERENCES, XStream.ID_REFERENCES and XStream.NO_REFERENCES
+ * .
+ *
+ * @throws IllegalArgumentException if the mode is not one of the declared types
+ * @see #setMarshallingStrategy(MarshallingStrategy)
+ * @see #XPATH_ABSOLUTE_REFERENCES
+ * @see #XPATH_RELATIVE_REFERENCES
* @see #ID_REFERENCES
* @see #NO_REFERENCES
*/
- public void setMode(int mode) {
+ public void setMode(final int mode) {
switch (mode) {
- case NO_REFERENCES:
- setMarshallingStrategy(new TreeMarshallingStrategy());
- break;
- case ID_REFERENCES:
- setMarshallingStrategy(new ReferenceByIdMarshallingStrategy());
- break;
- case XPATH_REFERENCES:
- setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy());
- break;
- default:
- throw new IllegalArgumentException("Unknown mode : " + 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);
}
}
/**
- * @deprecated Use addImplicitCollection() instead.
- */
- public void addDefaultCollection(Class ownerType, String fieldName) {
- addImplicitCollection(ownerType, fieldName);
- }
-
- /**
- * Adds a default implicit collection which is used for any unmapped xml tag.
- *
+ * 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 an java.util.ArrayList.
+ * @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) {
- implicitCollectionMapper.add(ownerType, fieldName, null, Object.class);
+ public void addImplicitCollection(final Class> ownerType, final 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 an java.util.ArrayList.
- * @param itemType type of the items to be part of this 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) {
- implicitCollectionMapper.add(ownerType, fieldName, null, itemType);
+ public void addImplicitCollection(final Class> ownerType, final String fieldName, final 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 an java.util.ArrayList.
- * @param itemFieldName element name of 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) {
- implicitCollectionMapper.add(ownerType, fieldName, itemFieldName, itemType);
+ public void addImplicitCollection(final Class> ownerType, final String fieldName, final String itemFieldName,
+ final 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(final Class> ownerType, final 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(final Class> ownerType, final String fieldName, final 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(final Class> ownerType, final String fieldName, final 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 field of the itemType that is used for the key in the map
+ * @since 1.4
+ */
+ public void addImplicitMap(final Class> ownerType, final String fieldName, final Class> itemType,
+ final 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 itemName alias name of the items
+ * @param itemType type of the items to be part of this map as value
+ * @param keyFieldName the name of the field of the itemType that is used for the key in the map
+ * @since 1.4
+ */
+ public void addImplicitMap(final Class> ownerType, final String fieldName, final String itemName,
+ final Class> itemType, final String keyFieldName) {
+ if (implicitCollectionMapper == null) {
+ throw new InitializationException("No " + ImplicitCollectionMapper.class.getName() + " available");
+ }
+ implicitCollectionMapper.add(ownerType, fieldName, itemName, 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.
- *
- *
To change the name of the root element (from <object-stream>), use
- * {@link #createObjectOutputStream(java.io.Writer, String)}.
- *
+ *
+ * To change the name of the root element (from <object-stream>), use
+ * {@link #createObjectOutputStream(java.io.Writer, String)}.
+ *
+ *
* @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(new PrettyPrintWriter(writer), "object-stream");
+ public ObjectOutputStream createObjectOutputStream(final 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.
- *
- *
To change the name of the root element (from <object-stream>), use
- * {@link #createObjectOutputStream(java.io.Writer, String)}.
- *
+ *
+ * To change the name of the root element (from <object-stream>), use
+ * {@link #createObjectOutputStream(java.io.Writer, String)}.
+ *
+ *
* @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 {
+ public ObjectOutputStream createObjectOutputStream(final 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(new PrettyPrintWriter(writer), rootNodeName);
+ public ObjectOutputStream createObjectOutputStream(final Writer writer, final String rootNodeName)
+ throws IOException {
+ return createObjectOutputStream(hierarchicalStreamDriver.createWriter(writer), rootNodeName);
}
/**
+ * Creates an ObjectOutputStream that serializes a stream of objects to the OutputStream using XStream.
+ *
+ * To change the name of the root element (from <object-stream>), use
+ * {@link #createObjectOutputStream(java.io.Writer, String)}.
+ *
+ *
+ * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, String)
+ * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
+ * @since 1.3
+ */
+ public ObjectOutputStream createObjectOutputStream(final 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(final OutputStream out, final String rootNodeName)
+ throws IOException {
+ return createObjectOutputStream(hierarchicalStreamDriver.createWriter(out), rootNodeName);
+ }
+
+ /**
* Creates an ObjectOutputStream that serializes a stream of objects to the writer using XStream.
- *
- *
Because an ObjectOutputStream can contain multiple items and XML only allows a single root node, the stream
- * must be written inside an enclosing node.
- *
- *
It is necessary to call ObjectOutputStream.close() when done, otherwise the stream will be incomplete.
- *
+ *
+ * Because an ObjectOutputStream can contain multiple items and XML only allows a single root node, the stream must
+ * be written inside an enclosing node.
+ *
+ *
+ * It is necessary to call ObjectOutputStream.close() when done, otherwise the stream will be incomplete.
+ *
+ *
* @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 {
- writer.startNode(rootNodeName);
+ @SuppressWarnings("resource")
+ public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer, final 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, writer);
+ @Override
+ public void writeToStream(final Object object) {
+ marshal(object, statefulWriter);
}
- public void writeFieldsToStream(Map fields) throws NotActiveException {
+ @Override
+ public void writeFieldsToStream(final Map fields) throws NotActiveException {
throw new NotActiveException("not in call to writeObject");
}
+ @Override
public void defaultWriteObject() throws NotActiveException {
throw new NotActiveException("not in call to writeObject");
}
+ @Override
public void flush() {
- writer.flush();
+ statefulWriter.flush();
}
+ @Override
public void close() {
- writer.endNode();
- writer.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 {
+ public ObjectInputStream createObjectInputStream(final Reader xmlReader) throws IOException {
return createObjectInputStream(hierarchicalStreamDriver.createReader(xmlReader));
}
/**
- * Creates an ObjectInputStream that deserializes a stream of objects from a reader using XStream.
- *
- *
Example
- *
ObjectInputStream in = xstream.createObjectOutputStream(aReader);
+ * 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(final InputStream in) throws IOException {
+ return createObjectInputStream(hierarchicalStreamDriver.createReader(in));
+ }
+
+ /**
+ * Creates an ObjectInputStream that deserializes a stream of objects from a reader using XStream.
Example
+ *
+ *
+ * ObjectInputStream in = xstream.createObjectOutputStream(aReader);
* int a = out.readInt();
* Object b = out.readObject();
- * Object c = out.readObject();
- *
+ * Object c = out.readObject();
+ *
+ *
* @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() {
+ @Override
public Object readFromStream() throws EOFException {
if (!reader.hasMoreChildren()) {
throw new EOFException();
}
reader.moveDown();
- Object result = unmarshal(reader);
+ final Object result = unmarshal(reader);
reader.moveUp();
return result;
}
- public Map readFieldsFromStream() throws IOException {
+ @Override
+ public Map readFieldsFromStream() throws IOException {
throw new NotActiveException("not in call to readObject");
}
+ @Override
public void defaultReadObject() throws NotActiveException {
throw new NotActiveException("not in call to readObject");
}
- public void registerValidation(ObjectInputValidation validation, int priority) throws NotActiveException {
+ @Override
+ public void registerValidation(final ObjectInputValidation validation, final int priority)
+ throws NotActiveException {
throw new NotActiveException("stream inactive");
}
+ @Override
public void close() {
reader.close();
}
- });
+ }, classLoaderReference);
}
/**
- * Change the ClassLoader XStream uses to load classes.
- *
+ * 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) {
+ public void setClassLoader(final ClassLoader classLoader) {
classLoaderReference.setReference(classLoader);
}
/**
- * Change the ClassLoader XStream uses to load classes.
- *
+ * Retrieve the ClassLoader XStream uses to load classes.
+ *
* @since 1.1.1
*/
public ClassLoader getClassLoader() {
return classLoaderReference.getReference();
}
/**
- * Prevents a field from being serialized.
- *
- * @since 1.2
+ * Retrieve the reference to this instance' ClassLoader. Use this reference for other XStream components (like
+ * converters) to ensure that they will use a changed ClassLoader instance automatically.
+ *
+ * @return the reference
+ * @since 1.4.5
*/
- public void omitField(Class type, String fieldName) {
- fieldAliasingMapper.omitField(type, fieldName);
+ public ClassLoaderReference getClassLoaderReference() {
+ return classLoaderReference;
}
- public static class InitializationException extends BaseException {
- public InitializationException(String message, Throwable cause) {
- super(message, cause);
+ /**
+ * 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(final Class> definedIn, final String fieldName) {
+ if (fieldAliasingMapper == null) {
+ throw new InitializationException("No " + FieldAliasingMapper.class.getName() + " available");
}
+ fieldAliasingMapper.omitField(definedIn, fieldName);
}
+ /**
+ * Ignore all unknown elements.
+ *
+ * @since 1.4.5
+ */
+ public void ignoreUnknownElements() {
+ ignoreUnknownElements(IGNORE_ALL);
+ }
+
+ /**
+ * Add pattern for unknown element names to ignore.
+ *
+ * @param pattern the name pattern as regular expression
+ * @since 1.4.5
+ */
+ public void ignoreUnknownElements(final String pattern) {
+ ignoreUnknownElements(Pattern.compile(pattern));
+ }
+
+ /**
+ * Add pattern for unknown element names to ignore.
+ *
+ * @param pattern the name pattern as regular expression
+ * @since 1.4.5
+ */
+ private void ignoreUnknownElements(final Pattern pattern) {
+ if (fieldAliasingMapper == null) {
+ throw new 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 (annotationMapper == null) {
+ throw new InitializationException("No " + AnnotationMapper.class.getName() + " available");
+ }
+ annotationMapper.processAnnotations(types);
+ }
+
+ /**
+ * 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 true if annotations are auto-detected
+ * @since 1.3
+ */
+ public void autodetectAnnotations(final boolean mode) {
+ if (annotationMapper != null) {
+ annotationMapper.autodetectAnnotations(mode);
+ }
+ }
+
+ /**
+ * Add a new security permission.
+ *
+ * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or
+ * {@link AnyTypePermission} will implicitly wipe any existing permission.
+ *
+ *
+ * @param permission the permission to add
+ * @since 1.4.7
+ */
+ public void addPermission(final TypePermission permission) {
+ if (securityMapper != null) {
+ securityMapper.addPermission(permission);
+ }
+ }
+
+ /**
+ * Add security permission for explicit types by name.
+ *
+ * @param names the type names to allow
+ * @since 1.4.7
+ */
+ public void allowTypes(final 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(final Class>... types) {
+ addPermission(new ExplicitTypePermission(types));
+ }
+
+ /**
+ * Add security permission for a type hierarchy.
+ *
+ * @param type the base type to allow
+ * @since 1.4.7
+ */
+ public void allowTypeHierarchy(final Class> type) {
+ addPermission(new TypeHierarchyPermission(type));
+ }
+
+ /**
+ * Add security permission for types matching one of the specified regular expressions.
+ *
+ * @param regexps the regular expressions to allow type names
+ * @since 1.4.7
+ */
+ public void allowTypesByRegExp(final String... regexps) {
+ addPermission(new RegExpTypePermission(regexps));
+ }
+
+ /**
+ * Add security permission for types matching one of the specified regular expressions.
+ *
+ * @param regexps the regular expressions to allow type names
+ * @since 1.4.7
+ */
+ public void allowTypesByRegExp(final Pattern... regexps) {
+ addPermission(new RegExpTypePermission(regexps));
+ }
+
+ /**
+ * Add security permission for types matching one of the specified wildcard patterns.
+ *
+ * Supported are patterns with path expressions using dot as separator:
+ *
+ *
+ *
?: one non-control character except separator, e.g. for 'java.net.Inet?Address'
+ *
*: arbitrary number of non-control characters except separator, e.g. for types in a package like
+ * 'java.lang.*'
+ *
**: arbitrary number of non-control characters including separator, e.g. for types in a package and
+ * subpackages like 'java.lang.**'
+ *
+ *
+ * @param patterns the patterns to allow type names
+ * @since 1.4.7
+ */
+ public void allowTypesByWildcard(final String... patterns) {
+ addPermission(new WildcardTypePermission(patterns));
+ }
+
+ /**
+ * Add security permission denying another one.
+ *
+ * @param permission the permission to deny
+ * @since 1.4.7
+ */
+ public void denyPermission(final TypePermission permission) {
+ addPermission(new NoPermission(permission));
+ }
+
+ /**
+ * Add security permission forbidding explicit types by name.
+ *
+ * @param names the type names to forbid
+ * @since 1.4.7
+ */
+ public void denyTypes(final String... names) {
+ denyPermission(new ExplicitTypePermission(names));
+ }
+
+ /**
+ * Add security permission forbidding explicit types.
+ *
+ * @param types the types to forbid
+ * @since 1.4.7
+ */
+ public void denyTypes(final Class>... types) {
+ denyPermission(new ExplicitTypePermission(types));
+ }
+
+ /**
+ * Add security permission forbidding a type hierarchy.
+ *
+ * @param type the base type to forbid
+ * @since 1.4.7
+ */
+ public void denyTypeHierarchy(final Class> type) {
+ denyPermission(new TypeHierarchyPermission(type));
+ }
+
+ /**
+ * Add security permission forbidding types matching one of the specified regular expressions.
+ *
+ * @param regexps the regular expressions to forbid type names
+ * @since 1.4.7
+ */
+ public void denyTypesByRegExp(final String... regexps) {
+ denyPermission(new RegExpTypePermission(regexps));
+ }
+
+ /**
+ * Add security permission forbidding types matching one of the specified regular expressions.
+ *
+ * @param regexps the regular expressions to forbid type names
+ * @since 1.4.7
+ */
+ public void denyTypesByRegExp(final Pattern... regexps) {
+ denyPermission(new RegExpTypePermission(regexps));
+ }
+
+ /**
+ * Add security permission forbidding types matching one of the specified wildcard patterns.
+ *
+ * Supported are patterns with path expressions using dot as separator:
+ *
+ *
+ *
?: one non-control character except separator, e.g. for 'java.net.Inet?Address'
+ *
*: arbitrary number of non-control characters except separator, e.g. for types in a package like
+ * 'java.lang.*'
+ *
**: arbitrary number of non-control characters including separator, e.g. for types in a package and
+ * subpackages like 'java.lang.**'
+ *
+ *
+ * @param patterns the patterns to forbid names
+ * @since 1.4.7
+ */
+ public void denyTypesByWildcard(final String... patterns) {
+ denyPermission(new WildcardTypePermission(patterns));
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/XStreamException.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/XStreamException.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/XStreamException.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007, 2008, 2013 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 22. October 2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream;
+
+
+/**
+ * Base exception for all thrown exceptions with XStream.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @since 1.3
+ */
+public class XStreamException extends RuntimeException {
+
+ /**
+ * Default constructor.
+ *
+ * @since 1.3
+ */
+ protected XStreamException() {
+ this("", null);
+ }
+
+ /**
+ * Constructs an XStreamException with a message.
+ *
+ * @param message
+ * @since 1.3
+ */
+ public XStreamException(String message) {
+ this(message, null);
+ }
+
+ /**
+ * Constructs an XStreamException as wrapper for a different causing {@link Throwable}.
+ *
+ * @param cause
+ * @since 1.3
+ */
+ public XStreamException(Throwable cause) {
+ this("", cause);
+ }
+
+ /**
+ * Constructs an XStreamException with a message as wrapper for a different causing
+ * {@link Throwable}.
+ *
+ * @param message
+ * @param cause
+ * @since 1.3
+ */
+ public XStreamException(String message, Throwable cause) {
+ super(message + (cause == null ? "" : " : " + cause.getMessage()), cause);
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/XStreamer.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/XStreamer.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/XStreamer.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2006, 2007, 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 13. April 2006 by Joerg Schaible
+ */
+package com.thoughtworks.xstream;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.xml.datatype.DatatypeFactory;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.ConverterLookup;
+import com.thoughtworks.xstream.converters.ConverterMatcher;
+import com.thoughtworks.xstream.converters.ConverterRegistry;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.javabean.JavaBeanProvider;
+import com.thoughtworks.xstream.converters.reflection.FieldKeySorter;
+import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
+import com.thoughtworks.xstream.core.JVM;
+import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.naming.NameCoder;
+import com.thoughtworks.xstream.io.xml.XppDriver;
+import com.thoughtworks.xstream.mapper.Mapper;
+import com.thoughtworks.xstream.security.TypeHierarchyPermission;
+import com.thoughtworks.xstream.security.TypePermission;
+import com.thoughtworks.xstream.security.WildcardTypePermission;
+
+
+/**
+ * Self-contained XStream generator. The class is a utility to write XML streams that contain additionally the XStream
+ * that was used to serialize the object graph. Such a stream can be unmarshalled using this embedded XStream instance,
+ * that kept any settings.
+ *
+ * @author Jörg Schaible
+ * @since 1.2
+ */
+public class XStreamer {
+
+ private final static TypePermission[] PERMISSIONS = {
+ new TypeHierarchyPermission(ConverterMatcher.class), new TypeHierarchyPermission(Mapper.class),
+ new TypeHierarchyPermission(XStream.class), new TypeHierarchyPermission(ReflectionProvider.class),
+ new TypeHierarchyPermission(JavaBeanProvider.class), new TypeHierarchyPermission(FieldKeySorter.class),
+ new TypeHierarchyPermission(ConverterLookup.class), new TypeHierarchyPermission(ConverterRegistry.class),
+ new TypeHierarchyPermission(HierarchicalStreamDriver.class),
+ new TypeHierarchyPermission(MarshallingStrategy.class), new TypeHierarchyPermission(MarshallingContext.class),
+ new TypeHierarchyPermission(UnmarshallingContext.class), new TypeHierarchyPermission(NameCoder.class),
+ new TypeHierarchyPermission(TypePermission.class),
+ new WildcardTypePermission(JVM.class.getPackage().getName() + ".**"),
+ new TypeHierarchyPermission(DatatypeFactory.class) // required by DurationConverter
+ };
+
+ /**
+ * Serialize an object including the XStream to a pretty-printed XML String.
+ *
+ * @throws ObjectStreamException if the XML contains non-serializable elements
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be serialized
+ * @since 1.2
+ * @see #toXML(XStream, Object, Writer)
+ */
+ public String toXML(final XStream xstream, final Object obj) throws ObjectStreamException {
+ final Writer writer = new StringWriter();
+ try {
+ toXML(xstream, obj, writer);
+ } catch (final ObjectStreamException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new ConversionException("Unexpected IO error from a StringWriter", e);
+ }
+ return writer.toString();
+ }
+
+ /**
+ * Serialize an object including the XStream to the given Writer as pretty-printed XML.
+ *
+ * Warning: XStream will serialize itself into this XML stream. To read such an XML code, you should use
+ * {@link XStreamer#fromXML(Reader)} or one of the other overloaded methods. Since a lot of internals are written
+ * into the stream, you cannot expect to use such an XML to work with another XStream version or with XStream
+ * running on different JDKs and/or versions. We have currently no JDK 1.3 support, nor will the
+ * PureReflectionConverter work with a JDK less than 1.5.
+ *
+ *
+ * @throws IOException if an error occurs reading from the Writer.
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be serialized
+ * @since 1.2
+ */
+ public void toXML(final XStream xstream, final Object obj, final Writer out) throws IOException {
+ final XStream outer = new XStream();
+ final ObjectOutputStream oos = outer.createObjectOutputStream(out);
+ try {
+ oos.writeObject(xstream);
+ oos.flush();
+ xstream.toXML(obj, out);
+ } finally {
+ oos.close();
+ }
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from a String. The method will use internally an XppDriver to
+ * load the contained XStream instance with default permissions.
+ *
+ * @param xml the XML data
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws ObjectStreamException if the XML contains non-deserializable elements
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.2
+ * @see #toXML(XStream, Object, Writer)
+ */
+ public T fromXML(final String xml) throws ClassNotFoundException, ObjectStreamException {
+ try {
+ return fromXML(new StringReader(xml));
+ } catch (final ObjectStreamException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new ConversionException("Unexpected IO error from a StringReader", e);
+ }
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from a String. The method will use internally an XppDriver to
+ * load the contained XStream instance.
+ *
+ * @param xml the XML data
+ * @param permissions the permissions to use (ensure that they include the defaults)
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws ObjectStreamException if the XML contains non-deserializable elements
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.4.7
+ * @see #toXML(XStream, Object, Writer)
+ */
+ public T fromXML(final String xml, final TypePermission... permissions)
+ throws ClassNotFoundException, ObjectStreamException {
+ try {
+ return fromXML(new StringReader(xml), permissions);
+ } catch (final ObjectStreamException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new ConversionException("Unexpected IO error from a StringReader", e);
+ }
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from a String.
+ *
+ * @param driver the implementation to use
+ * @param xml the XML data
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws ObjectStreamException if the XML contains non-deserializable elements
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.2
+ * @see #toXML(XStream, Object, Writer)
+ */
+ public T fromXML(final HierarchicalStreamDriver driver, final String xml)
+ throws ClassNotFoundException, ObjectStreamException {
+ try {
+ return fromXML(driver, new StringReader(xml));
+ } catch (final ObjectStreamException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new ConversionException("Unexpected IO error from a StringReader", e);
+ }
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from a String.
+ *
+ * @param driver the implementation to use
+ * @param xml the XML data
+ * @param permissions the permissions to use (ensure that they include the defaults)
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws ObjectStreamException if the XML contains non-deserializable elements
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.4.7
+ * @see #toXML(XStream, Object, Writer)
+ */
+ public T fromXML(final HierarchicalStreamDriver driver, final String xml, final TypePermission... permissions)
+ throws ClassNotFoundException, ObjectStreamException {
+ try {
+ return fromXML(driver, new StringReader(xml), permissions);
+ } catch (final ObjectStreamException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new ConversionException("Unexpected IO error from a StringReader", e);
+ }
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from an XML Reader. The method will use internally an XppDriver
+ * to load the contained XStream instance with default permissions.
+ *
+ * @param xml the {@link Reader} providing the XML data
+ * @throws IOException if an error occurs reading from the Reader.
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.2
+ * @see #toXML(XStream, Object, Writer)
+ */
+ public T fromXML(final Reader xml) throws IOException, ClassNotFoundException {
+ return fromXML(new XppDriver(), xml);
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from an XML Reader. The method will use internally an XppDriver
+ * to load the contained XStream instance.
+ *
+ * @param xml the {@link Reader} providing the XML data
+ * @param permissions the permissions to use (ensure that they include the defaults)
+ * @throws IOException if an error occurs reading from the Reader.
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.4.7
+ * @see #toXML(XStream, Object, Writer)
+ */
+ public T fromXML(final Reader xml, final TypePermission... permissions)
+ throws IOException, ClassNotFoundException {
+ return fromXML(new XppDriver(), xml, permissions);
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from an XML Reader.
+ *
+ * @param driver the implementation to use
+ * @param xml the {@link Reader} providing the XML data
+ * @throws IOException if an error occurs reading from the Reader.
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.2
+ */
+ public T fromXML(final HierarchicalStreamDriver driver, final Reader xml)
+ throws IOException, ClassNotFoundException {
+ return fromXML(driver, xml, PERMISSIONS);
+ }
+
+ /**
+ * Deserialize a self-contained XStream with object from an XML Reader.
+ *
+ * @param driver the implementation to use
+ * @param xml the {@link Reader} providing the XML data
+ * @param permissions the permissions to use (ensure that they include the defaults)
+ * @throws IOException if an error occurs reading from the Reader.
+ * @throws ClassNotFoundException if a class in the XML stream cannot be found
+ * @throws com.thoughtworks.xstream.XStreamException if the object cannot be deserialized
+ * @since 1.4.7
+ */
+ public T fromXML(final HierarchicalStreamDriver driver, final Reader xml, final TypePermission... permissions)
+ throws IOException, ClassNotFoundException {
+ final XStream outer = new XStream(driver);
+ for (final TypePermission permission : permissions) {
+ outer.addPermission(permission);
+ }
+ final HierarchicalStreamReader reader = driver.createReader(xml);
+ final ObjectInputStream configIn = outer.createObjectInputStream(reader);
+ try {
+ final XStream configured = (XStream)configIn.readObject();
+ final ObjectInputStream in = configured.createObjectInputStream(reader);
+ try {
+ @SuppressWarnings("unchecked")
+ final T t = (T)in.readObject();
+ return t;
+ } finally {
+ in.close();
+ }
+ } finally {
+ configIn.close();
+ }
+ }
+
+ /**
+ * Retrieve the default permissions to unmarshal an XStream instance.
+ *
+ * The returned list will only cover permissions for XStream's own types. If your custom converters or mappers keep
+ * references to other types, you will have to add permission for those types on your own.
+ *
+ *
+ * @since 1.4.7
+ */
+ public static TypePermission[] getDefaultPermissions() {
+ return PERMISSIONS.clone();
+ }
+}
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/alias/CannotResolveClassException.java'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/alias/ClassMapper.java'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/alias/NameMapper.java'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/Annotations.java'.
Fisheye: No comparison available. Pass `N' to diff?
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAlias.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAlias.java (.../XStreamAlias.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAlias.java (.../XStreamAlias.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,19 +1,39 @@
+/*
+ * Copyright (C) 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2013 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 11. August 2005 by Mauro Talevi
+ */
package com.thoughtworks.xstream.annotations;
+import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
- * Annotation used to define an XStream class or field value. This annotation should only be used with classes and fields
+ * Annotation used to define an XStream class or field alias.
*
* @author Emil Kirschner
* @author Chung-Onn Cheong
+ * @see com.thoughtworks.xstream.XStream#alias(String, Class)
+ * @see com.thoughtworks.xstream.XStream#alias(String, Class, Class)
+ * @see com.thoughtworks.xstream.XStream#addDefaultImplementation(Class, Class)
*/
@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
public @interface XStreamAlias {
/**
- * The value of the class or field value
+ * The name of the class or field alias.
*/
public String value();
+ /**
+ * A possible default implementation if the annotated type is an interface.
+ */
public Class> impl() default Void.class; //Use Void to denote as Null
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAliasType.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAliasType.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAliasType.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 XStream Committers.
+ * All rights reserved.
+ *
+ * Created on 12.07.2013 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotation used to define an XStream type alias.
+ *
+ * @author Jörg Schaible
+ * @since 1.4.5
+ * @see com.thoughtworks.xstream.XStream#aliasType(String, Class)
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface XStreamAliasType {
+ /**
+ * The name of the type alias.
+ */
+ public String value();
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAsAttribute.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAsAttribute.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamAsAttribute.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2006, 2007 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 24. December 2006 by Guilherme Silveira
+ */
+package com.thoughtworks.xstream.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines that a field should be serialized as an attribute.
+ *
+ * @author Guilherme Silveira
+ * @since 1.2.2
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Documented
+public @interface XStreamAsAttribute {
+}
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamContainedType.java'.
Fisheye: No comparison available. Pass `N' to diff?
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamConverter.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamConverter.java (.../XStreamConverter.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamConverter.java (.../XStreamConverter.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,18 +1,109 @@
+/*
+ * Copyright (C) 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 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 16. September 2005 by Mauro Talevi
+ */
package com.thoughtworks.xstream.annotations;
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.ConverterMatcher;
+
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import com.thoughtworks.xstream.converters.Converter;
/**
+ * Annotation to declare a converter. The annotation supports additionally the injection of
+ * various constructor arguments provided by XStream:
+ *
+ *
{@link com.thoughtworks.xstream.mapper.Mapper}: The current mapper chain of the XStream
+ * instance.
+ *
{@link com.thoughtworks.xstream.core.ClassLoaderReference}: The reference to the class
+ * loader used by the XStream instance to deserialize the objects.
+ *
{@link com.thoughtworks.xstream.converters.reflection.ReflectionProvider}: The reflection
+ * provider used by the reflection based converters of the current XStream instance.
+ *
{@link com.thoughtworks.xstream.converters.ConverterLookup}: The lookup for converters
+ * handling a special type.
+ *
All elements provided with the individual arrays of this annotation. The provided values
+ * follow the declaration sequence if a constructor requires multiple arguments of the same
+ * type.
+ *
{@link Class}: The type of the element where the annotation is declared. Note, that this
+ * argument is not supported when using
+ * {@link com.thoughtworks.xstream.annotations.XStreamConverters} or {@link #useImplicitType()}
+ * == false.
+ *
{@link com.thoughtworks.xstream.core.JVM}: Utility e.g. to load classes.
+ *
{@link ClassLoader} (deprecated since 1.4.5): The class loader used by the XStream
+ * instance to deserialize the objects. Use ClassLoaderReference as argument
+ *
+ *
+ * The algorithm will try the converter's constructor with the most arguments first.
+ *
+ *
+ * Note, the annotation matches a {@link ConverterMatcher}.
+ * {@link com.thoughtworks.xstream.converters.Converter} as well as
+ * {@link com.thoughtworks.xstream.converters.SingleValueConverter} extend this interface. The
+ * {@link com.thoughtworks.xstream.mapper.AnnotationMapper} can only handle these two
+ * known types.
+ *
*
* @author Chung-Onn Cheong
+ * @author Jörg Schaible
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
+@Target({ElementType.TYPE, ElementType.FIELD})
+@Documented
public @interface XStreamConverter {
- Class extends Converter> value();
+ Class extends ConverterMatcher> value();
+
+ int priority() default XStream.PRIORITY_NORMAL;
+
+ /**
+ * Flag to provide the current type as implicit first Class argument to a converter's
+ * constructor.
+ *
+ * @return true if the current type is provided
+ * @since 1.4.5
+ */
+ boolean useImplicitType() default true;
+
+ /**
+ * Provide class types as arguments for the converter's constructor arguments.
+ *
+ * Note, that XStream itself provides the current class type as first Class argument to a
+ * constructor, if the annotation is added directly to a class type (and not as part of a
+ * parameter declaration of a {@link XStreamConverters} annotation). The current type has
+ * precedence over any type provided with this method. This behavior can be overridden
+ * setting {@link #useImplicitType()} to false.
+ *
+ * @return the types
+ * @since 1.4.2
+ */
+ Class>[] types() default {};
+
+ String[] strings() default {};
+
+ byte[] bytes() default {};
+
+ char[] chars() default {};
+
+ short[] shorts() default {};
+
+ int[] ints() default {};
+
+ long[] longs() default {};
+
+ float[] floats() default {};
+
+ double[] doubles() default {};
+
+ boolean[] booleans() default {};
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamConverters.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamConverters.java (.../XStreamConverters.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamConverters.java (.../XStreamConverters.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,3 +1,14 @@
+/*
+ * Copyright (C) 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007 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 16. September 2005 by Mauro Talevi
+ */
package com.thoughtworks.xstream.annotations;
import java.lang.annotation.ElementType;
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamImplicit.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamImplicit.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamImplicit.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006, 2007, 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 01. December 2006 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation for marking a field as an implicit collection or array.
+ *
+ * @author Lucio Benfante
+ * @author Jörg Schaible
+ * @since 1.2.2
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface XStreamImplicit {
+ /**
+ * Element name of the implicit collection.
+ */
+ String itemFieldName() default "";
+ /**
+ * Field name of map entries that are used as key for the element in the implicit map.
+ * @since 1.4
+ */
+ String keyFieldName() default "";
+}
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamImplicitCollection.java'.
Fisheye: No comparison available. Pass `N' to diff?
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamInclude.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamInclude.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamInclude.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 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 13. November 2008 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to force automated processing of further classes.
+ *
+ * @author Steven Sparling
+ * @since 1.3.1
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface XStreamInclude
+{
+ public Class>[] value();
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamOmitField.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamOmitField.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/annotations/XStreamOmitField.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2007 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 06. May 2005 by Guilherme Silveira
+ */
+package com.thoughtworks.xstream.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Declares a field to be omitted. The result is the same as invoking the method
+ * omitField in a XStream instance.
+ *
+ * @author Chung-Onn Cheong
+ * @author Guilherme Silveira
+ * @since 1.2.2
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @ interface XStreamOmitField {
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConversionException.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConversionException.java (.../ConversionException.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConversionException.java (.../ConversionException.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,87 +1,115 @@
+/*
+ * Copyright (C) 2003, 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 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 26. September 2003 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters;
-import com.thoughtworks.xstream.core.BaseException;
-
-import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.Map;
+import com.thoughtworks.xstream.XStreamException;
+
+
/**
- * Thrown by {@link Converter} implementations when they cannot convert an object
- * to/from textual data.
- *
- * When this exception is thrown it can be passed around to things that accept an
- * {@link ErrorWriter}, allowing them to add diagnostics to the stack trace.
- *
+ * Thrown by {@link Converter} implementations when they cannot convert an object to/from textual data. When this
+ * exception is thrown it can be passed around to things that accept an {@link ErrorWriter}, allowing them to add
+ * diagnostics to the stack trace.
+ *
* @author Joe Walnes
- *
+ * @author Jörg Schaible
* @see ErrorWriter
*/
-public class ConversionException extends BaseException implements ErrorWriter {
+public class ConversionException extends XStreamException implements ErrorWriter {
- private Map stuff = new HashMap();
+ private static final String SEPARATOR = "\n-------------------------------";
+ private final Map stuff = new LinkedHashMap();
- /**
- * Plays nice with JDK1.3 and JDK1.4
- */
- protected Exception cause;
-
- public ConversionException(String msg, Exception cause) {
- super(msg);
+ public ConversionException(final String msg, final Throwable cause) {
+ super(msg, cause);
if (msg != null) {
add("message", msg);
}
if (cause != null) {
add("cause-exception", cause.getClass().getName());
- add("cause-message", cause.getMessage());
- this.cause = cause;
+ add("cause-message", cause instanceof ConversionException
+ ? ((ConversionException)cause).getShortMessage()
+ : cause.getMessage());
}
}
- public ConversionException(String msg) {
+ public ConversionException(final String msg) {
super(msg);
}
- public ConversionException(Exception cause) {
+ public ConversionException(final Throwable cause) {
this(cause.getMessage(), cause);
}
- public String get(String errorKey) {
- return (String) stuff.get(errorKey);
+ @Override
+ public String get(final String errorKey) {
+ return stuff.get(errorKey);
}
- public void add(String name, String information) {
- stuff.put(name, information);
+ @Override
+ public void add(final String name, final String information) {
+ String key = name;
+ int i = 0;
+ while (stuff.containsKey(key)) {
+ final String value = stuff.get(key);
+ if (information.equals(value)) {
+ return;
+ }
+ key = name + "[" + ++i + "]";
+ }
+ stuff.put(key, information);
}
- public Iterator keys() {
+ @Override
+ public void set(final String name, final String information) {
+ String key = name;
+ int i = 0;
+ stuff.put(key, information); // keep order
+ while (stuff.containsKey(key)) {
+ if (i != 0) {
+ stuff.remove(key);
+ }
+ key = name + "[" + ++i + "]";
+ }
+ }
+
+ @Override
+ public Iterator keys() {
return stuff.keySet().iterator();
}
+ @Override
public String getMessage() {
- StringBuffer result = new StringBuffer();
+ final StringBuilder result = new StringBuilder();
if (super.getMessage() != null) {
result.append(super.getMessage());
}
- result.append("\n---- Debugging information ----");
- for (Iterator iterator = keys(); iterator.hasNext();) {
- String k = (String) iterator.next();
- String v = get(k);
+ if (!result.toString().endsWith(SEPARATOR)) {
+ result.append("\n---- Debugging information ----");
+ }
+ for (final Iterator iterator = keys(); iterator.hasNext();) {
+ final String k = iterator.next();
+ final String v = get(k);
result.append('\n').append(k);
- int padding = 20 - k.length();
- for (int i = 0; i < padding; i++) {
- result.append(' ');
- }
- result.append(": ").append(v).append(' ');
+ result.append(" ".substring(Math.min(20, k.length())));
+ result.append(": ").append(v);
}
- result.append("\n-------------------------------");
+ result.append(SEPARATOR);
return result.toString();
}
- public Throwable getCause() {
- return cause;
- }
-
public String getShortMessage() {
return super.getMessage();
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/Converter.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/Converter.java (.../Converter.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/Converter.java (.../Converter.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,59 +1,66 @@
+/*
+ * Copyright (C) 2003, 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 26. September 2003 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+
/**
- * Converter implementations are responsible marshalling Java objects
- * to/from textual data.
- *
- *
If an exception occurs during processing, a {@link ConversionException}
- * should be thrown.
- *
- *
If working with the high level {@link com.thoughtworks.xstream.XStream} facade,
- * you can register new converters using the XStream.registerConverter() method.
- *
- *
If working with the lower level API, the
- * {@link com.thoughtworks.xstream.converters.ConverterLookup} implementation is
- * responsible for looking up the appropriate converter.
- *
- *
{@link com.thoughtworks.xstream.converters.basic.AbstractBasicConverter}
- * provides a starting point for objects that can store all information
- * in a single String.
- *
- *
{@link com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter}
- * provides a starting point for objects that hold a collection of other objects
- * (such as Lists and Maps).
+ * If an exception occurs during processing, a {@link ConversionException} should be thrown.
+ *
+ *
+ * If working with the high level {@link com.thoughtworks.xstream.XStream} facade, you can register new converters using
+ * the XStream.registerConverter() method.
+ *
+ *
+ * If working with the lower level API, the {@link com.thoughtworks.xstream.converters.ConverterLookup} implementation
+ * is responsible for looking up the appropriate converter.
+ *
+ *
+ * Converters for object that can store all information in a single value should implement
+ * {@link com.thoughtworks.xstream.converters.SingleValueConverter}.
+ * {@link com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter} provides a starting point.
+ *
+ *
+ * {@link com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter} provides a starting point for
+ * objects that hold a collection of other objects (such as Lists and Maps).
+ *
+ *
* @author Joe Walnes
* @see com.thoughtworks.xstream.XStream
* @see com.thoughtworks.xstream.converters.ConverterLookup
- * @see com.thoughtworks.xstream.converters.basic.AbstractBasicConverter
+ * @see com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter
* @see com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter
*/
-public interface Converter {
+public interface Converter extends ConverterMatcher {
/**
- * Called by XStream to determine whether to use this converter
- * instance to marshall a particular type.
- */
- boolean canConvert(Class type);
-
- /**
* Convert an object to textual data.
- *
- * @param source The object to be marshalled.
- * @param writer A stream to write to.
- * @param context A context that allows nested objects to be processed by XStream.
+ *
+ * @param source the object to be marshalled.
+ * @param writer a stream to write to.
+ * @param context a context that allows nested objects to be processed by XStream.
*/
void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context);
/**
* Convert textual data back into an object.
- *
- * @param reader The stream to read the text from.
- * @param context
- * @return The resulting object.
+ *
+ * @param reader the stream to read the text from.
+ * @param context a context that allows nested objects to be processed by XStream.
+ * @return the resulting object.
*/
Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context);
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterLookup.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterLookup.java (.../ConverterLookup.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterLookup.java (.../ConverterLookup.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,24 +1,30 @@
+/*
+ * Copyright (C) 2003, 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 26. September 2003 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters;
/**
* Responsible for looking up the correct Converter implementation for a specific type.
- *
+ *
* @author Joe Walnes
* @see Converter
*/
public interface ConverterLookup {
/**
* Lookup a converter for a specific type.
- *
- * This type may be any Class, including primitive and array types. It may also be null, signifying
- * the value to be converted is a null type.
+ *
+ * This type may be any Class, including primitive and array types. It may also be null, signifying the value to be
+ * converted is a null type.
+ *
*/
- Converter lookupConverterForType(Class type);
-
- /**
- * @deprecated As of 1.1.1 you can register Converters with priorities, making the need for a default converter redundant.
- */
- Converter defaultConverter();
-
+ Converter lookupConverterForType(Class> type);
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterMatcher.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterMatcher.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterMatcher.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006, 2007, 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 15. February 2006 by Mauro Talevi
+ */
+package com.thoughtworks.xstream.converters;
+
+/**
+ * ConverterMatcher allows to match converters to classes by determining if a given type can be converted by the
+ * converter instance. ConverterMatcher is the base interface of any converter.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @author Mauro Talevi
+ * @see com.thoughtworks.xstream.converters.Converter
+ * @see com.thoughtworks.xstream.converters.SingleValueConverter
+ * @since 1.2
+ */
+public interface ConverterMatcher {
+
+ /**
+ * Determines whether the converter can marshal a particular type.
+ *
+ * @param type the Class representing the object type to be converted
+ */
+ boolean canConvert(Class> type);
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterRegistry.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterRegistry.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/ConverterRegistry.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2008 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 01. January 2008 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters;
+
+/**
+ * An interface for the converter management.
+ *
+ * @author Jörg Schaible
+ * @since 1.3
+ */
+public interface ConverterRegistry {
+
+ void registerConverter(Converter converter, int priority);
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/DataHolder.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/DataHolder.java (.../DataHolder.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/DataHolder.java (.../DataHolder.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,16 +1,29 @@
+/*
+ * Copyright (C) 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 16. August 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters;
import java.util.Iterator;
+
/**
* Holds generic data, to be used as seen fit by the user.
- *
+ *
* @author Joe Walnes
*/
public interface DataHolder {
Object get(Object key);
+
void put(Object key, Object value);
- Iterator keys();
+ Iterator
- */
-public class BeanProvider {
-// private final Map serializedDataCache = Collections.synchronizedMap(new HashMap());
-//
- protected PropertyDictionary propertyDictionary = new PropertyDictionary();
-
+public class BeanProvider implements JavaBeanProvider {
+
+ /**
+ * @deprecated As of 1.4.6
+ */
+ @Deprecated
protected static final Object[] NO_PARAMS = new Object[0];
+ protected PropertyDictionary propertyDictionary;
- public Object newInstance(Class type) {
+ /**
+ * Construct a BeanProvider that will process the bean properties in their natural order.
+ */
+ public BeanProvider() {
+ this(new PropertyDictionary(new NativePropertySorter()));
+ }
+
+ /**
+ * Construct a BeanProvider with a comparator to sort the bean properties by name in the dictionary.
+ *
+ * @param propertyNameComparator the comparator
+ */
+ public BeanProvider(final Comparator propertyNameComparator) {
+ this(new PropertyDictionary(new ComparingPropertySorter(propertyNameComparator)));
+ }
+
+ /**
+ * Construct a BeanProvider with a provided property dictionary.
+ *
+ * @param propertyDictionary the property dictionary to use
+ * @since 1.4
+ */
+ public BeanProvider(final PropertyDictionary propertyDictionary) {
+ this.propertyDictionary = propertyDictionary;
+ }
+
+ @Override
+ public Object newInstance(final Class> type) {
try {
- return getDefaultConstrutor(type).newInstance(NO_PARAMS);
- } catch (InstantiationException e) {
+ return type.newInstance();
+ } catch (final InstantiationException e) {
throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (IllegalAccessException e) {
+ } catch (final IllegalAccessException e) {
throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (InvocationTargetException e) {
- if (e.getTargetException() instanceof RuntimeException) {
- throw (RuntimeException) e.getTargetException();
- } else if (e.getTargetException() instanceof Error) {
- throw (Error) e.getTargetException();
- } else {
- throw new ObjectAccessException("Constructor for " + type.getName()
- + " threw an exception", e);
- }
+ } catch (final SecurityException e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ } catch (final ExceptionInInitializerError e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
}
}
-// private Object instantiateUsingSerialization(Class type) {
-// try {
-// byte[] data;
-// if (serializedDataCache.containsKey(type)) {
-// data = (byte[]) serializedDataCache.get(type);
-// } else {
-// ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-// DataOutputStream stream = new DataOutputStream(bytes);
-// stream.writeShort(ObjectStreamConstants.STREAM_MAGIC);
-// stream.writeShort(ObjectStreamConstants.STREAM_VERSION);
-// stream.writeByte(ObjectStreamConstants.TC_OBJECT);
-// stream.writeByte(ObjectStreamConstants.TC_CLASSDESC);
-// stream.writeUTF(type.getName());
-// stream.writeLong(ObjectStreamClass.lookup(type).getSerialVersionUID());
-// stream.writeByte(2); // classDescFlags (2 = Serializable)
-// stream.writeShort(0); // field count
-// stream.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
-// stream.writeByte(ObjectStreamConstants.TC_NULL);
-// data = bytes.toByteArray();
-// serializedDataCache.put(type, data);
-// }
-//
-// ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
-// return in.readObject();
-// } catch (IOException e) {
-// throw new ObjectAccessException("", e);
-// } catch (ClassNotFoundException e) {
-// throw new ObjectAccessException("", e);
-// }
-// }
-
- public void visitSerializableProperties(Object object, Visitor visitor) {
- for (Iterator iterator = propertyDictionary.serializablePropertiesFor(object.getClass()); iterator
- .hasNext();) {
- BeanProperty property = (BeanProperty) iterator.next();
+ @Override
+ public void visitSerializableProperties(final Object object, final JavaBeanProvider.Visitor visitor) {
+ final PropertyDescriptor[] propertyDescriptors = getSerializableProperties(object);
+ for (final PropertyDescriptor property : propertyDescriptors) {
try {
- Object value = property.get(object);
- visitor.visit(property.getName(), property.getType(), value);
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not get property " + property.getClass()
- + "." + property.getName(), e);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not get property " + property.getClass()
- + "." + property.getName(), e);
+ final Method readMethod = property.getReadMethod();
+ final String name = property.getName();
+ final Class> definedIn = readMethod.getDeclaringClass();
+ if (visitor.shouldVisit(name, definedIn)) {
+ final Object value = readMethod.invoke(object);
+ visitor.visit(name, property.getPropertyType(), definedIn, value);
+ }
+ } catch (final IllegalArgumentException e) {
+ throw new ObjectAccessException("Could not get property "
+ + object.getClass()
+ + "."
+ + property.getName(), e);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Could not get property "
+ + object.getClass()
+ + "."
+ + property.getName(), e);
+ } catch (final InvocationTargetException e) {
+ throw new ObjectAccessException("Could not get property "
+ + object.getClass()
+ + "."
+ + property.getName(), e);
}
}
}
- public void writeProperty(Object object, String propertyName, Object value) {
- BeanProperty property = propertyDictionary.property(object.getClass(), propertyName);
+ @Override
+ public void writeProperty(final Object object, final String propertyName, final Object value) {
+ final PropertyDescriptor property = getProperty(propertyName, object.getClass());
try {
- property.set(object, value);
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not set property " + object.getClass() + "."
- + property.getName(), e);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not set property " + object.getClass() + "."
- + property.getName(), e);
+ property.getWriteMethod().invoke(object, new Object[]{value});
+ } catch (final IllegalArgumentException e) {
+ throw new ObjectAccessException("Could not set property " + object.getClass() + "." + property.getName(), e);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Could not set property " + object.getClass() + "." + property.getName(), e);
+ } catch (final InvocationTargetException e) {
+ throw new ObjectAccessException("Could not set property " + object.getClass() + "." + property.getName(), e);
}
}
- public Class getPropertyType(Object object, String name) {
- return propertyDictionary.property(object.getClass(), name).getType();
+ @Override
+ public Class> getPropertyType(final Object object, final String name) {
+ return getProperty(name, object.getClass()).getPropertyType();
}
- public boolean propertyDefinedInClass(String name, Class type) {
- return propertyDictionary.property(type, name) != null;
+ @Override
+ public boolean propertyDefinedInClass(final String name, final Class> type) {
+ return getProperty(name, type) != null;
}
/**
* Returns true if the Bean provider can instantiate the specified class
*/
- public boolean canInstantiate(Class type) {
- return getDefaultConstrutor(type) != null;
+ @Override
+ public boolean canInstantiate(final Class> type) {
+ try {
+ return newInstance(type) != null;
+ } catch (final ObjectAccessException e) {
+ return false;
+ }
}
-
+
/**
* Returns the default constructor, or null if none is found
+ *
* @param type
- * @return
+ * @deprecated As of 1.4.6 use {@link #newInstance(Class)} or {@link #canInstantiate(Class)} directly.
*/
- protected Constructor getDefaultConstrutor(Class type) {
- Constructor[] constructors = type.getConstructors();
- for (int i = 0; i < constructors.length; i++) {
- Constructor c = constructors[i];
- if (c.getParameterTypes().length == 0 && Modifier.isPublic(c.getModifiers()))
+ @Deprecated
+ protected Constructor> getDefaultConstrutor(final Class> type) {
+
+ final Constructor>[] constructors = type.getConstructors();
+ for (final Constructor> c : constructors) {
+ if (c.getParameterTypes().length == 0 && Modifier.isPublic(c.getModifiers())) {
return c;
+ }
}
return null;
}
-
- interface Visitor {
- void visit(String name, Class type, Object value);
+
+ protected PropertyDescriptor[] getSerializableProperties(final Object object) {
+ final List result = new ArrayList();
+ for (final Iterator iter = propertyDictionary.propertiesFor(object.getClass()); iter
+ .hasNext();) {
+ final PropertyDescriptor descriptor = iter.next();
+ if (canStreamProperty(descriptor)) {
+ result.add(descriptor);
+ }
+ }
+ return result.toArray(new PropertyDescriptor[result.size()]);
}
-}
\ No newline at end of file
+ protected boolean canStreamProperty(final PropertyDescriptor descriptor) {
+ return descriptor.getReadMethod() != null && descriptor.getWriteMethod() != null;
+ }
+
+ public boolean propertyWriteable(final String name, final Class> type) {
+ final PropertyDescriptor property = getProperty(name, type);
+ return property.getWriteMethod() != null;
+ }
+
+ protected PropertyDescriptor getProperty(final String name, final Class> type) {
+ return propertyDictionary.propertyDescriptor(type, name);
+ }
+
+ /**
+ * @deprecated As of 1.4 use {@link JavaBeanProvider.Visitor}
+ */
+ @Deprecated
+ public interface Visitor extends JavaBeanProvider.Visitor {}
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/ComparingPropertySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/ComparingPropertySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/ComparingPropertySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011, 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 16. July 2011 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.javabean;
+
+import java.beans.PropertyDescriptor;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+/**
+ * A sorter that uses a comparator to determine the order of the bean properties.
+ *
+ * @author Jörg Schaible
+ * @since 1.4
+ */
+public class ComparingPropertySorter implements PropertySorter {
+
+ private final Comparator comparator;
+
+ public ComparingPropertySorter(final Comparator propertyNameComparator) {
+ comparator = propertyNameComparator;
+ }
+
+ @Override
+ public Map sort(final Class> type, final Map nameMap) {
+ final TreeMap map = new TreeMap(comparator);
+ map.putAll(nameMap);
+ return map;
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java (.../JavaBeanConverter.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java (.../JavaBeanConverter.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,116 +1,167 @@
+/*
+ * Copyright (C) 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 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 12. April 2005 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.javabean;
-import com.thoughtworks.xstream.alias.ClassMapper;
+import java.util.HashSet;
+import java.util.Set;
+
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.reflection.MissingFieldException;
+import com.thoughtworks.xstream.core.util.FastField;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
/**
- * Can convert any bean with a public default constructor. BeanInfo are not
- * taken into consideration, this class looks for bean patterns for simple
- * properties
+ * Can convert any bean with a public default constructor. The {@link BeanProvider} used as default is based on
+ * {@link java.beans.BeanInfo}. Indexed properties are currently not supported.
*/
public class JavaBeanConverter implements Converter {
- /**
- * TODO:
- * - use bean introspection instead of reflection.
- * - support indexed properties
- * - ignore default values
- * - use BeanInfo
- */
- private ClassMapper classMapper;
+ /* TODO: - support indexed properties - support attributes (XSTR-620) - support local converters (XSTR-601) Problem:
+ * Mappers take definitions based on reflection, they don't know about bean info */
+ protected final Mapper mapper;
+ protected final JavaBeanProvider beanProvider;
+ private final Class> type;
- private String classAttributeIdentifier;
+ public JavaBeanConverter(final Mapper mapper) {
+ this(mapper, (Class>)null);
+ }
- private BeanProvider beanProvider;
+ public JavaBeanConverter(final Mapper mapper, final Class> type) {
+ this(mapper, new BeanProvider(), type);
+ }
- public JavaBeanConverter(ClassMapper classMapper, String classAttributeIdentifier) {
- this.classMapper = classMapper;
- this.classAttributeIdentifier = classAttributeIdentifier;
- this.beanProvider = new BeanProvider();
+ public JavaBeanConverter(final Mapper mapper, final JavaBeanProvider beanProvider) {
+ this(mapper, beanProvider, null);
}
+ public JavaBeanConverter(final Mapper mapper, final JavaBeanProvider beanProvider, final Class> type) {
+ this.mapper = mapper;
+ this.beanProvider = beanProvider;
+ this.type = type;
+ }
+
/**
- * Only checks for the availability of a public default constructor.
- * If you need stricter checks, subclass JavaBeanConverter
+ * Checks if the bean provider can instantiate this type. If you need less strict checks, subclass JavaBeanConverter
*/
- public boolean canConvert(Class type) {
- return beanProvider.canInstantiate(type);
+ @Override
+ public boolean canConvert(final Class> type) {
+ return (this.type == null || this.type == type) && beanProvider.canInstantiate(type);
}
+ @Override
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
+ final String classAttributeName = mapper.aliasForSystemAttribute("class");
+ beanProvider.visitSerializableProperties(source, new JavaBeanProvider.Visitor() {
+ @Override
+ public boolean shouldVisit(final String name, final Class> definedIn) {
+ return mapper.shouldSerializeMember(definedIn, name);
+ }
- beanProvider.visitSerializableProperties(source, new BeanProvider.Visitor() {
- public void visit(String propertyName, Class fieldType, Object newObj) {
+ @Override
+ public void visit(final String propertyName, final Class> fieldType, final Class> definedIn,
+ final Object newObj) {
if (newObj != null) {
- writeField(propertyName, fieldType, newObj);
+ writeField(propertyName, fieldType, newObj, definedIn);
}
}
- private void writeField(String propertyName, Class fieldType, Object newObj) {
- writer.startNode(classMapper.serializedMember(source.getClass(), propertyName));
-
- Class actualType = newObj.getClass();
-
- Class defaultType = classMapper.defaultImplementationOf(fieldType);
- if (!actualType.equals(defaultType)) {
- writer.addAttribute(classAttributeIdentifier, classMapper.serializedClass(actualType));
+ private void writeField(final String propertyName, final Class> fieldType, final Object newObj,
+ final Class> definedIn) {
+ final Class> actualType = newObj.getClass();
+ final Class> defaultType = mapper.defaultImplementationOf(fieldType);
+ final String serializedMember = mapper.serializedMember(source.getClass(), propertyName);
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, serializedMember, actualType);
+ if (!actualType.equals(defaultType) && classAttributeName != null) {
+ writer.addAttribute(classAttributeName, mapper.serializedClass(actualType));
}
context.convertAnother(newObj);
writer.endNode();
}
-
});
}
+ @Override
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
final Object result = instantiateNewInstance(context);
+ final Set seenProperties = new HashSet() {
+ @Override
+ public boolean add(final FastField e) {
+ if (!super.add(e)) {
+ throw new DuplicatePropertyException(e.getName());
+ }
+ return true;
+ }
+ };
+ final Class> resultType = result.getClass();
while (reader.hasMoreChildren()) {
reader.moveDown();
- String propertyName = classMapper.realMember(result.getClass(), reader.getNodeName());
+ final String propertyName = mapper.realMember(resultType, reader.getNodeName());
- boolean propertyExistsInClass = beanProvider.propertyDefinedInClass(propertyName, result.getClass());
+ if (mapper.shouldSerializeMember(resultType, propertyName)) {
+ final boolean propertyExistsInClass = beanProvider.propertyDefinedInClass(propertyName, resultType);
- Class type = determineType(reader, result, propertyName);
- Object value = context.convertAnother(result, type);
-
- if (propertyExistsInClass) {
- beanProvider.writeProperty(result, propertyName, value);
+ if (propertyExistsInClass) {
+ final Class> type = determineType(reader, result, propertyName);
+ final Object value = context.convertAnother(result, type);
+ beanProvider.writeProperty(result, propertyName, value);
+ seenProperties.add(new FastField(resultType, propertyName));
+ } else {
+ throw new MissingFieldException(resultType.getName(), propertyName);
+ }
}
-
reader.moveUp();
}
return result;
}
- private Object instantiateNewInstance(UnmarshallingContext context) {
+ private Object instantiateNewInstance(final UnmarshallingContext context) {
Object result = context.currentObject();
if (result == null) {
result = beanProvider.newInstance(context.getRequiredType());
}
return result;
}
- private Class determineType(HierarchicalStreamReader reader, Object result, String fieldName) {
- String classAttribute = reader.getAttribute(classAttributeIdentifier);
+ private Class> determineType(final HierarchicalStreamReader reader, final Object result, final String fieldName) {
+ final String classAttributeName = mapper.aliasForSystemAttribute("class");
+ final String classAttribute = classAttributeName == null ? null : reader.getAttribute(classAttributeName);
if (classAttribute != null) {
- return classMapper.realClass(classAttribute);
+ return mapper.realClass(classAttribute);
} else {
- return classMapper.defaultImplementationOf(beanProvider.getPropertyType(result, fieldName));
+ return mapper.defaultImplementationOf(beanProvider.getPropertyType(result, fieldName));
}
}
- public static class DuplicateFieldException extends ConversionException {
- public DuplicateFieldException(String msg) {
- super(msg);
+ /**
+ * Exception to indicate double processing of a property to avoid silent clobbering.
+ *
+ * @author Jörg Schaible
+ * @since 1.4.2
+ */
+ public static class DuplicatePropertyException extends ConversionException {
+ public DuplicatePropertyException(final String msg) {
+ super("Duplicate property " + msg);
+ add("property", msg);
}
}
-}
\ No newline at end of file
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/JavaBeanProvider.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/JavaBeanProvider.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/JavaBeanProvider.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011, 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 07. July 2011 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.javabean;
+
+/**
+ * @author Jörg Schaible
+ * @since 1.4
+ */
+public interface JavaBeanProvider {
+
+ Object newInstance(Class> type);
+
+ void visitSerializableProperties(Object object, Visitor visitor);
+
+ void writeProperty(Object object, String propertyName, Object value);
+
+ Class> getPropertyType(Object object, String name);
+
+ boolean propertyDefinedInClass(String name, Class> type);
+
+ /**
+ * Returns true if the Bean provider can instantiate the specified class
+ */
+ boolean canInstantiate(Class> type);
+
+ public interface Visitor {
+ boolean shouldVisit(String name, Class> definedIn);
+
+ void visit(String name, Class> type, Class> definedIn, Object value);
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/NativePropertySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/NativePropertySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/NativePropertySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011, 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 16. July 2011 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.javabean;
+
+import java.beans.PropertyDescriptor;
+import java.util.Map;
+
+
+/**
+ * A sorter that keeps the natural order of the bean properties as they are returned by the JavaBean introspection.
+ *
+ * @author Jörg Schaible
+ * @since 1.4
+ */
+public class NativePropertySorter implements PropertySorter {
+
+ @Override
+ public Map sort(final Class> type, final Map nameMap) {
+ return nameMap;
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/PropertyDictionary.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/PropertyDictionary.java (.../PropertyDictionary.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/PropertyDictionary.java (.../PropertyDictionary.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,199 +1,127 @@
+/*
+ * Copyright (C) 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 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 12. April 2005 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.javabean;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
import java.beans.Introspector;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
+import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
+import java.util.LinkedHashMap;
import java.util.Map;
+import com.thoughtworks.xstream.converters.reflection.MissingFieldException;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
+import com.thoughtworks.xstream.core.Caching;
+
/**
- * Builds the serializable properties maps for each bean and caches them.
+ * Builds the properties maps for each bean and caches them.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
*/
-public class PropertyDictionary {
+public class PropertyDictionary implements Caching {
+ private transient Map, Map> propertyNameCache = Collections
+ .synchronizedMap(new HashMap, Map>());
+ private final PropertySorter sorter;
- private final Map keyedByPropertyNameCache = Collections.synchronizedMap(new HashMap());
+ public PropertyDictionary() {
+ this(new NativePropertySorter());
+ }
- public Iterator serializablePropertiesFor(Class cls) {
- return buildMap(cls).values().iterator();
+ public PropertyDictionary(final PropertySorter sorter) {
+ this.sorter = sorter;
}
/**
- * Locates a serializable property
- *
- * @param cls
- * @param name
- * @param definedIn
- * @return
+ * @deprecated As of 1.3.1, use {@link #propertiesFor(Class)} instead
*/
- public BeanProperty property(Class cls, String name) {
- Map properties = buildMap(cls);
- BeanProperty property = (BeanProperty) properties.get(name);
- if (property == null) {
- throw new ObjectAccessException("No such property " + cls.getName() + "." + name);
- } else {
- return property;
+ @Deprecated
+ public Iterator serializablePropertiesFor(final Class> type) {
+ final Collection beanProperties = new ArrayList();
+ final Collection descriptors = buildMap(type).values();
+ for (final PropertyDescriptor descriptor : descriptors) {
+ if (descriptor.getReadMethod() != null && descriptor.getWriteMethod() != null) {
+ beanProperties.add(new BeanProperty(type, descriptor.getName(), descriptor.getPropertyType()));
+ }
}
+ return beanProperties.iterator();
}
/**
- * Builds the map of all serializable properties for the the provided bean
+ * Locates a serializable property.
*
* @param cls
- * @param tupleKeyed
- * @return
+ * @param name
+ * @deprecated As of 1.3.1, use {@link #propertyDescriptor(Class, String)} instead
*/
- private Map buildMap(Class cls) {
- final String clsName = cls.getName();
- if (!keyedByPropertyNameCache.containsKey(clsName)) {
- synchronized (keyedByPropertyNameCache) {
- if (!keyedByPropertyNameCache.containsKey(clsName)) { // double check
- // Gather all the properties, using only the keyed map. It
- // is possible that a class have two writable only
- // properties that have the same name
- // but different types
- final Map propertyMap = new HashMap();
- Method[] methods = cls.getMethods();
-
- for (int i = 0; i < methods.length; i++) {
- if (!Modifier.isPublic(methods[i].getModifiers())
- || Modifier.isStatic(methods[i].getModifiers()))
- continue;
-
- String methodName = methods[i].getName();
- Class[] parameters = methods[i].getParameterTypes();
- Class returnType = methods[i].getReturnType();
- String propertyName;
- if ((methodName.startsWith("get") || methodName.startsWith("is"))
- && parameters.length == 0 && returnType != void.class) {
- if (methodName.startsWith("get")) {
- propertyName = Introspector.decapitalize(methodName.substring(3));
- } else {
- propertyName = Introspector.decapitalize(methodName.substring(2));
- }
- BeanProperty property = getBeanProperty(propertyMap, cls, propertyName,
- returnType);
- property.setGetterMethod(methods[i]);
- } else if (methodName.startsWith("set") && parameters.length == 1
- && returnType == void.class) {
- propertyName = Introspector.decapitalize(methodName.substring(3));
- BeanProperty property = getBeanProperty(propertyMap, cls, propertyName,
- parameters[0]);
- property.setSetterMethod(methods[i]);
- }
- }
-
- // retain only those that can be both read and written and
- // sort them by name
- List serializableProperties = new ArrayList();
- for (Iterator it = propertyMap.values().iterator(); it.hasNext();) {
- BeanProperty property = (BeanProperty) it.next();
- if (property.isReadable() && property.isWritable()) {
- serializableProperties.add(property);
- }
- }
- Collections.sort(serializableProperties, new BeanPropertyComparator());
-
- // build the maps and return
- final Map keyedByFieldName = new OrderRetainingMap();
- for (Iterator it = serializableProperties.iterator(); it.hasNext();) {
- BeanProperty property = (BeanProperty) it.next();
- keyedByFieldName.put(property.getName(), property);
- }
-
- keyedByPropertyNameCache.put(clsName, keyedByFieldName);
- }
- }
+ @Deprecated
+ public BeanProperty property(final Class> cls, final String name) {
+ BeanProperty beanProperty = null;
+ final PropertyDescriptor descriptor = buildMap(cls).get(name);
+ if (descriptor == null) {
+ throw new MissingFieldException(cls.getName(), name);
}
- return (Map) keyedByPropertyNameCache.get(clsName);
- }
-
- private BeanProperty getBeanProperty(Map propertyMap, Class cls, String propertyName, Class type) {
- PropertyKey key = new PropertyKey(propertyName, type);
- BeanProperty property = (BeanProperty) propertyMap.get(key);
- if (property == null) {
- property = new BeanProperty(cls, propertyName, type);
- propertyMap.put(key, property);
+ if (descriptor.getReadMethod() != null && descriptor.getWriteMethod() != null) {
+ beanProperty = new BeanProperty(cls, descriptor.getName(), descriptor.getPropertyType());
}
- return property;
+ return beanProperty;
}
- /**
- * Needed to avoid problems with multiple setters with the same name, but
- * referred to different types
- */
- private static class PropertyKey {
- private String propertyName;
-
- private Class propertyType;
-
- public PropertyKey(String propertyName, Class propertyType) {
- this.propertyName = propertyName;
- this.propertyType = propertyType;
- }
-
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (!(o instanceof PropertyKey))
- return false;
-
- final PropertyKey propertyKey = (PropertyKey) o;
-
- if (propertyName != null ? !propertyName.equals(propertyKey.propertyName)
- : propertyKey.propertyName != null)
- return false;
- if (propertyType != null ? !propertyType.equals(propertyKey.propertyType)
- : propertyKey.propertyType != null)
- return false;
-
- return true;
- }
-
- public int hashCode() {
- int result;
- result = (propertyName != null ? propertyName.hashCode() : 0);
- result = 29 * result + (propertyType != null ? propertyType.hashCode() : 0);
- return result;
- }
-
- public String toString() {
- return "PropertyKey{propertyName='" + propertyName + "'" + ", propertyType="
- + propertyType + "}";
- }
-
+ public Iterator propertiesFor(final Class> type) {
+ return buildMap(type).values().iterator();
}
/**
- * Compares properties by name
+ * Locates a property descriptor.
+ *
+ * @param type
+ * @param name
*/
- private static class BeanPropertyComparator implements Comparator {
-
- public int compare(Object o1, Object o2) {
- return ((BeanProperty) o1).getName().compareTo(((BeanProperty) o2).getName());
+ public PropertyDescriptor propertyDescriptor(final Class> type, final String name) {
+ final PropertyDescriptor descriptor = buildMap(type).get(name);
+ if (descriptor == null) {
+ throw new MissingFieldException(type.getName(), name);
}
-
+ return descriptor;
}
- private static class OrderRetainingMap extends HashMap {
-
- private List valueOrder = new ArrayList();
-
- public Object put(Object key, Object value) {
- valueOrder.add(value);
- return super.put(key, value);
+ private Map buildMap(final Class> type) {
+ Map nameMap = propertyNameCache.get(type);
+ if (nameMap == null) {
+ BeanInfo beanInfo;
+ try {
+ beanInfo = Introspector.getBeanInfo(type, Object.class);
+ } catch (final IntrospectionException e) {
+ throw new ObjectAccessException("Cannot get BeanInfo of type " + type.getName(), e);
+ }
+ nameMap = new LinkedHashMap();
+ final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
+ for (final PropertyDescriptor descriptor : propertyDescriptors) {
+ nameMap.put(descriptor.getName(), descriptor);
+ }
+ nameMap = sorter.sort(type, nameMap);
+ propertyNameCache.put(type, nameMap);
}
-
- public Collection values() {
- return Collections.unmodifiableList(valueOrder);
- }
+ return nameMap;
}
-}
\ No newline at end of file
+ @Override
+ public void flushCache() {
+ propertyNameCache.clear();
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/PropertySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/PropertySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/javabean/PropertySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011, 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 16. July 2011 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.javabean;
+
+import java.beans.PropertyDescriptor;
+import java.util.Map;
+
+
+/**
+ * An interface capable of sorting Java bean properties.
+ *
+ * Implement this interface if you want to customize the order in which XStream serializes the properties of a bean.
+ *
+ * The method will be called with the class type that contains all the properties and a Map that retains the order
+ * in which the elements have been added. The sequence in which elements are returned by an iterator defines the
+ * processing order of the properties. An implementation may create a different Map with similar semantic, add all
+ * elements of the original map and return the new one.
+ *
+ *
+ * @param type the bean class that contains all the properties
+ * @param nameMap the map to sort, key is the property name, value the {@link PropertyDescriptor}
+ * @return the sorted nameMap
+ * @since 1.4
+ */
+ Map sort(Class> type, Map nameMap);
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/AbstractAttributedCharacterIteratorAttributeConverter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/AbstractAttributedCharacterIteratorAttributeConverter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/AbstractAttributedCharacterIteratorAttributeConverter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2007, 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 01. February 2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.text.AttributedCharacterIterator;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
+import com.thoughtworks.xstream.core.util.Fields;
+
+
+/**
+ * An abstract converter implementation for constants of {@link java.text.AttributedCharacterIterator.Attribute} and
+ * derived types.
+ *
+ * @author Jörg Schaible
+ * @since 1.2.2
+ */
+public class AbstractAttributedCharacterIteratorAttributeConverter
+ extends AbstractSingleValueConverter {
+
+ private static final Map> instanceMaps = new HashMap>();
+ private static final Method getName;
+ static {
+ Method method = null;
+ try {
+ method = AttributedCharacterIterator.Attribute.class.getDeclaredMethod("getName", (Class[])null);
+ if (!method.isAccessible()) {
+ method.setAccessible(true);
+ }
+ } catch (final SecurityException e) {
+ // ignore for now
+ } catch (final NoSuchMethodException e) {
+ // ignore for now
+ }
+ getName = method;
+ }
+
+ private final Class extends T> type;
+ private transient Map attributeMap;
+
+ public AbstractAttributedCharacterIteratorAttributeConverter(final Class extends T> type) {
+ super();
+ if (!AttributedCharacterIterator.Attribute.class.isAssignableFrom(type)) {
+ throw new IllegalArgumentException(type.getName()
+ + " is not a "
+ + AttributedCharacterIterator.Attribute.class.getName());
+ }
+ this.type = type;
+ readResolve();
+ }
+
+ @Override
+ public boolean canConvert(final Class> type) {
+ return type == this.type && !attributeMap.isEmpty();
+ }
+
+ @Override
+ public String toString(final Object source) {
+ @SuppressWarnings("unchecked")
+ final T t = (T)source;
+ return getName(t);
+ }
+
+ private String getName(final AttributedCharacterIterator.Attribute attribute) {
+ Exception ex = null;
+ if (getName != null) {
+ try {
+ return (String)getName.invoke(attribute);
+ } catch (final IllegalAccessException e) {
+ ex = e;
+ } catch (final InvocationTargetException e) {
+ ex = e;
+ }
+ }
+ final String s = attribute.toString();
+ final String className = attribute.getClass().getName();
+ if (s.startsWith(className)) {
+ return s.substring(className.length() + 1, s.length() - 1);
+ }
+ throw new ConversionException("Cannot find name of attribute of type " + className, ex);
+ }
+
+ @Override
+ public Object fromString(final String str) {
+ if (attributeMap.containsKey(str)) {
+ return attributeMap.get(str);
+ }
+ throw new ConversionException("Cannot find attribute of type " + type.getName() + " with name " + str);
+ }
+
+ private Object readResolve() {
+ @SuppressWarnings("unchecked")
+ final Map typedMap = (Map)instanceMaps.get(type.getName());
+ attributeMap = typedMap;
+ if (attributeMap == null) {
+ attributeMap = new HashMap();
+ final Field instanceMap = Fields.locate(type, Map.class, true);
+ if (instanceMap != null) {
+ try {
+ @SuppressWarnings("unchecked")
+ final Map map = (Map)Fields.read(instanceMap, null);
+ if (map != null) {
+ boolean valid = true;
+ for (final Map.Entry entry : map.entrySet()) {
+ valid = entry.getKey().getClass() == String.class && entry.getValue().getClass() == type;
+ }
+ if (valid) {
+ attributeMap.putAll(map);
+ }
+ }
+ } catch (final ObjectAccessException e) {
+ }
+ }
+ if (attributeMap.isEmpty()) {
+ try {
+ final Field[] fields = type.getDeclaredFields();
+ for (final Field field : fields) {
+ if (field.getType() == type == Modifier.isStatic(field.getModifiers())) {
+ @SuppressWarnings("unchecked")
+ final T attribute = (T)Fields.read(field, null);
+ attributeMap.put(toString(attribute), attribute);
+ }
+ }
+ } catch (final SecurityException e) {
+ attributeMap.clear();
+ } catch (final ObjectAccessException e) {
+ attributeMap.clear();
+ } catch (final NoClassDefFoundError e) {
+ attributeMap.clear();
+ }
+ }
+ instanceMaps.put(type.getName(), attributeMap);
+ }
+ return this;
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 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 02. March 2006 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.SingleValueConverter;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.core.Caching;
+import com.thoughtworks.xstream.core.ReferencingMarshallingContext;
+import com.thoughtworks.xstream.core.util.ArrayIterator;
+import com.thoughtworks.xstream.core.util.FastField;
+import com.thoughtworks.xstream.core.util.HierarchicalStreams;
+import com.thoughtworks.xstream.core.util.Primitives;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.CannotResolveClassException;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+
+public abstract class AbstractReflectionConverter implements Converter, Caching {
+
+ protected final ReflectionProvider reflectionProvider;
+ protected final Mapper mapper;
+ protected transient SerializationMethodInvoker serializationMethodInvoker;
+ private transient ReflectionProvider pureJavaReflectionProvider;
+
+ public AbstractReflectionConverter(final Mapper mapper, final ReflectionProvider reflectionProvider) {
+ this.mapper = mapper;
+ this.reflectionProvider = reflectionProvider;
+ serializationMethodInvoker = new SerializationMethodInvoker();
+ }
+
+ protected boolean canAccess(final Class> type) {
+ try {
+ reflectionProvider.getFieldOrNull(type, "%");
+ return true;
+ } catch (final NoClassDefFoundError e) {
+ // restricted type in GAE
+ }
+ return false;
+ }
+
+ @Override
+ public void marshal(final Object original, final HierarchicalStreamWriter writer, final MarshallingContext context) {
+ final Object source = serializationMethodInvoker.callWriteReplace(original);
+
+ if (source != original && context instanceof ReferencingMarshallingContext) {
+ ((ReferencingMarshallingContext>)context).replace(original, source);
+ }
+ if (source.getClass() != original.getClass()) {
+ final String attributeName = mapper.aliasForSystemAttribute("resolves-to");
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, mapper.serializedClass(source.getClass()));
+ }
+ context.convertAnother(source);
+ } else {
+ doMarshal(source, writer, context);
+ }
+ }
+
+ protected void doMarshal(final Object source, final HierarchicalStreamWriter writer,
+ final MarshallingContext context) {
+ final List fields = new ArrayList();
+ final Map defaultFieldDefinition = new HashMap();
+
+ // Attributes might be preferred to child elements ...
+ reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
+ final Set writtenAttributes = new HashSet();
+
+ @Override
+ public void visit(final String fieldName, final Class> type, final Class> definedIn, final Object value) {
+ if (!mapper.shouldSerializeMember(definedIn, fieldName)) {
+ return;
+ }
+ if (!defaultFieldDefinition.containsKey(fieldName)) {
+ Class> lookupType = source.getClass();
+ // See XSTR-457 and OmitFieldsTest
+ if (definedIn != source.getClass() && !mapper.shouldSerializeMember(lookupType, fieldName)) {
+ lookupType = definedIn;
+ }
+ defaultFieldDefinition.put(fieldName, reflectionProvider.getField(lookupType, fieldName));
+ }
+
+ final SingleValueConverter converter = mapper.getConverterFromItemType(fieldName, type, definedIn);
+ if (converter != null) {
+ final String attribute = mapper.aliasForAttribute(mapper.serializedMember(definedIn, fieldName));
+ if (value != null) {
+ if (writtenAttributes.contains(fieldName)) { // TODO: use attribute
+ throw new ConversionException("Cannot write field with name '"
+ + fieldName
+ + "' twice as attribute for object of type "
+ + source.getClass().getName());
+ }
+ final String str = converter.toString(value);
+ if (str != null) {
+ writer.addAttribute(attribute, str);
+ }
+ }
+ writtenAttributes.add(fieldName); // TODO: use attribute
+ } else {
+ fields.add(new FieldInfo(fieldName, type, definedIn, value));
+ }
+ }
+ });
+
+ new Object() {
+ {
+ for (final FieldInfo fieldInfo : fields) {
+ final FieldInfo info = fieldInfo;
+ if (info.value != null) {
+ final Mapper.ImplicitCollectionMapping mapping = mapper.getImplicitCollectionDefForFieldName(
+ source.getClass(), info.fieldName);
+ if (mapping != null) {
+ if (context instanceof ReferencingMarshallingContext) {
+ if (info.value != Collections.EMPTY_LIST
+ && info.value != Collections.EMPTY_SET
+ && info.value != Collections.EMPTY_MAP) {
+ final ReferencingMarshallingContext> refContext = (ReferencingMarshallingContext>)context;
+ refContext.registerImplicit(info.value);
+ }
+ }
+ final boolean isCollection = info.value instanceof Collection;
+ final boolean isMap = info.value instanceof Map;
+ final boolean isEntry = isMap && mapping.getKeyFieldName() == null;
+ final boolean isArray = info.value.getClass().isArray();
+ for (final Iterator> iter = isArray ? new ArrayIterator(info.value) : isCollection
+ ? ((Collection>)info.value).iterator()
+ : isEntry ? ((Map, ?>)info.value).entrySet().iterator() : ((Map, ?>)info.value)
+ .values()
+ .iterator(); iter.hasNext();) {
+ final Object obj = iter.next();
+ final String itemName;
+ final Class> itemType;
+ if (obj == null) {
+ itemType = Object.class;
+ itemName = mapper.serializedClass(null);
+ } else if (isEntry) {
+ final String entryName = mapping.getItemFieldName() != null ? mapping
+ .getItemFieldName() : mapper.serializedClass(Map.Entry.class);
+ final Map.Entry, ?> entry = (Map.Entry, ?>)obj;
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, entryName, entry
+ .getClass());
+ writeItem(entry.getKey(), context, writer);
+ writeItem(entry.getValue(), context, writer);
+ writer.endNode();
+ continue;
+ } else if (mapping.getItemFieldName() != null) {
+ itemType = mapping.getItemType();
+ itemName = mapping.getItemFieldName();
+ } else {
+ itemType = obj.getClass();
+ itemName = mapper.serializedClass(itemType);
+ }
+ writeField(info.fieldName, itemName, itemType, info.definedIn, obj);
+ }
+ } else {
+ writeField(info.fieldName, null, info.type, info.definedIn, info.value);
+ }
+ }
+ }
+
+ }
+
+ void writeField(final String fieldName, final String aliasName, final Class> fieldType,
+ final Class> definedIn, final Object newObj) {
+ final Class> actualType = newObj != null ? newObj.getClass() : fieldType;
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, aliasName != null ? aliasName : mapper
+ .serializedMember(source.getClass(), fieldName), actualType);
+
+ if (newObj != null) {
+ final Class> defaultType = mapper.defaultImplementationOf(fieldType);
+ if (!actualType.equals(defaultType)) {
+ final String serializedClassName = mapper.serializedClass(actualType);
+ if (!serializedClassName.equals(mapper.serializedClass(defaultType))) {
+ final String attributeName = mapper.aliasForSystemAttribute("class");
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, serializedClassName);
+ }
+ }
+ }
+
+ final Field defaultField = defaultFieldDefinition.get(fieldName);
+ if (defaultField.getDeclaringClass() != definedIn) {
+ final String attributeName = mapper.aliasForSystemAttribute("defined-in");
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, mapper.serializedClass(definedIn));
+ }
+ }
+
+ final Field field = reflectionProvider.getField(definedIn, fieldName);
+ marshallField(context, newObj, field);
+ }
+ writer.endNode();
+ }
+
+ void writeItem(final Object item, final MarshallingContext context, final HierarchicalStreamWriter writer) {
+ if (item == null) {
+ final String name = mapper.serializedClass(null);
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, name, Mapper.Null.class);
+ writer.endNode();
+ } else {
+ final String name = mapper.serializedClass(item.getClass());
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, name, item.getClass());
+ context.convertAnother(item);
+ writer.endNode();
+ }
+ }
+ };
+ }
+
+ protected void marshallField(final MarshallingContext context, final Object newObj, final Field field) {
+ context.convertAnother(newObj, mapper.getLocalConverter(field.getDeclaringClass(), field.getName()));
+ }
+
+ @Override
+ public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
+ Object result = instantiateNewInstance(reader, context);
+ result = doUnmarshal(result, reader, context);
+ return serializationMethodInvoker.callReadResolve(result);
+ }
+
+ public Object doUnmarshal(final Object result, final HierarchicalStreamReader reader,
+ final UnmarshallingContext context) {
+ final Class> resultType = result.getClass();
+ final Set seenFields = new HashSet() {
+ @Override
+ public boolean add(final FastField e) {
+ if (!super.add(e)) {
+ throw new DuplicateFieldException(e.getName());
+ }
+ return true;
+ }
+ };
+
+ // process attributes before recursing into child elements.
+ final Iterator it = reader.getAttributeNames();
+ while (it.hasNext()) {
+ final String attrAlias = it.next();
+ // TODO: realMember should return FastField
+ final String attrName = mapper.realMember(resultType, mapper.attributeForAlias(attrAlias));
+ final Field field = reflectionProvider.getFieldOrNull(resultType, attrName);
+ if (field != null && shouldUnmarshalField(field)) {
+ final Class> classDefiningField = field.getDeclaringClass();
+ if (!mapper.shouldSerializeMember(classDefiningField, attrName)) {
+ continue;
+ }
+
+ // we need a converter that produces a string representation only
+ final SingleValueConverter converter = mapper.getConverterFromAttribute(classDefiningField, attrName,
+ field.getType());
+ Class> type = field.getType();
+ if (converter != null) {
+ final Object value = converter.fromString(reader.getAttribute(attrAlias));
+ if (type.isPrimitive()) {
+ type = Primitives.box(type);
+ }
+ if (value != null && !type.isAssignableFrom(value.getClass())) {
+ throw new ConversionException("Cannot convert type "
+ + value.getClass().getName()
+ + " to type "
+ + type.getName());
+ }
+ seenFields.add(new FastField(classDefiningField, attrName));
+ reflectionProvider.writeField(result, attrName, value, classDefiningField);
+ }
+ }
+ }
+
+ Map> implicitCollectionsForCurrentObject = null;
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+
+ final String originalNodeName = reader.getNodeName();
+ final Class> explicitDeclaringClass = readDeclaringClass(reader);
+ final Class> fieldDeclaringClass = explicitDeclaringClass == null ? resultType : explicitDeclaringClass;
+ final String fieldName = mapper.realMember(fieldDeclaringClass, originalNodeName);
+ final Mapper.ImplicitCollectionMapping implicitCollectionMapping = mapper
+ .getImplicitCollectionDefForFieldName(fieldDeclaringClass, fieldName);
+ final Object value;
+ String implicitFieldName = null;
+ Field field = null;
+ Class> type = null;
+ if (implicitCollectionMapping == null) {
+ // no item of an implicit collection for this name ... do we have a field?
+ field = reflectionProvider.getFieldOrNull(fieldDeclaringClass, fieldName);
+ if (field == null) {
+ // it is not a field ... do we have a field alias?
+ final Class> itemType = mapper.getItemTypeForItemFieldName(resultType, fieldName);
+ if (itemType != null) {
+ final String classAttribute = HierarchicalStreams.readClassAttribute(reader, mapper);
+ if (classAttribute != null) {
+ type = mapper.realClass(classAttribute);
+ } else {
+ type = itemType;
+ }
+ } else {
+ // it is not an alias ... do we have an element of an implicit
+ // collection based on type only?
+ try {
+ type = mapper.realClass(originalNodeName);
+ implicitFieldName = mapper.getFieldNameForItemTypeAndName(context.getRequiredType(), type,
+ originalNodeName);
+ } catch (final CannotResolveClassException e) {
+ // type stays null ...
+ }
+ if (type == null || type != null && implicitFieldName == null) {
+ // either not a type or element is a type alias, but does not
+ // belong to an implicit field
+ handleUnknownField(explicitDeclaringClass, fieldName, resultType, originalNodeName);
+
+ // element is unknown in declaring class, ignore it now
+ type = null;
+ }
+ }
+ if (type == null) {
+ // no type, no value
+ value = null;
+ } else {
+ if (Map.Entry.class.equals(type)) {
+ // it is an element of an implicit map with two elements now for
+ // key and value
+ reader.moveDown();
+ final Object key = context.convertAnother(result, HierarchicalStreams.readClassType(reader,
+ mapper));
+ reader.moveUp();
+ reader.moveDown();
+ final Object v = context.convertAnother(result, HierarchicalStreams.readClassType(reader,
+ mapper));
+ reader.moveUp();
+ value = Collections.singletonMap(key, v).entrySet().iterator().next();
+ } else {
+ // recurse info hierarchy
+ value = context.convertAnother(result, type);
+ }
+ }
+ } else {
+ boolean fieldAlreadyChecked = false;
+
+ // we have a field, but do we have to address a hidden one?
+ if (explicitDeclaringClass == null) {
+ while (field != null
+ && !(fieldAlreadyChecked = shouldUnmarshalField(field)
+ && mapper.shouldSerializeMember(field.getDeclaringClass(), fieldName))) {
+ field = reflectionProvider.getFieldOrNull(field.getDeclaringClass().getSuperclass(),
+ fieldName);
+ }
+ }
+ if (field != null
+ && (fieldAlreadyChecked || shouldUnmarshalField(field)
+ && mapper.shouldSerializeMember(field.getDeclaringClass(), fieldName))) {
+
+ final String classAttribute = HierarchicalStreams.readClassAttribute(reader, mapper);
+ if (classAttribute != null) {
+ type = mapper.realClass(classAttribute);
+ } else {
+ type = mapper.defaultImplementationOf(field.getType());
+ }
+ // TODO the reflection provider should already return the proper field
+ value = unmarshallField(context, result, type, field);
+ final Class> definedType = field.getType();
+ if (!definedType.isPrimitive()) {
+ type = definedType;
+ }
+ } else {
+ value = null;
+ }
+ }
+ } else {
+ // we have an implicit collection with defined names
+ implicitFieldName = implicitCollectionMapping.getFieldName();
+ type = implicitCollectionMapping.getItemType();
+ if (type == null) {
+ final String classAttribute = HierarchicalStreams.readClassAttribute(reader, mapper);
+ type = mapper.realClass(classAttribute != null ? classAttribute : originalNodeName);
+ }
+ value = context.convertAnother(result, type);
+ }
+
+ if (value != null && !type.isAssignableFrom(value.getClass())) {
+ throw new ConversionException("Cannot convert type "
+ + value.getClass().getName()
+ + " to type "
+ + type.getName());
+ }
+
+ if (field != null) {
+ reflectionProvider.writeField(result, fieldName, value, field.getDeclaringClass());
+ seenFields.add(new FastField(field.getDeclaringClass(), fieldName));
+ } else if (type != null) {
+ if (implicitFieldName == null) {
+ // look for implicit field
+ implicitFieldName = mapper.getFieldNameForItemTypeAndName(context.getRequiredType(), value != null
+ ? value.getClass()
+ : Mapper.Null.class, originalNodeName);
+ }
+ if (implicitCollectionsForCurrentObject == null) {
+ implicitCollectionsForCurrentObject = new HashMap>();
+ }
+ writeValueToImplicitCollection(value, implicitCollectionsForCurrentObject, result, implicitFieldName);
+ }
+
+ reader.moveUp();
+ }
+
+ if (implicitCollectionsForCurrentObject != null) {
+ for (final Map.Entry> entry : implicitCollectionsForCurrentObject
+ .entrySet()) {
+ final Object value = entry.getValue();
+ if (value instanceof ArraysList) {
+ final Object array = ((ArraysList)value).toPhysicalArray();
+ reflectionProvider.writeField(result, entry.getKey(), array, null);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ protected Object unmarshallField(final UnmarshallingContext context, final Object result, final Class> type,
+ final Field field) {
+ return context.convertAnother(result, type, mapper
+ .getLocalConverter(field.getDeclaringClass(), field.getName()));
+ }
+
+ protected boolean shouldUnmarshalTransientFields() {
+ return false;
+ }
+
+ protected boolean shouldUnmarshalField(final Field field) {
+ return !(Modifier.isTransient(field.getModifiers()) && !shouldUnmarshalTransientFields());
+ }
+
+ private void handleUnknownField(final Class> classDefiningField, final String fieldName,
+ final Class> resultType, final String originalNodeName) {
+ if (classDefiningField == null) {
+ for (Class> cls = resultType; cls != null; cls = cls.getSuperclass()) {
+ if (!mapper.shouldSerializeMember(cls, originalNodeName)) {
+ return;
+ }
+ }
+ }
+ throw new UnknownFieldException(resultType.getName(), fieldName);
+ }
+
+ private void writeValueToImplicitCollection(final Object value,
+ final Map> implicitCollections, final Object result,
+ final String implicitFieldName) {
+ Collection super Object> collection = implicitCollections.get(implicitFieldName);
+ if (collection == null) {
+ final Class> physicalFieldType = reflectionProvider.getFieldType(result, implicitFieldName, null);
+ if (physicalFieldType.isArray()) {
+ collection = new ArraysList(physicalFieldType);
+ } else {
+ final Class> fieldType = mapper.defaultImplementationOf(physicalFieldType);
+ if (!(Collection.class.isAssignableFrom(fieldType) || Map.class.isAssignableFrom(fieldType))) {
+ throw new ObjectAccessException("Field "
+ + implicitFieldName
+ + " of "
+ + result.getClass().getName()
+ + " is configured for an implicit Collection or Map, but field is of type "
+ + fieldType.getName());
+ }
+ if (pureJavaReflectionProvider == null) {
+ pureJavaReflectionProvider = new PureJavaReflectionProvider();
+ }
+ final Object instance = pureJavaReflectionProvider.newInstance(fieldType);
+ if (instance instanceof Collection) {
+ @SuppressWarnings("unchecked")
+ final Collection super Object> uncheckedCollection = (Collection super Object>)instance;
+ collection = uncheckedCollection;
+ } else {
+ final Mapper.ImplicitCollectionMapping implicitCollectionMapping = mapper
+ .getImplicitCollectionDefForFieldName(result.getClass(), implicitFieldName);
+ @SuppressWarnings("unchecked")
+ final Map map = (Map)instance;
+ collection = new MappingList(map, implicitCollectionMapping.getKeyFieldName());
+ }
+ reflectionProvider.writeField(result, implicitFieldName, instance, null);
+ }
+ implicitCollections.put(implicitFieldName, collection);
+ }
+ collection.add(value);
+ }
+
+ private Class> readDeclaringClass(final HierarchicalStreamReader reader) {
+ final String attributeName = mapper.aliasForSystemAttribute("defined-in");
+ final String definedIn = attributeName == null ? null : reader.getAttribute(attributeName);
+ return definedIn == null ? null : mapper.realClass(definedIn);
+ }
+
+ protected Object instantiateNewInstance(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
+ final String attributeName = mapper.aliasForSystemAttribute("resolves-to");
+ final String readResolveValue = attributeName == null ? null : reader.getAttribute(attributeName);
+ final Object currentObject = context.currentObject();
+ if (currentObject != null) {
+ return currentObject;
+ } else if (readResolveValue != null) {
+ return reflectionProvider.newInstance(mapper.realClass(readResolveValue));
+ } else {
+ return reflectionProvider.newInstance(context.getRequiredType());
+ }
+ }
+
+ @Override
+ public void flushCache() {
+ serializationMethodInvoker.flushCache();
+ }
+
+ private Object readResolve() {
+ serializationMethodInvoker = new SerializationMethodInvoker();
+ return this;
+ }
+
+ public static class DuplicateFieldException extends ConversionException {
+ public DuplicateFieldException(final String msg) {
+ super("Duplicate field " + msg);
+ add("field", msg);
+ }
+ }
+
+ public static class UnknownFieldException extends ConversionException {
+ public UnknownFieldException(final String type, final String field) {
+ super("No such field " + type + "." + field);
+ add("field", field);
+ }
+ }
+
+ private static class FieldInfo {
+ final String fieldName;
+ final Class> type;
+ final Class> definedIn;
+ final Object value;
+
+ FieldInfo(final String fieldName, final Class> type, final Class> definedIn, final Object value) {
+ this.fieldName = fieldName;
+ this.type = type;
+ this.definedIn = definedIn;
+ this.value = value;
+ }
+ }
+
+ private static class ArraysList extends ArrayList {
+ final Class> physicalFieldType;
+
+ ArraysList(final Class> physicalFieldType) {
+ this.physicalFieldType = physicalFieldType;
+ }
+
+ Object toPhysicalArray() {
+ final Object[] objects = toArray();
+ final Object array = Array.newInstance(physicalFieldType.getComponentType(), objects.length);
+ if (physicalFieldType.getComponentType().isPrimitive()) {
+ for (int i = 0; i < objects.length; ++i) {
+ Array.set(array, i, Array.get(objects, i));
+ }
+ } else {
+ System.arraycopy(objects, 0, array, 0, objects.length);
+ }
+ return array;
+ }
+ }
+
+ private class MappingList extends AbstractList {
+
+ private final Map map;
+ private final String keyFieldName;
+ private final Map, Field> fieldCache = new HashMap, Field>();
+
+ public MappingList(final Map map, final String keyFieldName) {
+ this.map = map;
+ this.keyFieldName = keyFieldName;
+ }
+
+ @Override
+ public boolean add(final Object object) {
+ if (object == null) {
+ final boolean containsNull = !map.containsKey(null);
+ map.put(null, null);
+ return containsNull;
+ }
+ final Class> itemType = object.getClass();
+ if (keyFieldName != null) {
+ Field field = fieldCache.get(itemType);
+ if (field == null) {
+ field = reflectionProvider.getField(itemType, keyFieldName);
+ fieldCache.put(itemType, field);
+ }
+ if (field != null) {
+ try {
+ final Object key = field.get(object);
+ return map.put(key, object) == null;
+ } catch (final IllegalArgumentException e) {
+ throw new ObjectAccessException("Could not get field "
+ + field.getClass()
+ + "."
+ + field.getName(), e);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Could not get field "
+ + field.getClass()
+ + "."
+ + field.getName(), e);
+ }
+ }
+ } else if (object instanceof Map.Entry) {
+ @SuppressWarnings("unchecked")
+ final Map.Entry entry = (Map.Entry)object;
+ return map.put(entry.getKey(), entry.getValue()) == null;
+ }
+
+ throw new ConversionException("Element of type "
+ + object.getClass().getName()
+ + " is not defined as entry for map of type "
+ + map.getClass().getName());
+ }
+
+ @Override
+ public Object get(final int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,498 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 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 13. April 2006 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.core.ClassLoaderReference;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.CGLIBMapper;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.CallbackFilter;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.Factory;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.NoOp;
+
+
+/**
+ * Converts a proxy created by the CGLIB {@link Enhancer}. Such a proxy is recreated while deserializing the proxy. The
+ * converter does only work, if
+ *
+ *
the DefaultNamingPolicy is used for the proxy's name
+ *
the proxy uses a factory or only one Callback is registered
+ *
a possible super class has at least a protected default constructor
+ *
+ * Note, that the this converter relies on the CGLIBMapper.
+ *
+ * @author Jörg Schaible
+ * @since 1.2
+ */
+public class CGLIBEnhancedConverter extends SerializableConverter {
+ private static String DEFAULT_NAMING_MARKER = "$$EnhancerByCGLIB$$";
+ private static String CALLBACK_MARKER = "CGLIB$CALLBACK_";
+ private transient Map> fieldCache;
+
+ /**
+ * Construct a CGLIBEnhancedConverter.
+ *
+ * @param mapper the mapper chain instance
+ * @param reflectionProvider the reflection provider
+ * @param classLoaderReference the reference to the {@link ClassLoader} of the XStream instance
+ * @since 1.4.5
+ */
+ public CGLIBEnhancedConverter(
+ final Mapper mapper, final ReflectionProvider reflectionProvider,
+ final ClassLoaderReference classLoaderReference) {
+ super(mapper, new CGLIBFilteringReflectionProvider(reflectionProvider), classLoaderReference);
+ fieldCache = new HashMap>();
+ }
+
+ /**
+ * @deprecated As of 1.4.5 use {@link #CGLIBEnhancedConverter(Mapper, ReflectionProvider, ClassLoaderReference)}
+ */
+ @Deprecated
+ public CGLIBEnhancedConverter(
+ final Mapper mapper, final ReflectionProvider reflectionProvider, final ClassLoader classLoader) {
+ super(mapper, new CGLIBFilteringReflectionProvider(reflectionProvider), classLoader);
+ fieldCache = new HashMap>();
+ }
+
+ /**
+ * @deprecated As of 1.4 use {@link #CGLIBEnhancedConverter(Mapper, ReflectionProvider, ClassLoaderReference)}
+ */
+ @Deprecated
+ public CGLIBEnhancedConverter(final Mapper mapper, final ReflectionProvider reflectionProvider) {
+ this(mapper, new CGLIBFilteringReflectionProvider(reflectionProvider), CGLIBEnhancedConverter.class
+ .getClassLoader());
+ }
+
+ @Override
+ public boolean canConvert(final Class> type) {
+ return Enhancer.isEnhanced(type)
+ && type.getName().indexOf(DEFAULT_NAMING_MARKER) > 0
+ || type == CGLIBMapper.Marker.class;
+ }
+
+ @Override
+ public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
+ final Class> type = source.getClass();
+ final boolean hasFactory = Factory.class.isAssignableFrom(type);
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, "type", type);
+ context.convertAnother(type.getSuperclass());
+ writer.endNode();
+ writer.startNode("interfaces");
+ final Class>[] interfaces = type.getInterfaces();
+ for (final Class> interface1 : interfaces) {
+ if (interface1 == Factory.class) {
+ continue;
+ }
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(interface1.getClass()),
+ interface1.getClass());
+ context.convertAnother(interface1);
+ writer.endNode();
+ }
+ writer.endNode();
+ writer.startNode("hasFactory");
+ writer.setValue(String.valueOf(hasFactory));
+ writer.endNode();
+ Map, ?> callbackIndexMap = null;
+ final Callback[] callbacks = hasFactory ? ((Factory)source).getCallbacks() : getCallbacks(source);
+ if (callbacks.length > 1) {
+ if (hasFactory) {
+ callbackIndexMap = createCallbackIndexMap((Factory)source);
+ } else {
+ final ConversionException exception = new ConversionException(
+ "Cannot handle CGLIB enhanced proxies without factory that have multiple callbacks");
+ exception.add("proxy superclass", type.getSuperclass().getName());
+ exception.add("number of callbacks", String.valueOf(callbacks.length));
+ throw exception;
+ }
+ writer.startNode("callbacks");
+ writer.startNode("mapping");
+ context.convertAnother(callbackIndexMap);
+ writer.endNode();
+ }
+ boolean hasInterceptor = false;
+ for (final Callback callback : callbacks) {
+ if (callback == null) {
+ final String name = mapper.serializedClass(null);
+ writer.startNode(name);
+ writer.endNode();
+ } else {
+ hasInterceptor = hasInterceptor || MethodInterceptor.class.isAssignableFrom(callback.getClass());
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(callback.getClass()),
+ callback.getClass());
+ context.convertAnother(callback);
+ writer.endNode();
+ }
+ }
+ if (callbacks.length > 1) {
+ writer.endNode();
+ }
+ try {
+ final Field field = type.getDeclaredField("serialVersionUID");
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ final long serialVersionUID = field.getLong(null);
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, "serialVersionUID", String.class);
+ writer.setValue(String.valueOf(serialVersionUID));
+ writer.endNode();
+ } catch (final NoSuchFieldException e) {
+ // OK, ignore
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Access to serialVersionUID of " + type.getName() + " not allowed", e);
+ }
+ if (hasInterceptor) {
+ writer.startNode("instance");
+ super.doMarshalConditionally(source, writer, context);
+ writer.endNode();
+ }
+ }
+
+ private Callback[] getCallbacks(final Object source) {
+ final Class> type = source.getClass();
+ List fields = fieldCache.get(type.getName());
+ if (fields == null) {
+ fields = new ArrayList();
+ fieldCache.put(type.getName(), fields);
+ for (int i = 0; true; ++i) {
+ try {
+ final Field field = type.getDeclaredField(CALLBACK_MARKER + i);
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ fields.add(field);
+ } catch (final NoSuchFieldException e) {
+ break;
+ }
+ }
+ }
+ final List list = new ArrayList();
+ for (int i = 0; i < fields.size(); ++i) {
+ try {
+ final Field field = fields.get(i);
+ final Callback callback = (Callback)field.get(source);
+ list.add(callback);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Access to "
+ + type.getName()
+ + "."
+ + CALLBACK_MARKER
+ + i
+ + " not allowed", e);
+ }
+ }
+ return list.toArray(new Callback[list.size()]);
+ }
+
+ private Map super Object, ? super Object> createCallbackIndexMap(final Factory source) {
+ final Callback[] originalCallbacks = source.getCallbacks();
+ final Callback[] reverseEngineeringCallbacks = new Callback[originalCallbacks.length];
+ final Map super Object, ? super Object> callbackIndexMap = new HashMap();
+ int idxNoOp = -1;
+ for (int i = 0; i < originalCallbacks.length; i++) {
+ final Callback callback = originalCallbacks[i];
+ if (callback == null) {
+ reverseEngineeringCallbacks[i] = null;
+ } else if (NoOp.class.isAssignableFrom(callback.getClass())) {
+ reverseEngineeringCallbacks[i] = NoOp.INSTANCE;
+ idxNoOp = i;
+ } else {
+ reverseEngineeringCallbacks[i] = createReverseEngineeredCallbackOfProperType(callback, i,
+ callbackIndexMap);
+ }
+ }
+
+ try {
+ source.setCallbacks(reverseEngineeringCallbacks);
+ final Set> interfaces = new HashSet>();
+ final Set methods = new HashSet();
+ Class> type = source.getClass();
+ do {
+ methods.addAll(Arrays.asList(type.getDeclaredMethods()));
+ methods.addAll(Arrays.asList(type.getMethods()));
+ final Class>[] implementedInterfaces = type.getInterfaces();
+ interfaces.addAll(Arrays.asList(implementedInterfaces));
+ type = type.getSuperclass();
+ } while (type != null);
+ for (final Iterator> iterator = interfaces.iterator(); iterator.hasNext();) {
+ type = iterator.next();
+ methods.addAll(Arrays.asList(type.getDeclaredMethods()));
+ }
+ for (final Iterator iter = methods.iterator(); iter.hasNext();) {
+ final Method method = iter.next();
+ if (!method.isAccessible()) {
+ method.setAccessible(true);
+ }
+ if (Factory.class.isAssignableFrom(method.getDeclaringClass())
+ || (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) {
+ iter.remove();
+ continue;
+ }
+ final Class>[] parameterTypes = method.getParameterTypes();
+ Method calledMethod = method;
+ try {
+ if ((method.getModifiers() & Modifier.ABSTRACT) > 0) {
+ calledMethod = source.getClass().getMethod(method.getName(), method.getParameterTypes());
+ }
+ callbackIndexMap.put(null, method);
+ calledMethod.invoke(source, parameterTypes == null
+ ? (Object[])null
+ : createNullArguments(parameterTypes));
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Access to " + calledMethod + " not allowed", e);
+ } catch (final InvocationTargetException e) {
+ // OK, ignore
+ } catch (final NoSuchMethodException e) {
+ final ConversionException exception = new ConversionException(
+ "CGLIB enhanced proxies wit abstract nethod that has not been implemented");
+ exception.add("proxy superclass", type.getSuperclass().getName());
+ exception.add("method", method.toString());
+ throw exception;
+ }
+ if (callbackIndexMap.containsKey(method)) {
+ iter.remove();
+ }
+ }
+ if (idxNoOp >= 0) {
+ final Integer idx = Integer.valueOf(idxNoOp);
+ for (final Method method : methods) {
+ callbackIndexMap.put(method, idx);
+ }
+ }
+ } finally {
+ source.setCallbacks(originalCallbacks);
+ }
+
+ callbackIndexMap.remove(null);
+ return callbackIndexMap;
+ }
+
+ private Object[] createNullArguments(final Class>[] parameterTypes) {
+ final Object[] arguments = new Object[parameterTypes.length];
+ for (int i = 0; i < arguments.length; i++) {
+ final Class> type = parameterTypes[i];
+ if (type.isPrimitive()) {
+ if (type == byte.class) {
+ arguments[i] = new Byte((byte)0);
+ } else if (type == short.class) {
+ arguments[i] = new Short((short)0);
+ } else if (type == int.class) {
+ arguments[i] = new Integer(0);
+ } else if (type == long.class) {
+ arguments[i] = new Long(0);
+ } else if (type == float.class) {
+ arguments[i] = new Float(0);
+ } else if (type == double.class) {
+ arguments[i] = new Double(0);
+ } else if (type == char.class) {
+ arguments[i] = new Character('\0');
+ } else {
+ arguments[i] = Boolean.FALSE;
+ }
+ }
+ }
+ return arguments;
+ }
+
+ private Callback createReverseEngineeredCallbackOfProperType(final Callback callback, final int index,
+ final Map super Object, ? super Object> callbackIndexMap) {
+ Class> iface = null;
+ Class>[] interfaces = callback.getClass().getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (Callback.class.isAssignableFrom(interfaces[i])) {
+ iface = interfaces[i];
+ if (iface == Callback.class) {
+ final ConversionException exception = new ConversionException("Cannot handle CGLIB callback");
+ exception.add("CGLIB callback type", callback.getClass().getName());
+ throw exception;
+ }
+ interfaces = iface.getInterfaces();
+ if (Arrays.asList(interfaces).contains(Callback.class)) {
+ break;
+ }
+ i = -1;
+ }
+ }
+ return (Callback)Proxy.newProxyInstance(iface.getClassLoader(), new Class[]{iface},
+ new ReverseEngineeringInvocationHandler(index, callbackIndexMap));
+ }
+
+ @Override
+ public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
+ final Enhancer enhancer = new Enhancer();
+ reader.moveDown();
+ enhancer.setSuperclass((Class>)context.convertAnother(null, Class.class));
+ reader.moveUp();
+ reader.moveDown();
+ final List> interfaces = new ArrayList>();
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ interfaces.add((Class>)context.convertAnother(null, mapper.realClass(reader.getNodeName())));
+ reader.moveUp();
+ }
+ enhancer.setInterfaces(interfaces.toArray(new Class[interfaces.size()]));
+ reader.moveUp();
+ reader.moveDown();
+ final boolean useFactory = Boolean.valueOf(reader.getValue()).booleanValue();
+ enhancer.setUseFactory(useFactory);
+ reader.moveUp();
+
+ final List callbacksToEnhance = new ArrayList();
+ final List callbacks = new ArrayList();
+ Map callbackIndexMap = null;
+ reader.moveDown();
+ if ("callbacks".equals(reader.getNodeName())) {
+ reader.moveDown();
+ @SuppressWarnings("unchecked")
+ final Map typedMap = (Map)context.convertAnother(null, HashMap.class);
+ callbackIndexMap = typedMap;
+ reader.moveUp();
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ readCallback(reader, context, callbacksToEnhance, callbacks);
+ reader.moveUp();
+ }
+ } else {
+ readCallback(reader, context, callbacksToEnhance, callbacks);
+ }
+ enhancer.setCallbacks(callbacksToEnhance.toArray(new Callback[callbacksToEnhance.size()]));
+ if (callbackIndexMap != null) {
+ enhancer.setCallbackFilter(new ReverseEngineeredCallbackFilter(callbackIndexMap));
+ }
+ reader.moveUp();
+ Object result = null;
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ if (reader.getNodeName().equals("serialVersionUID")) {
+ enhancer.setSerialVersionUID(Long.valueOf(reader.getValue()));
+ } else if (reader.getNodeName().equals("instance")) {
+ result = create(enhancer, callbacks, useFactory);
+ super.doUnmarshalConditionally(result, reader, context);
+ }
+ reader.moveUp();
+ }
+ if (result == null) {
+ result = create(enhancer, callbacks, useFactory);
+ }
+ return serializationMethodInvoker.callReadResolve(result);
+ }
+
+ private void readCallback(final HierarchicalStreamReader reader, final UnmarshallingContext context,
+ final List callbacksToEnhance, final List callbacks) {
+ final Callback callback = (Callback)context.convertAnother(null, mapper.realClass(reader.getNodeName()));
+ callbacks.add(callback);
+ if (callback == null) {
+ callbacksToEnhance.add(NoOp.INSTANCE);
+ } else {
+ callbacksToEnhance.add(callback);
+ }
+ }
+
+ private Object create(final Enhancer enhancer, final List callbacks, final boolean useFactory) {
+ final Object result = enhancer.create();
+ if (useFactory) {
+ ((Factory)result).setCallbacks(callbacks.toArray(new Callback[callbacks.size()]));
+ }
+ return result;
+ }
+
+ @Override
+ protected List> hierarchyFor(final Class> type) {
+ final List> typeHierarchy = super.hierarchyFor(type);
+ // drop the CGLIB proxy
+ typeHierarchy.remove(typeHierarchy.size() - 1);
+ return typeHierarchy;
+ }
+
+ private Object readResolve() {
+ fieldCache = new HashMap>();
+ return this;
+ }
+
+ private static class CGLIBFilteringReflectionProvider extends ReflectionProviderWrapper {
+
+ public CGLIBFilteringReflectionProvider(final ReflectionProvider reflectionProvider) {
+ super(reflectionProvider);
+ }
+
+ @Override
+ public void visitSerializableFields(final Object object, final Visitor visitor) {
+ wrapped.visitSerializableFields(object, new Visitor() {
+ @Override
+ public void visit(final String name, final Class> type, final Class> definedIn, final Object value) {
+ if (!name.startsWith("CGLIB$")) {
+ visitor.visit(name, type, definedIn, value);
+ }
+ }
+ });
+ }
+ }
+
+ private static final class ReverseEngineeringInvocationHandler implements InvocationHandler {
+ private final Integer index;
+ private final Map super Object, ? super Object> indexMap;
+
+ public ReverseEngineeringInvocationHandler(final int index, final Map super Object, ? super Object> indexMap) {
+ this.indexMap = indexMap;
+ this.index = Integer.valueOf(index);
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ indexMap.put(indexMap.get(null), index);
+ return null;
+ }
+ }
+
+ private static class ReverseEngineeredCallbackFilter implements CallbackFilter {
+
+ private final Map callbackIndexMap;
+
+ public ReverseEngineeredCallbackFilter(final Map callbackIndexMap) {
+ this.callbackIndexMap = callbackIndexMap;
+ }
+
+ @Override
+ public int accept(final Method method) {
+ if (!callbackIndexMap.containsKey(method)) {
+ final ConversionException exception = new ConversionException(
+ "CGLIB callback not detected in reverse engineering");
+ exception.add("CGLIB callback", method.toString());
+ throw exception;
+ }
+ return callbackIndexMap.get(method).intValue();
+ }
+
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java (.../ExternalizableConverter.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java (.../ExternalizableConverter.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,117 +1,193 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 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 24. August 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.NotActiveException;
+import java.io.ObjectInputValidation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.core.ClassLoaderReference;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
+import com.thoughtworks.xstream.core.util.HierarchicalStreams;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.NotActiveException;
-import java.io.ObjectInput;
-import java.io.ObjectInputValidation;
-import java.io.ObjectOutput;
-import java.util.Map;
/**
- * Converts any object that implements the java.io.Externalizable interface, allowing compatability with native Java
+ * Converts any object that implements the {@link Externalizable} interface, allowing compatibility with native Java
* serialization.
- *
+ *
* @author Joe Walnes
*/
public class ExternalizableConverter implements Converter {
- private Mapper mapper;
+ private final Mapper mapper;
+ private final ClassLoaderReference classLoaderReference;
- public ExternalizableConverter(Mapper mapper) {
+ /**
+ * Construct an ExternalizableConverter.
+ *
+ * @param mapper the Mapper chain
+ * @param classLoaderReference the reference to XStream's {@link ClassLoader} instance
+ * @since 1.4.5
+ */
+ public ExternalizableConverter(final Mapper mapper, final ClassLoaderReference classLoaderReference) {
this.mapper = mapper;
+ this.classLoaderReference = classLoaderReference;
}
- public boolean canConvert(Class type) {
- return Externalizable.class.isAssignableFrom(type);
+ /**
+ * @deprecated As of 1.4.5 use {@link #ExternalizableConverter(Mapper, ClassLoaderReference)}
+ */
+ @Deprecated
+ public ExternalizableConverter(final Mapper mapper, final ClassLoader classLoader) {
+ this(mapper, new ClassLoaderReference(classLoader));
}
- public void marshal(Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
+ /**
+ * @deprecated As of 1.4 use {@link #ExternalizableConverter(Mapper, ClassLoader)}
+ */
+ @Deprecated
+ public ExternalizableConverter(final Mapper mapper) {
+ this(mapper, ExternalizableConverter.class.getClassLoader());
+ }
+
+ @Override
+ public boolean canConvert(final Class> type) {
+ return JVM.canCreateDerivedObjectOutputStream() && Externalizable.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
try {
- Externalizable externalizable = (Externalizable) source;
- CustomObjectOutputStream.StreamCallback callback = new CustomObjectOutputStream.StreamCallback() {
- public void writeToStream(Object object) {
+ final Externalizable externalizable = (Externalizable)source;
+ final CustomObjectOutputStream.StreamCallback callback = new CustomObjectOutputStream.StreamCallback() {
+ @Override
+ public void writeToStream(final Object object) {
if (object == null) {
writer.startNode("null");
writer.endNode();
} else {
- writer.startNode(mapper.serializedClass(object.getClass()));
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(object
+ .getClass()), object.getClass());
context.convertAnother(object);
writer.endNode();
}
}
- public void writeFieldsToStream(Map fields) {
+ @Override
+ public void writeFieldsToStream(final Map fields) {
throw new UnsupportedOperationException();
}
+ @Override
public void defaultWriteObject() {
throw new UnsupportedOperationException();
}
+ @Override
public void flush() {
writer.flush();
}
+ @Override
public void close() {
- throw new UnsupportedOperationException("Objects are not allowed to call ObjecOutput.close() from writeExternal()");
+ throw new UnsupportedOperationException(
+ "Objects are not allowed to call ObjectOutput.close() from writeExternal()");
}
};
- ObjectOutput objectOutput = CustomObjectOutputStream.getInstance(context, callback);
+ @SuppressWarnings("resource")
+ final CustomObjectOutputStream objectOutput = CustomObjectOutputStream.getInstance(context, callback);
externalizable.writeExternal(objectOutput);
- } catch (IOException e) {
- throw new ConversionException("Cannot serialize " + source.getClass().getName() + " using Externalization", e);
+ objectOutput.popCallback();
+ } catch (final IOException e) {
+ throw new ConversionException("Cannot serialize " + source.getClass().getName() + " using Externalization",
+ e);
}
}
+ @Override
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
- final Class type = context.getRequiredType();
+ final Class> type = context.getRequiredType();
+ final Constructor> defaultConstructor;
try {
- final Externalizable externalizable = (Externalizable) type.newInstance();
- CustomObjectInputStream.StreamCallback callback = new CustomObjectInputStream.StreamCallback() {
+ defaultConstructor = type.getDeclaredConstructor();
+ if (!defaultConstructor.isAccessible()) {
+ defaultConstructor.setAccessible(true);
+ }
+ final Externalizable externalizable = (Externalizable)defaultConstructor.newInstance();
+ final CustomObjectInputStream.StreamCallback callback = new CustomObjectInputStream.StreamCallback() {
+ @Override
public Object readFromStream() {
reader.moveDown();
- Object streamItem = context.convertAnother(externalizable, mapper.realClass(reader.getNodeName()));
+ final Class> type = HierarchicalStreams.readClassType(reader, mapper);
+ final Object streamItem = context.convertAnother(externalizable, type);
reader.moveUp();
return streamItem;
}
- public Map readFieldsFromStream() {
+ @Override
+ public Map readFieldsFromStream() {
throw new UnsupportedOperationException();
}
+ @Override
public void defaultReadObject() {
throw new UnsupportedOperationException();
}
- public void registerValidation(ObjectInputValidation validation, int priority) throws NotActiveException {
+ @Override
+ public void registerValidation(final ObjectInputValidation validation, final int priority)
+ throws NotActiveException {
throw new NotActiveException("stream inactive");
}
+ @Override
public void close() {
- throw new UnsupportedOperationException("Objects are not allowed to call ObjectInput.close() from readExternal()");
+ throw new UnsupportedOperationException(
+ "Objects are not allowed to call ObjectInput.close() from readExternal()");
}
};
- ObjectInput objectInput = CustomObjectInputStream.getInstance(context, callback);
- externalizable.readExternal(objectInput);
+ {
+ @SuppressWarnings("resource")
+ final CustomObjectInputStream objectInput = CustomObjectInputStream.getInstance(context, callback,
+ classLoaderReference);
+ externalizable.readExternal(objectInput);
+ objectInput.popCallback();
+ }
return externalizable;
- } catch (InstantiationException e) {
+ } catch (final NoSuchMethodException e) {
+ throw new ConversionException("Cannot construct " + type.getClass() + ", missing default constructor", e);
+ } catch (final InvocationTargetException e) {
throw new ConversionException("Cannot construct " + type.getClass(), e);
- } catch (IllegalAccessException e) {
+ } catch (final InstantiationException e) {
throw new ConversionException("Cannot construct " + type.getClass(), e);
- } catch (IOException e) {
+ } catch (final IllegalAccessException e) {
+ throw new ConversionException("Cannot construct " + type.getClass(), e);
+ } catch (final IOException e) {
throw new ConversionException("Cannot externalize " + type.getClass(), e);
- } catch (ClassNotFoundException e) {
+ } catch (final ClassNotFoundException e) {
throw new ConversionException("Cannot externalize " + type.getClass(), e);
}
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldDictionary.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldDictionary.java (.../FieldDictionary.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldDictionary.java (.../FieldDictionary.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,110 +1,178 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 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 14. May 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
-import com.thoughtworks.xstream.core.util.OrderRetainingMap;
-
import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
-public class FieldDictionary {
+import com.thoughtworks.xstream.core.Caching;
+import com.thoughtworks.xstream.core.JVM;
- private final Map keyedByFieldNameCache = Collections.synchronizedMap(new HashMap());
- private final Map keyedByFieldKeyCache = Collections.synchronizedMap(new HashMap());
- public Iterator serializableFieldsFor(Class cls) {
+/**
+ * A field dictionary instance caches information about classes fields.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @author Guilherme Silveira
+ */
+public class FieldDictionary implements Caching {
+
+ private transient Map, Map> keyedByFieldNameCache;
+ private transient Map, Map> keyedByFieldKeyCache;
+ private final FieldKeySorter sorter;
+
+ public FieldDictionary() {
+ this(new ImmutableFieldKeySorter());
+ }
+
+ public FieldDictionary(final FieldKeySorter sorter) {
+ this.sorter = sorter;
+ init();
+ }
+
+ private void init() {
+ keyedByFieldNameCache = new HashMap, Map>();
+ keyedByFieldKeyCache = new HashMap, Map>();
+ keyedByFieldNameCache.put(Object.class, Collections.emptyMap());
+ keyedByFieldKeyCache.put(Object.class, Collections.emptyMap());
+ }
+
+ /**
+ * Returns an iterator for all fields for some class
+ *
+ * @param cls the class you are interested on
+ * @return an iterator for its fields
+ */
+ public Iterator fieldsFor(final Class> cls) {
return buildMap(cls, true).values().iterator();
}
- public Field field(Class cls, String name, Class definedIn) {
- Map fields = buildMap(cls, definedIn != null);
- Field field = (Field) fields.get(definedIn != null ? (Object) new FieldKey(name, definedIn, 0) : (Object) name);
+ /**
+ * Returns an specific field of some class. If definedIn is null, it searches for the field named 'name' inside the
+ * class cls. If definedIn is different than null, tries to find the specified field name in the specified class cls
+ * which should be defined in class definedIn (either equals cls or a one of it's superclasses)
+ *
+ * @param cls the class where the field is to be searched
+ * @param name the field name
+ * @param definedIn the superclass (or the class itself) of cls where the field was defined
+ * @return the field itself
+ * @throws ObjectAccessException if no field can be found
+ */
+ public Field field(final Class> cls, final String name, final Class> definedIn) {
+ final Field field = fieldOrNull(cls, name, definedIn);
if (field == null) {
- throw new ObjectAccessException("No such field " + cls.getName() + "." + name);
+ throw new MissingFieldException(cls.getName(), name);
} else {
return field;
}
}
- private Map buildMap(Class cls, boolean tupleKeyed) {
- final String clsName = cls.getName();
- if (!keyedByFieldNameCache.containsKey(clsName)) {
- synchronized (keyedByFieldKeyCache) {
- if (!keyedByFieldNameCache.containsKey(clsName)) { // double check
- final Map keyedByFieldName = new HashMap();
- final Map keyedByFieldKey = new OrderRetainingMap();
- while (!Object.class.equals(cls)) {
- Field[] fields = cls.getDeclaredFields();
+ /**
+ * Returns an specific field of some class. If definedIn is null, it searches for the field named 'name' inside the
+ * class cls. If definedIn is different than null, tries to find the specified field name in the specified class cls
+ * which should be defined in class definedIn (either equals cls or a one of it's superclasses)
+ *
+ * @param cls the class where the field is to be searched
+ * @param name the field name
+ * @param definedIn the superclass (or the class itself) of cls where the field was defined
+ * @return the field itself or null
+ * @since 1.4
+ */
+ public Field fieldOrNull(final Class> cls, final String name, final Class> definedIn) {
+ final Map, Field> fields = buildMap(cls, definedIn != null);
+ final Field field = fields.get(definedIn != null ? (Object)new FieldKey(name, definedIn, -1) : (Object)name);
+ return field;
+ }
+
+ private Map, Field> buildMap(final Class> type, final boolean tupleKeyed) {
+ Class> cls = type;
+ synchronized (this) {
+ if (!keyedByFieldNameCache.containsKey(type)) {
+ final List> superClasses = new ArrayList>();
+ while (!Object.class.equals(cls) && cls != null) {
+ superClasses.add(0, cls);
+ cls = cls.getSuperclass();
+ }
+ Map lastKeyedByFieldName = Collections.emptyMap();
+ Map lastKeyedByFieldKey = Collections.emptyMap();
+ for (final Class> element : superClasses) {
+ cls = element;
+ if (!keyedByFieldNameCache.containsKey(cls)) {
+ final Map keyedByFieldName = new HashMap(lastKeyedByFieldName);
+ final Map keyedByFieldKey = new LinkedHashMap(
+ lastKeyedByFieldKey);
+ final Field[] fields = cls.getDeclaredFields();
+ if (JVM.reverseFieldDefinition()) {
+ for (int i = fields.length >> 1; i-- > 0;) {
+ final int idx = fields.length - i - 1;
+ final Field field = fields[i];
+ fields[i] = fields[idx];
+ fields[idx] = field;
+ }
+ }
for (int i = 0; i < fields.length; i++) {
- Field field = fields[i];
- field.setAccessible(true);
- if (!keyedByFieldName.containsKey(field.getName())) {
+ final Field field = fields[i];
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ final FieldKey fieldKey = new FieldKey(field.getName(), field.getDeclaringClass(), i);
+ final Field existent = keyedByFieldName.get(field.getName());
+ if (existent == null
+ // do overwrite statics
+ || (existent.getModifiers() & Modifier.STATIC) != 0
+ // overwrite non-statics with non-statics only
+ || existent != null
+ && (field.getModifiers() & Modifier.STATIC) == 0) {
keyedByFieldName.put(field.getName(), field);
}
- keyedByFieldKey.put(new FieldKey(field.getName(), field.getDeclaringClass(), i), field);
+ keyedByFieldKey.put(fieldKey, field);
}
- cls = cls.getSuperclass();
+ final Map sortedFieldKeys = sorter.sort(cls, keyedByFieldKey);
+ keyedByFieldNameCache.put(cls, keyedByFieldName);
+ keyedByFieldKeyCache.put(cls, sortedFieldKeys);
+ lastKeyedByFieldName = keyedByFieldName;
+ lastKeyedByFieldKey = sortedFieldKeys;
+ } else {
+ lastKeyedByFieldName = keyedByFieldNameCache.get(cls);
+ lastKeyedByFieldKey = keyedByFieldKeyCache.get(cls);
}
- keyedByFieldNameCache.put(clsName, keyedByFieldName);
- keyedByFieldKeyCache.put(clsName, keyedByFieldKey);
}
+ return tupleKeyed ? lastKeyedByFieldKey : lastKeyedByFieldName;
}
}
- return (Map) (tupleKeyed ? keyedByFieldKeyCache.get(clsName) : keyedByFieldNameCache.get(clsName));
+ return tupleKeyed ? keyedByFieldKeyCache.get(type) : keyedByFieldNameCache.get(type);
}
- private static class FieldKey {
- private String fieldName;
- private Class declaringClass;
- private Integer depth;
- private int order;
-
- public FieldKey(String fieldName, Class declaringClass, int order) {
- this.fieldName = fieldName;
- this.declaringClass = declaringClass;
- this.order = order;
- Class c = declaringClass;
- int i = 0;
- while (c.getSuperclass() != null) {
- i++;
- c = c.getSuperclass();
- }
- depth = new Integer(i);
+ @Override
+ public synchronized void flushCache() {
+ final Set> objectTypeSet = Collections.>singleton(Object.class);
+ keyedByFieldNameCache.keySet().retainAll(objectTypeSet);
+ keyedByFieldKeyCache.keySet().retainAll(objectTypeSet);
+ if (sorter instanceof Caching) {
+ ((Caching)sorter).flushCache();
}
-
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof FieldKey)) return false;
-
- final FieldKey fieldKey = (FieldKey) o;
-
- if (declaringClass != null ? !declaringClass.equals(fieldKey.declaringClass) : fieldKey.declaringClass != null) return false;
- if (fieldName != null ? !fieldName.equals(fieldKey.fieldName) : fieldKey.fieldName != null) return false;
-
- return true;
- }
-
- public int hashCode() {
- int result;
- result = (fieldName != null ? fieldName.hashCode() : 0);
- result = 29 * result + (declaringClass != null ? declaringClass.hashCode() : 0);
- return result;
- }
-
- public String toString() {
- return "FieldKey{" +
- "order=" + order +
- ", writer=" + depth +
- ", declaringClass=" + declaringClass +
- ", fieldName='" + fieldName + "'" +
- "}";
- }
-
-
}
+ protected Object readResolve() {
+ init();
+ return this;
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldKey.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldKey.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldKey.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007, 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 10. April 2007 by Guilherme Silveira
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+/**
+ * A field key.
+ *
+ * @author Guilherme Silveira
+ * @author Jörg Schaible
+ */
+public class FieldKey {
+ final private String fieldName;
+ final private Class> declaringClass;
+ final private int depth;
+ final private int order;
+
+ public FieldKey(final String fieldName, final Class> declaringClass, final int order) {
+ if (fieldName == null || declaringClass == null) {
+ throw new IllegalArgumentException("fieldName or declaringClass is null");
+ }
+ this.fieldName = fieldName;
+ this.declaringClass = declaringClass;
+ this.order = order;
+ Class> c = declaringClass;
+ int i = 0;
+ while (c.getSuperclass() != null) {
+ i++;
+ c = c.getSuperclass();
+ }
+ depth = i;
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public Class> getDeclaringClass() {
+ return declaringClass;
+ }
+
+ public int getDepth() {
+ return depth;
+ }
+
+ public int getOrder() {
+ return order;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof FieldKey)) {
+ return false;
+ }
+
+ final FieldKey fieldKey = (FieldKey)o;
+
+ if (!declaringClass.equals(fieldKey.declaringClass)) {
+ return false;
+ }
+ if (!fieldName.equals(fieldKey.fieldName)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ result = fieldName.hashCode();
+ result = 29 * result + declaringClass.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "FieldKey{"
+ + "order="
+ + order
+ + ", writer="
+ + depth
+ + ", declaringClass="
+ + declaringClass
+ + ", fieldName='"
+ + fieldName
+ + "'"
+ + "}";
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldKeySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldKeySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/FieldKeySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007, 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 10. April 2007 by Guilherme Silveira
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+
+/**
+ * An interface capable of sorting fields.
+ *
+ * Implement this interface if you want to customize the field order in which XStream serializes objects.
+ *
+ *
+ * @author Guilherme Silveira
+ * @since 1.2.2
+ */
+public interface FieldKeySorter {
+
+ /**
+ * Sort the fields of a type.
+ *
+ * The method will be called with the class type that contains all the fields and a Map that retains the order in
+ * which the elements have been added. The sequence in which elements are returned by an iterator defines the
+ * processing order of the fields. An implementation may create a different Map with similar semantic, add all
+ * elements of the original map and return the new one.
+ *
+ *
+ * @param type the class that contains all the fields
+ * @param keyedByFieldKey a Map containing a {@link FieldKey} as key element and a {@link java.lang.reflect.Field}
+ * as value.
+ * @return a Map with all the entries of the original Map
+ * @since 1.2.2
+ */
+ Map sort(Class> type, Map keyedByFieldKey);
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ImmutableFieldKeySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ImmutableFieldKeySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ImmutableFieldKeySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007, 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 10. April 2007 by Guilherme Silveira
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+
+/**
+ * Does not change the order of the fields.
+ *
+ * @author Guilherme Silveira
+ * @since 1.2.2
+ */
+public class ImmutableFieldKeySorter implements FieldKeySorter {
+
+ @Override
+ public Map sort(final Class> type, final Map keyedByFieldKey) {
+ return keyedByFieldKey;
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/MissingFieldException.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/MissingFieldException.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/MissingFieldException.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 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 01. October 2011 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+/**
+ * Indicates a missing field or property creating an object.
+ *
+ * @author Nikita Levyankov
+ * @author Joerg Schaible
+ * @since 1.4.2
+ */
+public class MissingFieldException extends ObjectAccessException {
+
+ private final String fieldName;
+ private final String className;
+
+ /**
+ * Construct a MissingFieldException.
+ * @param className the name of the class missing the field
+ * @param fieldName the name of the missed field
+ * @since 1.4.2
+ */
+ public MissingFieldException(final String className, final String fieldName) {
+ super("No field '" + fieldName + "' found in class '" + className + "'");
+ this.className = className;
+ this.fieldName = fieldName;
+ }
+
+ /**
+ * Retrieve the name of the missing field.
+ * @return the field name
+ * @since 1.4.2
+ */
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ /**
+ * Retrieve the name of the class with the missing field.
+ * @return the class name
+ * @since 1.4.2
+ */
+ protected String getClassName() {
+ return className;
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/NativeFieldKeySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/NativeFieldKeySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/NativeFieldKeySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007, 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 17.05.2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+/**
+ * Sort the fields in their natural order. Fields are returned in their declaration order, fields of base classes first.
+ *
+ * @author Jörg Schaible
+ * @since 1.2.2
+ */
+public class NativeFieldKeySorter implements FieldKeySorter {
+
+ @Override
+ public Map sort(final Class> type, final Map keyedByFieldKey) {
+ final Map map = new TreeMap(new Comparator() {
+
+ @Override
+ public int compare(final FieldKey fieldKey1, final FieldKey fieldKey2) {
+ int i = fieldKey1.getDepth() - fieldKey2.getDepth();
+ if (i == 0) {
+ i = fieldKey1.getOrder() - fieldKey2.getOrder();
+ }
+ return i;
+ }
+ });
+ map.putAll(keyedByFieldKey);
+ return map;
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ObjectAccessException.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ObjectAccessException.java (.../ObjectAccessException.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ObjectAccessException.java (.../ObjectAccessException.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,8 +1,19 @@
+/*
+ * Copyright (C) 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007 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 07. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
-import com.thoughtworks.xstream.core.BaseException;
+import com.thoughtworks.xstream.XStreamException;
-public class ObjectAccessException extends BaseException {
+public class ObjectAccessException extends XStreamException {
public ObjectAccessException(String message) {
super(message);
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/PureJavaReflectionProvider.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/PureJavaReflectionProvider.java (.../PureJavaReflectionProvider.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/PureJavaReflectionProvider.java (.../PureJavaReflectionProvider.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,154 +1,212 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2009, 2011, 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 07. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Collections;
-import java.io.Serializable;
-import java.io.ObjectStreamConstants;
-import java.io.DataOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
import java.io.IOException;
-import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
+import java.io.ObjectStreamConstants;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
/**
- * Pure Java ObjectFactory that instantiates objects using standard Java reflection, however the types of objects
- * that can be constructed are limited.
- *
- * Can newInstance: classes with public visibility, outer classes, static inner classes, classes with default constructors
- * and any class that implements java.io.Serializable.
- * Cannot newInstance: classes without public visibility, non-static inner classes, classes without default constructors.
- * Note that any code in the constructor of a class will be executed when the ObjectFactory instantiates the object.
+ * Pure Java ObjectFactory that instantiates objects using standard Java reflection, however the types of objects that
+ * can be constructed are limited.
+ *
+ * Can newInstance: classes with public visibility, outer classes, static inner classes, classes with default
+ * constructors and any class that implements java.io.Serializable.
*
+ *
+ * Cannot newInstance: classes without public visibility, non-static inner classes, classes without default
+ * constructors. Note that any code in the constructor of a class will be executed when the ObjectFactory instantiates
+ * the object.
+ *
+ *
+ * @author Joe Walnes
*/
public class PureJavaReflectionProvider implements ReflectionProvider {
- private final Map serializedDataCache = Collections.synchronizedMap(new HashMap());
+ private transient Map, byte[]> serializedDataCache;
+ protected FieldDictionary fieldDictionary;
- protected FieldDictionary fieldDictionary = new FieldDictionary();
+ public PureJavaReflectionProvider() {
+ this(new FieldDictionary(new ImmutableFieldKeySorter()));
+ }
- public Object newInstance(Class type) {
+ public PureJavaReflectionProvider(final FieldDictionary fieldDictionary) {
+ this.fieldDictionary = fieldDictionary;
+ init();
+ }
+
+ @Override
+ public Object newInstance(final Class> type) {
try {
- Constructor[] constructors = type.getDeclaredConstructors();
- for (int i = 0; i < constructors.length; i++) {
- if (constructors[i].getParameterTypes().length == 0) {
- if (!Modifier.isPublic(constructors[i].getModifiers())) {
- constructors[i].setAccessible(true);
+ for (final Constructor> constructor : type.getDeclaredConstructors()) {
+ if (constructor.getParameterTypes().length == 0) {
+ if (!constructor.isAccessible()) {
+ constructor.setAccessible(true);
}
- return constructors[i].newInstance(new Object[0]);
+ return constructor.newInstance(new Object[0]);
}
}
if (Serializable.class.isAssignableFrom(type)) {
return instantiateUsingSerialization(type);
} else {
- throw new ObjectAccessException("Cannot construct " + type.getName()
- + " as it does not have a no-args constructor");
+ throw new ObjectAccessException("Cannot construct "
+ + type.getName()
+ + " as it does not have a no-args constructor");
}
- } catch (InstantiationException e) {
+ } catch (final InstantiationException e) {
throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (IllegalAccessException e) {
+ } catch (final IllegalAccessException e) {
throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (InvocationTargetException e) {
+ } catch (final InvocationTargetException e) {
if (e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException)e.getTargetException();
} else if (e.getTargetException() instanceof Error) {
throw (Error)e.getTargetException();
} else {
- throw new ObjectAccessException("Constructor for " + type.getName() + " threw an exception", e);
+ throw new ObjectAccessException("Constructor for " + type.getName() + " threw an exception", e
+ .getTargetException());
}
}
}
- private Object instantiateUsingSerialization(Class type) {
+ private Object instantiateUsingSerialization(final Class> type) {
try {
- byte[] data;
- if (serializedDataCache.containsKey(type)) {
- data = (byte[]) serializedDataCache.get(type);
- } else {
- ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- DataOutputStream stream = new DataOutputStream(bytes);
- stream.writeShort(ObjectStreamConstants.STREAM_MAGIC);
- stream.writeShort(ObjectStreamConstants.STREAM_VERSION);
- stream.writeByte(ObjectStreamConstants.TC_OBJECT);
- stream.writeByte(ObjectStreamConstants.TC_CLASSDESC);
- stream.writeUTF(type.getName());
- stream.writeLong(ObjectStreamClass.lookup(type).getSerialVersionUID());
- stream.writeByte(2); // classDescFlags (2 = Serializable)
- stream.writeShort(0); // field count
- stream.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
- stream.writeByte(ObjectStreamConstants.TC_NULL);
- data = bytes.toByteArray();
- serializedDataCache.put(type, data);
- }
+ synchronized (serializedDataCache) {
+ byte[] data = serializedDataCache.get(type);
+ if (data == null) {
+ final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ final DataOutputStream stream = new DataOutputStream(bytes);
+ stream.writeShort(ObjectStreamConstants.STREAM_MAGIC);
+ stream.writeShort(ObjectStreamConstants.STREAM_VERSION);
+ stream.writeByte(ObjectStreamConstants.TC_OBJECT);
+ stream.writeByte(ObjectStreamConstants.TC_CLASSDESC);
+ stream.writeUTF(type.getName());
+ stream.writeLong(ObjectStreamClass.lookup(type).getSerialVersionUID());
+ stream.writeByte(2); // classDescFlags (2 = Serializable)
+ stream.writeShort(0); // field count
+ stream.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
+ stream.writeByte(ObjectStreamConstants.TC_NULL);
+ data = bytes.toByteArray();
+ serializedDataCache.put(type, data);
+ }
- ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
- return in.readObject();
- } catch (IOException e) {
- throw new ObjectAccessException("", e);
- } catch (ClassNotFoundException e) {
- throw new ObjectAccessException("", e);
+ final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data)) {
+ @Override
+ protected Class> resolveClass(final ObjectStreamClass desc) throws ClassNotFoundException {
+ return Class.forName(desc.getName(), false, type.getClassLoader());
+ }
+ };
+ return in.readObject();
+ }
+ } catch (final IOException e) {
+ throw new ObjectAccessException("Cannot create " + type.getName() + " by JDK serialization", e);
+ } catch (final ClassNotFoundException e) {
+ throw new ObjectAccessException("Cannot find class " + e.getMessage(), e);
}
}
- public void visitSerializableFields(Object object, ReflectionProvider.Visitor visitor) {
- for (Iterator iterator = fieldDictionary.serializableFieldsFor(object.getClass()); iterator.hasNext();) {
- Field field = (Field) iterator.next();
+ @Override
+ public void visitSerializableFields(final Object object, final ReflectionProvider.Visitor visitor) {
+ for (final Iterator iterator = fieldDictionary.fieldsFor(object.getClass()); iterator.hasNext();) {
+ final Field field = iterator.next();
if (!fieldModifiersSupported(field)) {
continue;
}
validateFieldAccess(field);
try {
- Object value = field.get(object);
+ final Object value = field.get(object);
visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (IllegalAccessException e) {
+ } catch (final IllegalAccessException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
}
}
}
- public void writeField(Object object, String fieldName, Object value, Class definedIn) {
- Field field = fieldDictionary.field(object.getClass(), fieldName, definedIn);
+ @Override
+ public void writeField(final Object object, final String fieldName, final Object value, final Class> definedIn) {
+ final Field field = fieldDictionary.field(object.getClass(), fieldName, definedIn);
validateFieldAccess(field);
try {
field.set(object, value);
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
- } catch (IllegalAccessException e) {
+ } catch (final IllegalAccessException e) {
throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
}
}
- public Class getFieldType(Object object, String fieldName, Class definedIn) {
+ @Override
+ public Class> getFieldType(final Object object, final String fieldName, final Class> definedIn) {
return fieldDictionary.field(object.getClass(), fieldName, definedIn).getType();
}
- public boolean fieldDefinedInClass(String fieldName, Class type) {
- try {
- fieldDictionary.field(type, fieldName, null);
- return true;
- } catch (ObjectAccessException e) {
- return false;
- }
+ /**
+ * @deprecated As of 1.4.5, use {@link #getFieldOrNull(Class, String)} instead
+ */
+ @Deprecated
+ @Override
+ public boolean fieldDefinedInClass(final String fieldName, final Class> type) {
+ final Field field = fieldDictionary.fieldOrNull(type, fieldName, null);
+ return field != null && fieldModifiersSupported(field);
}
- protected boolean fieldModifiersSupported(Field field) {
- return !(Modifier.isStatic(field.getModifiers())
- || Modifier.isTransient(field.getModifiers()));
+ protected boolean fieldModifiersSupported(final Field field) {
+ final int modifiers = field.getModifiers();
+ return !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers));
}
- protected void validateFieldAccess(Field field) {
+ protected void validateFieldAccess(final Field field) {
if (Modifier.isFinal(field.getModifiers())) {
- throw new ObjectAccessException("Invalid final field "
- + field.getDeclaringClass().getName() + "." + field.getName());
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
}
}
+ @Override
+ public Field getField(final Class> definedIn, final String fieldName) {
+ return fieldDictionary.field(definedIn, fieldName, null);
+ }
+
+ @Override
+ public Field getFieldOrNull(final Class> definedIn, final String fieldName) {
+ return fieldDictionary.fieldOrNull(definedIn, fieldName, null);
+ }
+
+ public void setFieldDictionary(final FieldDictionary dictionary) {
+ fieldDictionary = dictionary;
+ }
+
+ private Object readResolve() {
+ init();
+ return this;
+ }
+
+ protected void init() {
+ serializedDataCache = new HashMap, byte[]>();
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionConverter.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionConverter.java (.../ReflectionConverter.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionConverter.java (.../ReflectionConverter.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,191 +1,46 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 07. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
-import com.thoughtworks.xstream.converters.ConversionException;
-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 com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.mapper.Mapper;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-public class ReflectionConverter implements Converter {
+public class ReflectionConverter extends AbstractReflectionConverter {
- private final Mapper mapper;
- private final ReflectionProvider reflectionProvider;
- private final SerializationMethodInvoker serializationMethodInvoker;
+ // Might be missing in Android
+ private final static Class> eventHandlerType = JVM.loadClassForName("java.beans.EventHandler");
+ private Class> type;
- public ReflectionConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
- this.mapper = mapper;
- this.reflectionProvider = reflectionProvider;
- serializationMethodInvoker = new SerializationMethodInvoker();
+ public ReflectionConverter(final Mapper mapper, final ReflectionProvider reflectionProvider) {
+ super(mapper, reflectionProvider);
}
- public boolean canConvert(Class type) {
- return true;
+ /**
+ * Construct a ReflectionConverter for an explicit type.
+ *
+ * @param mapper the mapper in use
+ * @param reflectionProvider the reflection provider in use
+ * @param type the explicit type to handle
+ * @since 1.4.7
+ */
+ public ReflectionConverter(final Mapper mapper, final ReflectionProvider reflectionProvider, final Class> type) {
+ this(mapper, reflectionProvider);
+ this.type = type;
}
- public void marshal(Object original, final HierarchicalStreamWriter writer, final MarshallingContext context) {
- final Object source = serializationMethodInvoker.callWriteReplace(original);
-
- if (source.getClass() != original.getClass()) {
- writer.addAttribute(mapper.attributeForReadResolveField(), mapper.serializedClass(source.getClass()));
- }
-
- final Set seenFields = new HashSet();
-
- reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
- public void visit(String fieldName, Class fieldType, Class definedIn, Object newObj) {
- if (newObj != null) {
- Mapper.ImplicitCollectionMapping mapping = mapper.getImplicitCollectionDefForFieldName(source.getClass(), fieldName);
- if (mapping != null) {
- if (mapping.getItemFieldName() != null) {
- ArrayList list = (ArrayList) newObj;
- for (Iterator iter = list.iterator(); iter.hasNext();) {
- Object obj = iter.next();
- writeField(mapping.getItemFieldName(), mapping.getItemType(), definedIn, obj);
- }
- } else {
- context.convertAnother(newObj);
- }
- } else {
- writeField(fieldName, fieldType, definedIn, newObj);
- seenFields.add(fieldName);
- }
- }
- }
-
- private void writeField(String fieldName, Class fieldType, Class definedIn, Object newObj) {
- if (!mapper.shouldSerializeMember(definedIn, fieldName)) {
- return;
- }
- writer.startNode(mapper.serializedMember(definedIn, fieldName));
-
- Class actualType = newObj.getClass();
-
- Class defaultType = mapper.defaultImplementationOf(fieldType);
- if (!actualType.equals(defaultType)) {
- writer.addAttribute(mapper.attributeForImplementationClass(), mapper.serializedClass(actualType));
- }
-
- if (seenFields.contains(fieldName)) {
- writer.addAttribute(mapper.attributeForClassDefiningField(), mapper.serializedClass(definedIn));
- }
- context.convertAnother(newObj);
-
- writer.endNode();
- }
-
- });
+ @Override
+ public boolean canConvert(final Class> type) {
+ return (this.type != null && this.type == type || this.type == null && type != null && type != eventHandlerType)
+ && canAccess(type);
}
-
- public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
- final Object result = instantiateNewInstance(context, reader.getAttribute(mapper.attributeForReadResolveField()));
- final SeenFields seenFields = new SeenFields();
-
- Map implicitCollectionsForCurrentObject = null;
- while (reader.hasMoreChildren()) {
- reader.moveDown();
-
- String fieldName = mapper.realMember(result.getClass(), reader.getNodeName());
-
- Class classDefiningField = determineWhichClassDefinesField(reader);
- boolean fieldExistsInClass = reflectionProvider.fieldDefinedInClass(fieldName, result.getClass());
-
- Class type = determineType(reader, fieldExistsInClass, result, fieldName, classDefiningField);
- Object value = context.convertAnother(result, type);
-
- if (fieldExistsInClass) {
- reflectionProvider.writeField(result, fieldName, value, classDefiningField);
- seenFields.add(classDefiningField, fieldName);
- } else {
- implicitCollectionsForCurrentObject = writeValueToImplicitCollection(context, value, implicitCollectionsForCurrentObject, result, fieldName);
- }
-
- reader.moveUp();
- }
-
- return serializationMethodInvoker.callReadResolve(result);
- }
-
-
- private Map writeValueToImplicitCollection(UnmarshallingContext context, Object value, Map implicitCollections, Object result, String itemFieldName) {
- String fieldName = mapper.getFieldNameForItemTypeAndName(context.getRequiredType(), value.getClass(), itemFieldName);
- if (fieldName != null) {
- if (implicitCollections == null) {
- implicitCollections = new HashMap(); // lazy instantiation
- }
- Collection collection = (Collection) implicitCollections.get(fieldName);
- if (collection == null) {
- collection = new ArrayList();
- reflectionProvider.writeField(result, fieldName, collection, null);
- implicitCollections.put(fieldName, collection);
- }
- collection.add(value);
- }
- return implicitCollections;
- }
-
- private Class determineWhichClassDefinesField(HierarchicalStreamReader reader) {
- String definedIn = reader.getAttribute(mapper.attributeForClassDefiningField());
- return definedIn == null ? null : mapper.realClass(definedIn);
- }
-
- private Object instantiateNewInstance(UnmarshallingContext context, String readResolveValue) {
- Object currentObject = context.currentObject();
- if (currentObject != null) {
- return currentObject;
- } else if (readResolveValue != null) {
- return reflectionProvider.newInstance(mapper.realClass(readResolveValue));
- } else {
- return reflectionProvider.newInstance(context.getRequiredType());
- }
- }
-
- private static class SeenFields {
-
- private Set seen = new HashSet();
-
- public void add(Class definedInCls, String fieldName) {
- String uniqueKey = fieldName;
- if (definedInCls != null) {
- uniqueKey += " [" + definedInCls.getName() + "]";
- }
- if (seen.contains(uniqueKey)) {
- throw new DuplicateFieldException(uniqueKey);
- } else {
- seen.add(uniqueKey);
- }
- }
-
- }
-
- private Class determineType(HierarchicalStreamReader reader, boolean validField, Object result, String fieldName, Class definedInCls) {
- String classAttribute = reader.getAttribute(mapper.attributeForImplementationClass());
- if (classAttribute != null) {
- return mapper.realClass(classAttribute);
- } else if (!validField) {
- Class itemType = mapper.getItemTypeForItemFieldName(result.getClass(), fieldName);
- if (itemType != null) {
- return itemType;
- } else {
- return mapper.realClass(reader.getNodeName());
- }
- } else {
- return mapper.defaultImplementationOf(reflectionProvider.getFieldType(result, fieldName, definedInCls));
- }
- }
-
- public static class DuplicateFieldException extends ConversionException {
- public DuplicateFieldException(String msg) {
- super(msg);
- }
- }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionProvider.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionProvider.java (.../ReflectionProvider.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionProvider.java (.../ReflectionProvider.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,21 +1,80 @@
+/*
+ * Copyright (C) 2004, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 07. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
+import java.lang.reflect.Field;
+
+
/**
* Provides core reflection services.
+ *
+ * @author Joe Walnes
*/
public interface ReflectionProvider {
- Object newInstance(Class type);
+ /**
+ * Creates a new instance of the specified type. It is in the responsibility of the implementation how such an
+ * instance is created.
+ *
+ * @param type the type to instantiate
+ * @return a new instance of this type
+ */
+ Object newInstance(Class> type);
void visitSerializableFields(Object object, Visitor visitor);
- void writeField(Object object, String fieldName, Object value, Class definedIn);
+ void writeField(Object object, String fieldName, Object value, Class> definedIn);
- Class getFieldType(Object object, String fieldName, Class definedIn);
+ Class> getFieldType(Object object, String fieldName, Class> definedIn);
- boolean fieldDefinedInClass(String fieldName, Class type);
+ /**
+ * @deprecated As of 1.4.5, use {@link #getFieldOrNull(Class, String)} instead
+ */
+ @Deprecated
+ boolean fieldDefinedInClass(String fieldName, Class> type);
+ /**
+ * A visitor interface for serializable fields defined in a class.
+ */
interface Visitor {
- void visit(String name, Class type, Class definedIn, Object value);
+
+ /**
+ * Callback for each visit
+ *
+ * @param name field name
+ * @param type field type
+ * @param definedIn where the field was defined
+ * @param value field value
+ */
+ void visit(String name, Class> type, Class> definedIn, Object value);
}
+
+ /**
+ * Returns a field defined in some class.
+ *
+ * @param definedIn class where the field was defined
+ * @param fieldName field name
+ * @return the field itself
+ * @throws ObjectAccessException if field does not exist
+ */
+ Field getField(Class> definedIn, String fieldName);
+
+ /**
+ * Returns a field defined in some class.
+ *
+ * @param definedIn class where the field was defined
+ * @param fieldName field name
+ * @return the field itself or null
+ * @since 1.4.5
+ */
+ Field getFieldOrNull(Class> definedIn, String fieldName);
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionProviderWrapper.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionProviderWrapper.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/ReflectionProviderWrapper.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2006, 2007, 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 13. April 2006 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+
+
+/**
+ * A wrapper implementation for the ReflectionProvider.
+ *
+ * @author Jörg Schaible
+ * @since 1.2
+ */
+public class ReflectionProviderWrapper implements ReflectionProvider {
+
+ final protected ReflectionProvider wrapped;
+
+ public ReflectionProviderWrapper(final ReflectionProvider wrapper) {
+ wrapped = wrapper;
+ }
+
+ /**
+ * @deprecated As of 1.4.5, use {@link #getFieldOrNull(Class, String)} instead
+ */
+ @Deprecated
+ @Override
+ public boolean fieldDefinedInClass(final String fieldName, final Class> type) {
+ return wrapped.fieldDefinedInClass(fieldName, type);
+ }
+
+ @Override
+ public Field getField(final Class> definedIn, final String fieldName) {
+ return wrapped.getField(definedIn, fieldName);
+ }
+
+ @Override
+ public Field getFieldOrNull(final Class> definedIn, final String fieldName) {
+ return wrapped.getFieldOrNull(definedIn, fieldName);
+ }
+
+ @Override
+ public Class> getFieldType(final Object object, final String fieldName, final Class> definedIn) {
+ return wrapped.getFieldType(object, fieldName, definedIn);
+ }
+
+ @Override
+ public Object newInstance(final Class> type) {
+ return wrapped.newInstance(type);
+ }
+
+ @Override
+ public void visitSerializableFields(final Object object, final Visitor visitor) {
+ wrapped.visitSerializableFields(object, visitor);
+ }
+
+ @Override
+ public void writeField(final Object object, final String fieldName, final Object value, final Class> definedIn) {
+ wrapped.writeField(object, fieldName, value, definedIn);
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SelfStreamingInstanceChecker.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SelfStreamingInstanceChecker.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SelfStreamingInstanceChecker.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2006, 2007, 2013 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 03. April 2006 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import com.thoughtworks.xstream.converters.Converter;
+
+
+/**
+ * A special converter that prevents self-serialization. The serializing XStream instance adds a converter of this type
+ * to prevent self-serialization and will throw an exception instead.
+ *
+ * @author Jörg Schaible
+ * @since 1.2
+ * @deprecated As of 1.4.5 use {@link com.thoughtworks.xstream.core.util.SelfStreamingInstanceChecker}
+ */
+@Deprecated
+public class SelfStreamingInstanceChecker extends com.thoughtworks.xstream.core.util.SelfStreamingInstanceChecker {
+
+ public SelfStreamingInstanceChecker(final Converter defaultConverter, final Object xstream) {
+ super(defaultConverter, xstream);
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (.../SerializableConverter.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (.../SerializableConverter.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,119 +1,181 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 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 21. December 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
-import com.thoughtworks.xstream.converters.ConversionException;
-import com.thoughtworks.xstream.converters.Converter;
-import com.thoughtworks.xstream.converters.MarshallingContext;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
-import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
-import com.thoughtworks.xstream.mapper.Mapper;
-
import java.io.IOException;
import java.io.InvalidObjectException;
-import java.io.ObjectInputStream;
import java.io.ObjectInputValidation;
-import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.core.ClassLoaderReference;
+import com.thoughtworks.xstream.core.JVM;
+import com.thoughtworks.xstream.core.util.CustomObjectInputStream;
+import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
+import com.thoughtworks.xstream.core.util.HierarchicalStreams;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+
/**
* Emulates the mechanism used by standard Java Serialization for classes that implement java.io.Serializable AND
- * implement a custom readObject()/writeObject() method.
- *
- *
Supported features of serialization
+ * implement or inherit a custom readObject()/writeObject() method.
Supported features of serialization
*
- *
readObject(), writeObject()
- *
class inheritance
- *
readResolve(), writeReplace()
+ *
readObject(), writeObject()
+ *
class inheritance
+ *
readResolve(), writeReplace()
*
- *
*
Currently unsupported features
*
- *
putFields(), writeFields(), readFields()
- *
ObjectStreamField[] serialPersistentFields
- *
ObjectInputValidation
+ *
putFields(), writeFields(), readFields()
+ *
ObjectStreamField[] serialPersistentFields
+ *
ObjectInputValidation
*
- *
+ *
* @author Joe Walnes
+ * @author Jörg Schaible
*/
-public class SerializableConverter implements Converter {
+public class SerializableConverter extends AbstractReflectionConverter {
- private final SerializationMethodInvoker serializationMethodInvoker = new SerializationMethodInvoker();
- private final Mapper mapper;
- private final ReflectionProvider reflectionProvider;
-
private static final String ELEMENT_NULL = "null";
private static final String ELEMENT_DEFAULT = "default";
+ private static final String ELEMENT_UNSERIALIZABLE_PARENTS = "unserializable-parents";
private static final String ATTRIBUTE_CLASS = "class";
private static final String ATTRIBUTE_SERIALIZATION = "serialization";
private static final String ATTRIBUTE_VALUE_CUSTOM = "custom";
private static final String ELEMENT_FIELDS = "fields";
private static final String ELEMENT_FIELD = "field";
private static final String ATTRIBUTE_NAME = "name";
- public SerializableConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
- this.mapper = mapper;
- this.reflectionProvider = reflectionProvider;
+ private final ClassLoaderReference classLoaderReference;
+
+ /**
+ * Construct a SerializableConverter.
+ *
+ * @param mapper the mapper chain instance
+ * @param reflectionProvider the reflection provider
+ * @param classLoaderReference the reference to the {@link ClassLoader} of the XStream instance
+ * @since 1.4.5
+ */
+ public SerializableConverter(
+ final Mapper mapper, final ReflectionProvider reflectionProvider,
+ final ClassLoaderReference classLoaderReference) {
+ super(mapper, new UnserializableParentsReflectionProvider(reflectionProvider));
+ this.classLoaderReference = classLoaderReference;
}
- public boolean canConvert(Class type) {
- return Serializable.class.isAssignableFrom(type)
- && ( serializationMethodInvoker.supportsReadObject(type, true)
- || serializationMethodInvoker.supportsWriteObject(type, true) );
+ /**
+ * @deprecated As of 1.4.5 use {@link #SerializableConverter(Mapper, ReflectionProvider, ClassLoaderReference)}
+ */
+ @Deprecated
+ public SerializableConverter(
+ final Mapper mapper, final ReflectionProvider reflectionProvider, final ClassLoader classLoader) {
+ this(mapper, reflectionProvider, new ClassLoaderReference(classLoader));
}
- public void marshal(Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
- final Object replacedSource = serializationMethodInvoker.callWriteReplace(source);
+ /**
+ * @deprecated As of 1.4 use {@link #SerializableConverter(Mapper, ReflectionProvider, ClassLoaderReference)}
+ */
+ @Deprecated
+ public SerializableConverter(final Mapper mapper, final ReflectionProvider reflectionProvider) {
+ this(mapper, new UnserializableParentsReflectionProvider(reflectionProvider), new ClassLoaderReference(null));
+ }
- if (replacedSource.getClass() != source.getClass()) {
- writer.addAttribute(mapper.attributeForReadResolveField(), mapper.serializedClass(replacedSource.getClass()));
+ @Override
+ public boolean canConvert(final Class> type) {
+ return JVM.canCreateDerivedObjectOutputStream() && isSerializable(type);
+ }
+
+ private boolean isSerializable(final Class> type) {
+ if (type != null
+ && Serializable.class.isAssignableFrom(type)
+ && !type.isInterface()
+ && (serializationMethodInvoker.supportsReadObject(type, true) || serializationMethodInvoker
+ .supportsWriteObject(type, true))) {
+ for (final Class> clazz : hierarchyFor(type)) {
+ if (!Serializable.class.isAssignableFrom(clazz)) {
+ return canAccess(type);
+ }
+ }
+ return true;
}
+ return false;
+ }
- writer.addAttribute(ATTRIBUTE_SERIALIZATION, ATTRIBUTE_VALUE_CUSTOM);
+ @Override
+ public void doMarshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
+ final String attributeName = mapper.aliasForSystemAttribute(ATTRIBUTE_SERIALIZATION);
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, ATTRIBUTE_VALUE_CUSTOM);
+ }
// this is an array as it's a non final value that's accessed from an anonymous inner class.
- final Class[] currentType = new Class[1];
+ final Class>[] currentTypeRef = new Class>[1];
final boolean[] writtenClassWrapper = {false};
- CustomObjectOutputStream.StreamCallback callback = new CustomObjectOutputStream.StreamCallback() {
+ final CustomObjectOutputStream.StreamCallback callback = new CustomObjectOutputStream.StreamCallback() {
- public void writeToStream(Object object) {
+ @Override
+ public void writeToStream(final Object object) {
if (object == null) {
writer.startNode(ELEMENT_NULL);
writer.endNode();
} else {
- writer.startNode(mapper.serializedClass(object.getClass()));
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(object.getClass()),
+ object.getClass());
context.convertAnother(object);
writer.endNode();
}
}
- public void writeFieldsToStream(Map fields) {
- ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(currentType[0]);
+ @Override
+ public void writeFieldsToStream(final Map fields) {
+ final Class> currentType = currentTypeRef[0];
+ final ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(currentType);
writer.startNode(ELEMENT_DEFAULT);
- for (Iterator iterator = fields.keySet().iterator(); iterator.hasNext();) {
- String name = (String) iterator.next();
- ObjectStreamField field = objectStreamClass.getField(name);
- Object value = fields.get(name);
+ for (final String name : fields.keySet()) {
+ if (!mapper.shouldSerializeMember(currentType, name)) {
+ continue;
+ }
+ final ObjectStreamField field = objectStreamClass.getField(name);
+ final Object value = fields.get(name);
if (field == null) {
- throw new ObjectAccessException("Class " + value.getClass().getName()
- + " may not write a field named '" + name + "'");
+ throw new ObjectAccessException("Class "
+ + value.getClass().getName()
+ + " may not write a field named '"
+ + name
+ + "'");
}
if (value != null) {
- writer.startNode(mapper.serializedMember(currentType[0], name));
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedMember(source
+ .getClass(), name), value.getClass());
if (field.getType() != value.getClass() && !field.getType().isPrimitive()) {
- writer.addAttribute(ATTRIBUTE_CLASS, mapper.serializedClass(value.getClass()));
+ final String attributeName = mapper.aliasForSystemAttribute(ATTRIBUTE_CLASS);
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, mapper.serializedClass(value.getClass()));
+ }
}
context.convertAnother(value);
writer.endNode();
@@ -122,35 +184,40 @@
writer.endNode();
}
+ @Override
public void defaultWriteObject() {
boolean writtenDefaultFields = false;
- ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(currentType[0]);
-
+ final Class> currentType = currentTypeRef[0];
+ final ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(currentType);
if (objectStreamClass == null) {
return;
}
- ObjectStreamField[] fields = objectStreamClass.getFields();
- for (int i = 0; i < fields.length; i++) {
- ObjectStreamField field = fields[i];
- Object value = readField(field, currentType[0], replacedSource);
+ for (final ObjectStreamField field : objectStreamClass.getFields()) {
+ final Object value = readField(field, currentType, source);
if (value != null) {
if (!writtenClassWrapper[0]) {
- writer.startNode(mapper.serializedClass(currentType[0]));
+ writer.startNode(mapper.serializedClass(currentType));
writtenClassWrapper[0] = true;
}
if (!writtenDefaultFields) {
writer.startNode(ELEMENT_DEFAULT);
writtenDefaultFields = true;
}
+ if (!mapper.shouldSerializeMember(currentType, field.getName())) {
+ continue;
+ }
- writer.startNode(mapper.serializedMember(currentType[0], field.getName()));
-
- Class actualType = value.getClass();
- Class defaultType = mapper.defaultImplementationOf(field.getType());
+ final Class> actualType = value.getClass();
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedMember(source
+ .getClass(), field.getName()), actualType);
+ final Class> defaultType = mapper.defaultImplementationOf(field.getType());
if (!actualType.equals(defaultType)) {
- writer.addAttribute(ATTRIBUTE_CLASS, mapper.serializedClass(actualType));
+ final String attributeName = mapper.aliasForSystemAttribute(ATTRIBUTE_CLASS);
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, mapper.serializedClass(actualType));
+ }
}
context.convertAnother(value);
@@ -166,147 +233,188 @@
}
}
+ @Override
public void flush() {
writer.flush();
}
+ @Override
public void close() {
- throw new UnsupportedOperationException("Objects are not allowed to call ObjectOutputStream.close() from writeObject()");
+ throw new UnsupportedOperationException(
+ "Objects are not allowed to call ObjectOutputStream.close() from writeObject()");
}
};
try {
- Iterator classHieararchy = hierarchyFor(replacedSource.getClass());
- while (classHieararchy.hasNext()) {
- currentType[0] = (Class) classHieararchy.next();
- if (serializationMethodInvoker.supportsWriteObject(currentType[0], false)) {
- writtenClassWrapper[0] = true;
- writer.startNode(mapper.serializedClass(currentType[0]));
- ObjectOutputStream objectOutputStream = CustomObjectOutputStream.getInstance(context, callback);
- serializationMethodInvoker.callWriteObject(currentType[0], replacedSource, objectOutputStream);
- writer.endNode();
- } else if (serializationMethodInvoker.supportsReadObject(currentType[0], false)) {
- // Special case for objects that have readObject(), but not writeObject().
- // The class wrapper is always written, whether or not this class in the hierarchy has
- // serializable fields. This guarantees that readObject() will be called upon deserialization.
- writtenClassWrapper[0] = true;
- writer.startNode(mapper.serializedClass(currentType[0]));
- callback.defaultWriteObject();
- writer.endNode();
+ boolean mustHandleUnserializableParent = false;
+ for (final Class> currentType : hierarchyFor(source.getClass())) {
+ currentTypeRef[0] = currentType;
+ if (!Serializable.class.isAssignableFrom(currentType)) {
+ mustHandleUnserializableParent = true;
+ continue;
} else {
- writtenClassWrapper[0] = false;
- callback.defaultWriteObject();
- if (writtenClassWrapper[0]) {
+ if (mustHandleUnserializableParent) {
+ marshalUnserializableParent(writer, context, source);
+ mustHandleUnserializableParent = false;
+ }
+ if (serializationMethodInvoker.supportsWriteObject(currentType, false)) {
+ writtenClassWrapper[0] = true;
+ writer.startNode(mapper.serializedClass(currentType));
+ if (currentType != mapper.defaultImplementationOf(currentType)) {
+ final String classAttributeName = mapper.aliasForSystemAttribute(ATTRIBUTE_CLASS);
+ if (classAttributeName != null) {
+ writer.addAttribute(classAttributeName, currentType.getName());
+ }
+ }
+ @SuppressWarnings("resource")
+ final CustomObjectOutputStream objectOutputStream = CustomObjectOutputStream.getInstance(
+ context, callback);
+ serializationMethodInvoker.callWriteObject(currentType, source, objectOutputStream);
+ objectOutputStream.popCallback();
writer.endNode();
+ } else if (serializationMethodInvoker.supportsReadObject(currentType, false)) {
+ // Special case for objects that have readObject(), but not writeObject().
+ // The class wrapper is always written, whether or not this class in the hierarchy has
+ // serializable fields. This guarantees that readObject() will be called upon deserialization.
+ writtenClassWrapper[0] = true;
+ writer.startNode(mapper.serializedClass(currentType));
+ if (currentType != mapper.defaultImplementationOf(currentType)) {
+ final String classAttributeName = mapper.aliasForSystemAttribute(ATTRIBUTE_CLASS);
+ if (classAttributeName != null) {
+ writer.addAttribute(classAttributeName, currentType.getName());
+ }
+ }
+ callback.defaultWriteObject();
+ writer.endNode();
+ } else {
+ writtenClassWrapper[0] = false;
+ callback.defaultWriteObject();
+ if (writtenClassWrapper[0]) {
+ writer.endNode();
+ }
}
}
}
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new ObjectAccessException("Could not call defaultWriteObject()", e);
}
}
- private Object readField(ObjectStreamField field, Class type, Object instance) {
+ protected void marshalUnserializableParent(final HierarchicalStreamWriter writer, final MarshallingContext context,
+ final Object replacedSource) {
+ writer.startNode(ELEMENT_UNSERIALIZABLE_PARENTS);
+ super.doMarshal(replacedSource, writer, context);
+ writer.endNode();
+ }
+
+ private Object readField(final ObjectStreamField field, final Class> type, final Object instance) {
try {
- Field javaField = type.getDeclaredField(field.getName());
- javaField.setAccessible(true);
+ final Field javaField = type.getDeclaredField(field.getName());
+ if (!javaField.isAccessible()) {
+ javaField.setAccessible(true);
+ }
return javaField.get(instance);
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (IllegalAccessException e) {
+ } catch (final IllegalAccessException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (NoSuchFieldException e) {
+ } catch (final NoSuchFieldException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (SecurityException e) {
+ } catch (final SecurityException e) {
throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
}
}
- private Iterator hierarchyFor(Class type) {
- List result = new ArrayList();
- while(type != null) {
+ protected List> hierarchyFor(Class> type) {
+ final List> result = new ArrayList>();
+ while (type != Object.class && type != null) {
result.add(type);
type = type.getSuperclass();
}
// In Java Object Serialization, the classes are deserialized starting from parent class and moving down.
Collections.reverse(result);
- return result.iterator();
+ return result;
}
- public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
- String resolvesAttribute = reader.getAttribute(mapper.attributeForReadResolveField());
- Class requiredType;
- if (resolvesAttribute != null) {
- requiredType = mapper.realClass(resolvesAttribute);
- } else {
- requiredType = context.getRequiredType();
- }
- final Object result = reflectionProvider.newInstance(requiredType);
-
+ @Override
+ public Object doUnmarshal(final Object result, final HierarchicalStreamReader reader,
+ final UnmarshallingContext context) {
// this is an array as it's a non final value that's accessed from an anonymous inner class.
- final Class[] currentType = new Class[1];
+ final Class>[] currentType = new Class>[1];
- if (!ATTRIBUTE_VALUE_CUSTOM.equals(reader.getAttribute(ATTRIBUTE_SERIALIZATION))) {
+ final String attributeName = mapper.aliasForSystemAttribute(ATTRIBUTE_SERIALIZATION);
+ if (attributeName != null && !ATTRIBUTE_VALUE_CUSTOM.equals(reader.getAttribute(attributeName))) {
throw new ConversionException("Cannot deserialize object with new readObject()/writeObject() methods");
}
- CustomObjectInputStream.StreamCallback callback = new CustomObjectInputStream.StreamCallback() {
+ final CustomObjectInputStream.StreamCallback callback = new CustomObjectInputStream.StreamCallback() {
+ @Override
public Object readFromStream() {
reader.moveDown();
- Class type = mapper.realClass(reader.getNodeName());
- Object value = context.convertAnother(result, type);
+ final Class> type = HierarchicalStreams.readClassType(reader, mapper);
+ final Object value = context.convertAnother(result, type);
reader.moveUp();
return value;
}
- public Map readFieldsFromStream() {
- Map result = new HashMap();
+ @Override
+ public Map readFieldsFromStream() {
+ final Map fields = new HashMap();
reader.moveDown();
if (reader.getNodeName().equals(ELEMENT_FIELDS)) {
- // Maintain compatability with XStream 1.1.0
+ // Maintain compatibility with XStream 1.1.0
while (reader.hasMoreChildren()) {
reader.moveDown();
if (!reader.getNodeName().equals(ELEMENT_FIELD)) {
- throw new ConversionException("Expected <" + ELEMENT_FIELD + "/> element inside <" + ELEMENT_FIELD + "/>");
+ throw new ConversionException("Expected <"
+ + ELEMENT_FIELD
+ + "/> element inside <"
+ + ELEMENT_FIELD
+ + "/>");
}
- String name = reader.getAttribute(ATTRIBUTE_NAME);
- Class type = mapper.realClass(reader.getAttribute(ATTRIBUTE_CLASS));
- Object value = context.convertAnother(result, type);
- result.put(name, value);
+ final String name = reader.getAttribute(ATTRIBUTE_NAME);
+ final Class> type = mapper.realClass(reader.getAttribute(ATTRIBUTE_CLASS));
+ final Object value = context.convertAnother(result, type);
+ fields.put(name, value);
reader.moveUp();
}
} else if (reader.getNodeName().equals(ELEMENT_DEFAULT)) {
// New format introduced in XStream 1.1.1
- ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(currentType[0]);
+ final ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(currentType[0]);
while (reader.hasMoreChildren()) {
reader.moveDown();
- String name = reader.getNodeName();
- String typeName = reader.getAttribute(ATTRIBUTE_CLASS);
- Class type;
- if (typeName != null) {
- type = mapper.realClass(typeName);
- } else {
- ObjectStreamField field = objectStreamClass.getField(name);
- if (field == null) {
- throw new ObjectAccessException("Class " + currentType[0]
- + " does not contain a field named '" + name + "'");
+ final String name = mapper.realMember(currentType[0], reader.getNodeName());
+ if (mapper.shouldSerializeMember(currentType[0], name)) {
+ final String classAttribute = HierarchicalStreams.readClassAttribute(reader, mapper);
+ Class> type;
+ if (classAttribute != null) {
+ type = mapper.realClass(classAttribute);
+ } else {
+ final ObjectStreamField field = objectStreamClass.getField(name);
+ if (field == null) {
+ throw new MissingFieldException(currentType[0].getName(), name);
+ }
+ type = field.getType();
}
- type = field.getType();
+ final Object value = context.convertAnother(result, type);
+ fields.put(name, value);
}
- Object value = context.convertAnother(result, type);
- result.put(name, value);
reader.moveUp();
}
} else {
- throw new ConversionException("Expected <" + ELEMENT_FIELDS + "/> or <" +
- ELEMENT_DEFAULT + "/> element when calling ObjectInputStream.readFields()");
+ throw new ConversionException("Expected <"
+ + ELEMENT_FIELDS
+ + "/> or <"
+ + ELEMENT_DEFAULT
+ + "/> element when calling ObjectInputStream.readFields()");
}
reader.moveUp();
- return result;
+ return fields;
}
+ @Override
public void defaultReadObject() {
if (!reader.hasMoreChildren()) {
return;
@@ -318,57 +426,110 @@
while (reader.hasMoreChildren()) {
reader.moveDown();
- Class type;
- String fieldName = mapper.realMember(currentType[0], reader.getNodeName());
- String classAttribute = reader.getAttribute(ATTRIBUTE_CLASS);
- if (classAttribute != null) {
- type = mapper.realClass(classAttribute);
- } else {
- type = mapper.defaultImplementationOf(reflectionProvider.getFieldType(result, fieldName, currentType[0]));
+ final String fieldName = mapper.realMember(currentType[0], reader.getNodeName());
+ if (mapper.shouldSerializeMember(currentType[0], fieldName)) {
+ final String classAttribute = HierarchicalStreams.readClassAttribute(reader, mapper);
+ final Class> type;
+ if (classAttribute != null) {
+ type = mapper.realClass(classAttribute);
+ } else {
+ type = mapper.defaultImplementationOf(reflectionProvider.getFieldType(result, fieldName,
+ currentType[0]));
+ }
+
+ final Object value = context.convertAnother(result, type);
+ reflectionProvider.writeField(result, fieldName, value, currentType[0]);
}
- Object value = context.convertAnother(result, type);
- reflectionProvider.writeField(result, fieldName, value, currentType[0]);
-
reader.moveUp();
}
reader.moveUp();
}
- public void registerValidation(final ObjectInputValidation validation, int priority) {
+ @Override
+ public void registerValidation(final ObjectInputValidation validation, final int priority) {
context.addCompletionCallback(new Runnable() {
+ @Override
public void run() {
try {
validation.validateObject();
- } catch (InvalidObjectException e) {
+ } catch (final InvalidObjectException e) {
throw new ObjectAccessException("Cannot validate object : " + e.getMessage(), e);
}
}
}, priority);
}
+ @Override
public void close() {
- throw new UnsupportedOperationException("Objects are not allowed to call ObjectInputStream.close() from readObject()");
+ throw new UnsupportedOperationException(
+ "Objects are not allowed to call ObjectInputStream.close() from readObject()");
}
};
while (reader.hasMoreChildren()) {
reader.moveDown();
- currentType[0] = mapper.defaultImplementationOf(mapper.realClass(reader.getNodeName()));
- if (serializationMethodInvoker.supportsReadObject(currentType[0], false)) {
- ObjectInputStream objectInputStream = CustomObjectInputStream.getInstance(context, callback);
- serializationMethodInvoker.callReadObject(currentType[0], result, objectInputStream);
+ final String nodeName = reader.getNodeName();
+ if (nodeName.equals(ELEMENT_UNSERIALIZABLE_PARENTS)) {
+ super.doUnmarshal(result, reader, context);
} else {
- try {
- callback.defaultReadObject();
- } catch (IOException e) {
- throw new ObjectAccessException("Could not call defaultWriteObject()", e);
+ final String classAttribute = HierarchicalStreams.readClassAttribute(reader, mapper);
+ if (classAttribute == null) {
+ currentType[0] = mapper.defaultImplementationOf(mapper.realClass(nodeName));
+ } else {
+ currentType[0] = mapper.realClass(classAttribute);
}
+ if (serializationMethodInvoker.supportsReadObject(currentType[0], false)) {
+ @SuppressWarnings("resource")
+ final CustomObjectInputStream objectInputStream = CustomObjectInputStream.getInstance(context,
+ callback, classLoaderReference);
+ serializationMethodInvoker.callReadObject(currentType[0], result, objectInputStream);
+ objectInputStream.popCallback();
+ } else {
+ try {
+ callback.defaultReadObject();
+ } catch (final IOException e) {
+ throw new ObjectAccessException("Could not call defaultWriteObject()", e);
+ }
+ }
}
reader.moveUp();
}
- return serializationMethodInvoker.callReadResolve(result);
+ return result;
}
+ protected void doMarshalConditionally(final Object source, final HierarchicalStreamWriter writer,
+ final MarshallingContext context) {
+ if (isSerializable(source.getClass())) {
+ doMarshal(source, writer, context);
+ } else {
+ super.doMarshal(source, writer, context);
+ }
+ }
+
+ protected Object doUnmarshalConditionally(final Object result, final HierarchicalStreamReader reader,
+ final UnmarshallingContext context) {
+ return isSerializable(result.getClass()) ? doUnmarshal(result, reader, context) : super.doUnmarshal(result,
+ reader, context);
+ }
+
+ private static class UnserializableParentsReflectionProvider extends ReflectionProviderWrapper {
+
+ public UnserializableParentsReflectionProvider(final ReflectionProvider reflectionProvider) {
+ super(reflectionProvider);
+ }
+
+ @Override
+ public void visitSerializableFields(final Object object, final Visitor visitor) {
+ wrapped.visitSerializableFields(object, new Visitor() {
+ @Override
+ public void visit(final String name, final Class> type, final Class> definedIn, final Object value) {
+ if (!Serializable.class.isAssignableFrom(definedIn)) {
+ visitor.visit(name, type, definedIn, value);
+ }
+ }
+ });
+ }
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java (.../SerializationMethodInvoker.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SerializationMethodInvoker.java (.../SerializationMethodInvoker.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,128 +1,159 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 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 23. August 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
-import com.thoughtworks.xstream.converters.ConversionException;
-
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.Map;
-import java.util.HashMap;
+import java.util.Arrays;
import java.util.Collections;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.core.Caching;
+import com.thoughtworks.xstream.core.util.FastField;
+
+
/**
* Convenience wrapper to invoke special serialization methods on objects (and perform reflection caching).
- *
+ *
* @author Joe Walnes
+ * @author Jörg Schaible
*/
-public class SerializationMethodInvoker {
+public class SerializationMethodInvoker implements Caching {
- private Map cache = Collections.synchronizedMap(new HashMap());
- private static final Object NO_METHOD = new Object();
- private static final Object[] EMPTY_ARGS = new Object[0];
+ private static final Method NO_METHOD = new Object() {
+ @SuppressWarnings("unused")
+ private void noMethod() {
+ }
+ }.getClass().getDeclaredMethods()[0];
+ private static final FastField[] OBJECT_TYPE_FIELDS = new FastField[]{
+ new FastField(Object.class, "readResolve"), new FastField(Object.class, "writeReplace"),
+ new FastField(Object.class, "readObject"), new FastField(Object.class, "writeObject")};
+ private final Map cache = Collections.synchronizedMap(new HashMap());
+ {
+ for (final FastField element : OBJECT_TYPE_FIELDS) {
+ cache.put(element, NO_METHOD);
+ }
+ }
/**
* Resolves an object as native serialization does by calling readResolve(), if available.
*/
- public Object callReadResolve(Object result) {
+ public Object callReadResolve(final Object result) {
if (result == null) {
return null;
} else {
- Method readResolveMethod = getMethod(result.getClass(), "readResolve", null, true);
+ final Method readResolveMethod = getMethod(result.getClass(), "readResolve", true);
if (readResolveMethod != null) {
try {
- return readResolveMethod.invoke(result, EMPTY_ARGS);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not call " + result.getClass().getName() + ".readResolve()", e);
- } catch (InvocationTargetException e) {
- throw new ObjectAccessException("Could not call " + result.getClass().getName() + ".readResolve()", e);
+ return readResolveMethod.invoke(result);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Could not call " + result.getClass().getName() + ".readResolve()",
+ e);
+ } catch (final InvocationTargetException e) {
+ throw new ObjectAccessException("Could not call " + result.getClass().getName() + ".readResolve()",
+ e.getTargetException());
}
} else {
return result;
}
}
}
- public Object callWriteReplace(Object object) {
+ public Object callWriteReplace(final Object object) {
if (object == null) {
return null;
} else {
- Method writeReplaceMethod = getMethod(object.getClass(), "writeReplace", null, true);
+ final Method writeReplaceMethod = getMethod(object.getClass(), "writeReplace", true);
if (writeReplaceMethod != null) {
try {
- Object[] EMPTY_ARGS = new Object[0];
- return writeReplaceMethod.invoke(object, EMPTY_ARGS);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not call " + object.getClass().getName() + ".writeReplace()", e);
- } catch (InvocationTargetException e) {
- throw new ObjectAccessException("Could not call " + object.getClass().getName() + ".writeReplace()", e);
+ return writeReplaceMethod.invoke(object);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException(
+ "Could not call " + object.getClass().getName() + ".writeReplace()", e);
+ } catch (final InvocationTargetException e) {
+ throw new ObjectAccessException(
+ "Could not call " + object.getClass().getName() + ".writeReplace()", e.getTargetException());
}
} else {
return object;
}
}
}
- public boolean supportsReadObject(Class type, boolean includeBaseClasses) {
- return getMethod(type, "readObject", new Class[]{ObjectInputStream.class}, includeBaseClasses) != null;
+ public boolean supportsReadObject(final Class> type, final boolean includeBaseClasses) {
+ return getMethod(type, "readObject", includeBaseClasses, ObjectInputStream.class) != null;
}
- public void callReadObject(Class type, Object object, ObjectInputStream stream) {
+ public void callReadObject(final Class> type, final Object object, final ObjectInputStream stream) {
try {
- Method readObjectMethod = getMethod(type, "readObject", new Class[]{ObjectInputStream.class}, false);
- readObjectMethod.invoke(object, new Object[]{stream});
- } catch (IllegalAccessException e) {
+ final Method readObjectMethod = getMethod(type, "readObject", false, ObjectInputStream.class);
+ readObjectMethod.invoke(object, stream);
+ } catch (final IllegalAccessException e) {
throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e);
- } catch (InvocationTargetException e) {
- throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e);
+ } catch (final InvocationTargetException e) {
+ throw new ConversionException("Could not call " + object.getClass().getName() + ".readObject()", e
+ .getTargetException());
}
}
- public boolean supportsWriteObject(Class type, boolean includeBaseClasses) {
- return getMethod(type, "writeObject", new Class[]{ObjectOutputStream.class}, includeBaseClasses) != null;
+ public boolean supportsWriteObject(final Class> type, final boolean includeBaseClasses) {
+ return getMethod(type, "writeObject", includeBaseClasses, ObjectOutputStream.class) != null;
}
- public void callWriteObject(Class type, Object instance, ObjectOutputStream stream) {
+ public void callWriteObject(final Class> type, final Object instance, final ObjectOutputStream stream) {
try {
- Method readObjectMethod = getMethod(type, "writeObject", new Class[]{ObjectOutputStream.class}, false);
- readObjectMethod.invoke(instance, new Object[]{stream});
- } catch (IllegalAccessException e) {
+ final Method readObjectMethod = getMethod(type, "writeObject", false, ObjectOutputStream.class);
+ readObjectMethod.invoke(instance, stream);
+ } catch (final IllegalAccessException e) {
throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e);
- } catch (InvocationTargetException e) {
- throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e);
+ } catch (final InvocationTargetException e) {
+ throw new ConversionException("Could not call " + instance.getClass().getName() + ".writeObject()", e
+ .getTargetException());
}
}
- private Method getMethod(Class type, String name, Class[] parameterTypes, boolean includeBaseclasses) {
- Object key = type.getName() + "." + name + "." + includeBaseclasses;
- if (cache.containsKey(key)) {
- Object result = cache.get(key);
- return (Method) (result == NO_METHOD ? null : result);
+ private Method getMethod(final Class> type, final String name, final boolean includeBaseclasses,
+ final Class>... parameterTypes) {
+ final Method method = getMethod(type, name, parameterTypes);
+ return method == NO_METHOD || !includeBaseclasses && !method.getDeclaringClass().equals(type) ? null : method;
+ }
+
+ private Method getMethod(final Class> type, final String name, final Class>... parameterTypes) {
+ if (type == null) {
+ return null;
}
- if (includeBaseclasses) {
- while (type != null) {
- try {
- Method result = type.getDeclaredMethod(name, parameterTypes);
+ final FastField method = new FastField(type, name);
+ Method result = cache.get(method);
+
+ if (result == null) {
+ try {
+ result = type.getDeclaredMethod(name, parameterTypes);
+ if (!result.isAccessible()) {
result.setAccessible(true);
- cache.put(key, result);
- return result;
- } catch (NoSuchMethodException e) {
- type = type.getSuperclass();
}
+ } catch (final NoSuchMethodException e) {
+ result = getMethod(type.getSuperclass(), name, parameterTypes);
}
- cache.put(key, NO_METHOD);
- return null;
- } else {
- try {
- Method result = type.getDeclaredMethod(name, parameterTypes);
- result.setAccessible(true);
- cache.put(key, result);
- return result;
- } catch (NoSuchMethodException e) {
- cache.put(key, NO_METHOD);
- return null;
- }
+ cache.put(method, result);
}
+ return result;
}
+ @Override
+ public void flushCache() {
+ cache.keySet().retainAll(Arrays.asList(OBJECT_TYPE_FIELDS));
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007, 2009, 2011, 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 10. April 2007 by Guilherme Silveira
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.thoughtworks.xstream.core.Caching;
+import com.thoughtworks.xstream.io.StreamException;
+
+
+/**
+ * The default implementation for sorting fields. Invoke registerFieldOrder in order to set the field order for an
+ * specific type.
+ *
+ * @author Guilherme Silveira
+ * @since 1.2.2
+ */
+public class SortableFieldKeySorter implements FieldKeySorter, Caching {
+
+ private final Map, Comparator> map = new HashMap, Comparator>();
+
+ @Override
+ public Map sort(final Class> type, final Map keyedByFieldKey) {
+ if (map.containsKey(type)) {
+ final Map result = new LinkedHashMap();
+ final FieldKey[] fieldKeys = keyedByFieldKey.keySet().toArray(new FieldKey[keyedByFieldKey.size()]);
+ Arrays.sort(fieldKeys, map.get(type));
+ for (final FieldKey fieldKey : fieldKeys) {
+ result.put(fieldKey, keyedByFieldKey.get(fieldKey));
+ }
+ return result;
+ } else {
+ return keyedByFieldKey;
+ }
+ }
+
+ /**
+ * Registers the field order to use for a specific type. This will not affect any of the type's super or sub
+ * classes. If you skip a field which will be serialized, XStream will thrown an StreamException during the
+ * serialization process.
+ *
+ * @param type the type
+ * @param fields the field order
+ */
+ public void registerFieldOrder(final Class> type, final String[] fields) {
+ map.put(type, new FieldComparator(fields));
+ }
+
+ private class FieldComparator implements Comparator {
+
+ private final String[] fieldOrder;
+
+ public FieldComparator(final String[] fields) {
+ fieldOrder = fields;
+ }
+
+ private int compare(final String first, final String second) {
+ int firstPosition = -1, secondPosition = -1;
+ for (int i = 0; i < fieldOrder.length; i++) {
+ if (fieldOrder[i].equals(first)) {
+ firstPosition = i;
+ }
+ if (fieldOrder[i].equals(second)) {
+ secondPosition = i;
+ }
+ }
+ if (firstPosition == -1 || secondPosition == -1) {
+ // field not defined!!!
+ throw new StreamException("You have not given XStream a list of all fields to be serialized.");
+ }
+ return firstPosition - secondPosition;
+ }
+
+ @Override
+ public int compare(final FieldKey first, final FieldKey second) {
+ return compare(first.getFieldName(), second.getFieldName());
+ }
+
+ }
+
+ @Override
+ public void flushCache() {
+ map.clear();
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java (.../Sun14ReflectionProvider.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java (.../Sun14ReflectionProvider.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,115 +1,45 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2011, 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 07. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.converters.reflection;
-import sun.misc.Unsafe;
-import sun.reflect.ReflectionFactory;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Collections;
-
/**
- * Instantiates a new object on the Sun JVM by bypassing the constructor (meaning code in the constructor
- * will never be executed and parameters do not have to be known). This is the same method used by the internals of
- * standard Java serialization, but relies on internal Sun code that may not be present on all JVMs.
- *
+ * Instantiates a new object on the Sun JVM by bypassing the constructor (meaning code in the constructor will never be
+ * executed and parameters do not have to be known). This is the same method used by the internals of standard Java
+ * serialization, but relies on internal Sun code that may not be present on all JVMs.
+ *
* @author Joe Walnes
* @author Brian Slesinsky
+ * @deprecated As of upcoming use {@link SunUnsafeReflectionProvider}
*/
-public class Sun14ReflectionProvider extends PureJavaReflectionProvider {
-
- private final ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
- private Unsafe cachedUnsafe;
- private final Map constructorCache = Collections.synchronizedMap(new HashMap());
-
- private Unsafe getUnsafe() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
- if (cachedUnsafe != null) {
- return cachedUnsafe;
- }
- Class objectStreamClass = Class.forName("java.io.ObjectStreamClass$FieldReflector");
- Field unsafeField = objectStreamClass.getDeclaredField("unsafe");
- unsafeField.setAccessible(true);
- cachedUnsafe = (Unsafe) unsafeField.get(null);
- return cachedUnsafe;
+@Deprecated
+public class Sun14ReflectionProvider extends SunUnsafeReflectionProvider {
+ /**
+ * @deprecated As of upcoming use {@link SunUnsafeReflectionProvider#SunUnsafeReflectionProvider()}
+ */
+ @Deprecated
+ public Sun14ReflectionProvider() {
+ super();
}
- public Object newInstance(Class type) {
- try {
- Constructor customConstructor = getMungedConstructor(type);
- return customConstructor.newInstance(new Object[0]);
- } catch (NoSuchMethodException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (SecurityException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (InstantiationException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (InvocationTargetException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- }
+ /**
+ * @deprecated As of upcoming use {@link SunUnsafeReflectionProvider#SunUnsafeReflectionProvider(FieldDictionary)}
+ */
+ @Deprecated
+ public Sun14ReflectionProvider(final FieldDictionary dic) {
+ super(dic);
}
- private Constructor getMungedConstructor(Class type) throws NoSuchMethodException {
- if (!constructorCache.containsKey(type)) {
- Constructor javaLangObjectConstructor = Object.class.getDeclaredConstructor(new Class[0]);
- Constructor customConstructor = reflectionFactory.newConstructorForSerialization(type, javaLangObjectConstructor);
- constructorCache.put(type, customConstructor);
- }
- return (Constructor) constructorCache.get(type);
+ private Object readResolve() {
+ init();
+ return this;
}
-
- public void writeField(Object object, String fieldName, Object value, Class definedIn) {
- write(fieldDictionary.field(object.getClass(), fieldName, definedIn), object, value);
- }
-
- private void write(Field field, Object object, Object value) {
- try {
- Unsafe unsafe = getUnsafe();
- long offset = unsafe.objectFieldOffset(field);
- Class type = field.getType();
- if (type.isPrimitive()) {
- if (type.equals(Integer.TYPE)) {
- unsafe.putInt(object, offset, ((Integer) value).intValue());
- } else if (type.equals(Long.TYPE)) {
- unsafe.putLong(object, offset, ((Long) value).longValue());
- } else if (type.equals(Short.TYPE)) {
- unsafe.putShort(object, offset, ((Short) value).shortValue());
- } else if (type.equals(Character.TYPE)) {
- unsafe.putChar(object, offset, ((Character) value).charValue());
- } else if (type.equals(Byte.TYPE)) {
- unsafe.putByte(object, offset, ((Byte) value).byteValue());
- } else if (type.equals(Float.TYPE)) {
- unsafe.putFloat(object, offset, ((Float) value).floatValue());
- } else if (type.equals(Double.TYPE)) {
- unsafe.putDouble(object, offset, ((Double) value).doubleValue());
- } else if (type.equals(Boolean.TYPE)) {
- unsafe.putBoolean(object, offset, ((Boolean) value).booleanValue());
- } else {
- throw new ObjectAccessException("Could not set field " +
- object.getClass() + "." + field.getName() +
- ": Unknown type " + type);
- }
- } else {
- unsafe.putObject(object, offset, value);
- }
-
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
- } catch (NoSuchFieldException e) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
- } catch (ClassNotFoundException e) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
- }
- }
-
- protected void validateFieldAccess(Field field) {
- // (overriden) don't mind final fields.
- }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014 XStream Committers.
+ * All rights reserved.
+ *
+ * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+
+import sun.misc.Unsafe;
+
+
+/**
+ * Instantiates a new object bypassing the constructor using undocumented internal JDK features.
+ *
+ * The code in the constructor will never be executed and parameters do not have to be known. This is the same method
+ * used by the internals of standard Java serialization, but relies on internal code (sun.misc.Unsafe) that may not be
+ * present on all JVMs.
+ *
+ *
+ * The implementation will use standard Java functionality to write any fields. This requires Java 5 as minimum runtime
+ * and is used as fallback on platforms that do not provide the complete implementation level for the internals (like
+ * Dalvik).
+ *
+ *
+ * @author Jörg Schaible
+ * @author Joe Walnes
+ * @author Brian Slesinsky
+ * @since 1.4.7
+ */
+public class SunLimitedUnsafeReflectionProvider extends PureJavaReflectionProvider {
+
+ protected static final Unsafe unsafe;
+ protected static final Exception exception;
+ static {
+ Unsafe u = null;
+ Exception ex = null;
+ try {
+ final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ u = (Unsafe)unsafeField.get(null);
+ } catch (final SecurityException e) {
+ ex = e;
+ } catch (final NoSuchFieldException e) {
+ ex = e;
+ } catch (final IllegalArgumentException e) {
+ ex = e;
+ } catch (final IllegalAccessException e) {
+ ex = e;
+ }
+ exception = ex;
+ unsafe = u;
+ }
+
+ /**
+ * @since 1.4.7
+ */
+ public SunLimitedUnsafeReflectionProvider() {
+ super();
+ }
+
+ /**
+ * @since 1.4.7
+ */
+ public SunLimitedUnsafeReflectionProvider(final FieldDictionary fieldDictionary) {
+ super(fieldDictionary);
+ }
+
+ @Override
+ public Object newInstance(final Class> type) {
+ if (exception != null) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), exception);
+ }
+ try {
+ return unsafe.allocateInstance(type);
+ } catch (final SecurityException e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ } catch (final InstantiationException e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ } catch (final IllegalArgumentException e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ }
+ }
+
+ @Override
+ protected void validateFieldAccess(final Field field) {
+ // (overriden) don't mind final fields.
+ }
+
+ private Object readResolve() {
+ init();
+ return this;
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2011, 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 08. January 2014 by Joerg Schaible, renamed from Sun14ReflectionProvider
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Instantiates a new object bypassing the constructor using undocumented internal JDK features.
+ *
+ * The code in the constructor will never be executed and parameters do not have to be known. This is the same method
+ * used by the internals of standard Java serialization, but relies on internal code (sun.misc.Unsafe) that may not be
+ * present on all JVMs.
+ *
+ *
+ * The implementation will use the same internals to write into fields. This is a lot faster and was additionally the
+ * only possibility to set final fields prior to Java 5.
+ *
+ *
+ * @author Joe Walnes
+ * @author Brian Slesinsky
+ * @author Jörg Schaible
+ * @since 1.4.7
+ */
+public class SunUnsafeReflectionProvider extends SunLimitedUnsafeReflectionProvider {
+
+ // references to the Field key are kept in the FieldDictionary
+ private transient Map fieldOffsetCache;
+
+ /**
+ * @since 1.4.7
+ */
+ public SunUnsafeReflectionProvider() {
+ super();
+ }
+
+ /**
+ * @since 1.4.7
+ */
+ public SunUnsafeReflectionProvider(final FieldDictionary dic) {
+ super(dic);
+ }
+
+ @Override
+ public void writeField(final Object object, final String fieldName, final Object value, final Class> definedIn) {
+ write(fieldDictionary.field(object.getClass(), fieldName, definedIn), object, value);
+ }
+
+ private void write(final Field field, final Object object, final Object value) {
+ if (exception != null) {
+ throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(),
+ exception);
+ }
+ try {
+ final long offset = getFieldOffset(field);
+ final Class> type = field.getType();
+ if (type.isPrimitive()) {
+ if (type.equals(Integer.TYPE)) {
+ unsafe.putInt(object, offset, ((Integer)value).intValue());
+ } else if (type.equals(Long.TYPE)) {
+ unsafe.putLong(object, offset, ((Long)value).longValue());
+ } else if (type.equals(Short.TYPE)) {
+ unsafe.putShort(object, offset, ((Short)value).shortValue());
+ } else if (type.equals(Character.TYPE)) {
+ unsafe.putChar(object, offset, ((Character)value).charValue());
+ } else if (type.equals(Byte.TYPE)) {
+ unsafe.putByte(object, offset, ((Byte)value).byteValue());
+ } else if (type.equals(Float.TYPE)) {
+ unsafe.putFloat(object, offset, ((Float)value).floatValue());
+ } else if (type.equals(Double.TYPE)) {
+ unsafe.putDouble(object, offset, ((Double)value).doubleValue());
+ } else if (type.equals(Boolean.TYPE)) {
+ unsafe.putBoolean(object, offset, ((Boolean)value).booleanValue());
+ } else {
+ throw new ObjectAccessException("Could not set field "
+ + object.getClass()
+ + "."
+ + field.getName()
+ + ": Unknown type "
+ + type);
+ }
+ } else {
+ unsafe.putObject(object, offset, value);
+ }
+
+ } catch (final IllegalArgumentException e) {
+ throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
+ }
+ }
+
+ private synchronized long getFieldOffset(final Field f) {
+ Long l = fieldOffsetCache.get(f);
+ if (l == null) {
+ l = Long.valueOf(unsafe.objectFieldOffset(f));
+ fieldOffsetCache.put(f, l);
+ }
+
+ return l.longValue();
+ }
+
+ private Object readResolve() {
+ init();
+ return this;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ fieldOffsetCache = new HashMap();
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/XStream12FieldKeySorter.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/XStream12FieldKeySorter.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/converters/reflection/XStream12FieldKeySorter.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007, 2008, 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 19.09.2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+/**
+ * Sort the fields in the order of XStream 1.2.x. Fields are returned in their declaration order, fields of base classes
+ * last.
+ *
+ * @author Jörg Schaible
+ * @since 1.3
+ */
+public class XStream12FieldKeySorter implements FieldKeySorter {
+
+ @Override
+ public Map sort(final Class> type, final Map keyedByFieldKey) {
+ final Map map = new TreeMap(new Comparator() {
+
+ @Override
+ public int compare(final FieldKey fieldKey1, final FieldKey fieldKey2) {
+ int i = fieldKey2.getDepth() - fieldKey1.getDepth();
+ if (i == 0) {
+ i = fieldKey1.getOrder() - fieldKey2.getOrder();
+ }
+ return i;
+ }
+ });
+ map.putAll(keyedByFieldKey);
+ keyedByFieldKey.clear();
+ keyedByFieldKey.putAll(map);
+ return keyedByFieldKey;
+ }
+
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractReferenceMarshaller.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractReferenceMarshaller.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractReferenceMarshaller.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 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 15. March 2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core;
+
+import java.util.Iterator;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.ConverterLookup;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.core.util.ObjectIdDictionary;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.io.path.Path;
+import com.thoughtworks.xstream.io.path.PathTracker;
+import com.thoughtworks.xstream.io.path.PathTrackingWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+
+/**
+ * Abstract base class for a TreeMarshaller, that can build references.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @author Mauro Talevi
+ * @since 1.2
+ */
+public abstract class AbstractReferenceMarshaller extends TreeMarshaller implements MarshallingContext {
+
+ private final ObjectIdDictionary> references = new ObjectIdDictionary>();
+ private final ObjectIdDictionary implicitElements = new ObjectIdDictionary();
+ private final PathTracker pathTracker = new PathTracker();
+ private Path lastPath;
+
+ public AbstractReferenceMarshaller(
+ final HierarchicalStreamWriter writer, final ConverterLookup converterLookup, final Mapper mapper) {
+ super(writer, converterLookup, mapper);
+ this.writer = new PathTrackingWriter(writer, pathTracker);
+ }
+
+ @Override
+ public void convert(final Object item, final Converter converter) {
+ if (getMapper().isImmutableValueType(item.getClass())) {
+ // strings, ints, dates, etc... don't bother using references.
+ converter.marshal(item, writer, this);
+ } else {
+ final Path currentPath = pathTracker.getPath();
+ final Id existingReference = references.lookupId(item);
+ if (existingReference != null && existingReference.getPath() != currentPath) {
+ final String attributeName = getMapper().aliasForSystemAttribute("reference");
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, createReference(currentPath, existingReference.getItem()));
+ }
+ } else {
+ final R newReferenceKey = existingReference == null
+ ? createReferenceKey(currentPath, item)
+ : existingReference.getItem();
+ if (lastPath == null || !currentPath.isAncestor(lastPath)) {
+ fireValidReference(newReferenceKey);
+ lastPath = currentPath;
+ references.associateId(item, new Id(newReferenceKey, currentPath));
+ }
+ converter.marshal(item, writer, new ReferencingMarshallingContext() {
+
+ @Override
+ public void put(final Object key, final Object value) {
+ AbstractReferenceMarshaller.this.put(key, value);
+ }
+
+ @Override
+ public Iterator keys() {
+ return AbstractReferenceMarshaller.this.keys();
+ }
+
+ @Override
+ public Object get(final Object key) {
+ return AbstractReferenceMarshaller.this.get(key);
+ }
+
+ @Override
+ public void convertAnother(final Object nextItem, final Converter converter) {
+ AbstractReferenceMarshaller.this.convertAnother(nextItem, converter);
+ }
+
+ @Override
+ public void convertAnother(final Object nextItem) {
+ AbstractReferenceMarshaller.this.convertAnother(nextItem);
+ }
+
+ @Override
+ public void replace(final Object original, final Object replacement) {
+ references.associateId(replacement, new Id(newReferenceKey, currentPath));
+ }
+
+ @Override
+ public R lookupReference(final Object item) {
+ final Id id = references.lookupId(item);
+ return id.getItem();
+ }
+
+ /**
+ * @deprecated As of 1.4.2
+ */
+ @Deprecated
+ @Override
+ public Path currentPath() {
+ return pathTracker.getPath();
+ }
+
+ @Override
+ public void registerImplicit(final Object item) {
+ if (implicitElements.containsId(item)) {
+ throw new ReferencedImplicitElementException(item, currentPath);
+ }
+ implicitElements.associateId(item, newReferenceKey);
+ }
+ });
+ }
+ }
+ }
+
+ protected abstract String createReference(Path currentPath, R existingReferenceKey);
+
+ protected abstract R createReferenceKey(Path currentPath, Object item);
+
+ protected abstract void fireValidReference(R referenceKey);
+
+ private static class Id {
+ private final R item;
+ private final Path path;
+
+ public Id(final R item, final Path path) {
+ this.item = item;
+ this.path = path;
+ }
+
+ protected R getItem() {
+ return item;
+ }
+
+ protected Path getPath() {
+ return path;
+ }
+ }
+
+ public static class ReferencedImplicitElementException extends ConversionException {
+ public ReferencedImplicitElementException(final Object item, final Path path) {
+ super("Cannot reference implicit element");
+ add("implicit-element", item.toString());
+ add("referencing-element", path.toString());
+ }
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractReferenceUnmarshaller.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractReferenceUnmarshaller.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractReferenceUnmarshaller.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2011, 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 15. March 2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.ConverterLookup;
+import com.thoughtworks.xstream.core.util.FastStack;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+
+/**
+ * Abstract base class for a TreeUnmarshaller, that resolves references.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @author Mauro Talevi
+ * @since 1.2
+ */
+public abstract class AbstractReferenceUnmarshaller extends TreeUnmarshaller {
+
+ private static final Object NULL = new Object();
+ private final Map values = new HashMap();
+ private final FastStack parentStack = new FastStack(16);
+
+ public AbstractReferenceUnmarshaller(
+ final Object root, final HierarchicalStreamReader reader, final ConverterLookup converterLookup,
+ final Mapper mapper) {
+ super(root, reader, converterLookup, mapper);
+ }
+
+ @Override
+ protected Object convert(final Object parent, final Class> type, final Converter converter) {
+ if (parentStack.size() > 0) { // handles circular references
+ final R parentReferenceKey = parentStack.peek();
+ if (parentReferenceKey != null) {
+ // see AbstractCircularReferenceTest.testWeirdCircularReference()
+ if (!values.containsKey(parentReferenceKey)) {
+ values.put(parentReferenceKey, parent);
+ }
+ }
+ }
+ final Object result;
+ final String attributeName = getMapper().aliasForSystemAttribute("reference");
+ final String reference = attributeName == null ? null : reader.getAttribute(attributeName);
+ if (reference != null) {
+ final Object cache = values.get(getReferenceKey(reference));
+ if (cache == null) {
+ final ConversionException ex = new ConversionException("Invalid reference");
+ ex.add("reference", reference);
+ throw ex;
+ }
+ result = cache == NULL ? null : cache;
+ } else {
+ final R currentReferenceKey = getCurrentReferenceKey();
+ parentStack.push(currentReferenceKey);
+ result = super.convert(parent, type, converter);
+ if (currentReferenceKey != null) {
+ values.put(currentReferenceKey, result == null ? NULL : result);
+ }
+ parentStack.popSilently();
+ }
+ return result;
+ }
+
+ protected abstract R getReferenceKey(String reference);
+
+ protected abstract R getCurrentReferenceKey();
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractTreeMarshallingStrategy.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractTreeMarshallingStrategy.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/AbstractTreeMarshallingStrategy.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 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 26.09.2007 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core;
+
+import com.thoughtworks.xstream.MarshallingStrategy;
+import com.thoughtworks.xstream.converters.ConverterLookup;
+import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+
+/**
+ * Basic functionality of a tree based marshalling strategy.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @since 1.3
+ */
+public abstract class AbstractTreeMarshallingStrategy implements MarshallingStrategy {
+
+ @Override
+ public Object unmarshal(final Object root, final HierarchicalStreamReader reader, final DataHolder dataHolder,
+ final ConverterLookup converterLookup, final Mapper mapper) {
+ final TreeUnmarshaller context = createUnmarshallingContext(root, reader, converterLookup, mapper);
+ return context.start(dataHolder);
+ }
+
+ @Override
+ public void marshal(final HierarchicalStreamWriter writer, final Object obj, final ConverterLookup converterLookup,
+ final Mapper mapper, final DataHolder dataHolder) {
+ final TreeMarshaller context = createMarshallingContext(writer, converterLookup, mapper);
+ context.start(obj, dataHolder);
+ }
+
+ protected abstract TreeUnmarshaller createUnmarshallingContext(Object root, HierarchicalStreamReader reader,
+ ConverterLookup converterLookup, Mapper mapper);
+
+ protected abstract TreeMarshaller createMarshallingContext(HierarchicalStreamWriter writer,
+ ConverterLookup converterLookup, Mapper mapper);
+}
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/core/BaseException.java'.
Fisheye: No comparison available. Pass `N' to diff?
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/Caching.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/Caching.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/Caching.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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 19. July 2011 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core;
+
+/**
+ * Marker interface for caching implementations.
+ *
+ * @author Jörg Schaible
+ * @since 1.4
+ */
+public interface Caching {
+ void flushCache();
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ClassLoaderReference.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ClassLoaderReference.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ClassLoaderReference.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 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. June 2013 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core;
+
+import com.thoughtworks.xstream.core.util.CompositeClassLoader;
+
+/**
+ * Reference to a ClassLoader, allowing a single instance to be passed around the codebase that
+ * can later have its destination changed.
+ *
+ * @author Jörg Schaible
+ * @since 1.4.5
+ */
+public final class ClassLoaderReference {
+
+ private transient ClassLoader reference;
+
+ public ClassLoaderReference(ClassLoader reference) {
+ setReference(reference);
+ }
+
+ public ClassLoader getReference() {
+ return reference;
+ }
+
+ public void setReference(ClassLoader reference) {
+ this.reference = reference instanceof com.thoughtworks.xstream.core.util.ClassLoaderReference
+ ? ((com.thoughtworks.xstream.core.util.ClassLoaderReference)reference)
+ .getReference() : reference;
+ }
+
+ private Object readResolve() {
+ this.reference = new CompositeClassLoader();
+ return this;
+ }
+}
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/core/DefaultClassMapper.java'.
Fisheye: No comparison available. Pass `N' to diff?
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/DefaultConverterLookup.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/DefaultConverterLookup.java (.../DefaultConverterLookup.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/DefaultConverterLookup.java (.../DefaultConverterLookup.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,55 +1,82 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 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 07. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.alias.ClassMapper;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
-import com.thoughtworks.xstream.converters.basic.NullConverter;
+import com.thoughtworks.xstream.converters.ConverterRegistry;
import com.thoughtworks.xstream.core.util.PrioritizedList;
-import com.thoughtworks.xstream.XStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-public class DefaultConverterLookup implements ConverterLookup {
+/**
+ * The default implementation of converters lookup.
+ *
+ * @author Joe Walnes
+ * @author Jörg Schaible
+ * @author Guilherme Silveira
+ */
+public class DefaultConverterLookup implements ConverterLookup, ConverterRegistry, Caching {
- private final PrioritizedList converters = new PrioritizedList();
- private final Converter nullConverter = new NullConverter();
- private final Map typeToConverterMap = Collections.synchronizedMap(new HashMap());
- private final ClassMapper classMapper;
+ private final PrioritizedList converters = new PrioritizedList();
+ private transient Map, Converter> typeToConverterMap;
- public DefaultConverterLookup(ClassMapper classMapper) {
- this.classMapper = classMapper;
+ public DefaultConverterLookup() {
+ readResolve();
}
- /**
- * @deprecated As of 1.1.1 you can register Converters with priorities, making the need for a default converter redundant.
- */
- public Converter defaultConverter() {
- return (Converter) converters.firstOfLowestPriority();
- }
-
- public Converter lookupConverterForType(Class type) {
- if (type == null) {
- return nullConverter;
+ @Override
+ public Converter lookupConverterForType(final Class> type) {
+ final Converter cachedConverter = typeToConverterMap.get(type);
+ if (cachedConverter != null) {
+ return cachedConverter;
}
- Converter cachedConverter = (Converter) typeToConverterMap.get(type);
- if (cachedConverter != null) return cachedConverter;
- Class mapType = classMapper.defaultImplementationOf(type);
- Iterator iterator = converters.iterator();
- while (iterator.hasNext()) {
- Converter converter = (Converter) iterator.next();
- if (converter.canConvert(mapType)) {
- typeToConverterMap.put(type, converter);
+ for (final Converter converter : converters) {
+ if (converter.canConvert(type)) {
return converter;
}
}
throw new ConversionException("No converter specified for " + type);
}
- public void registerConverter(Converter converter, int priority) {
+
+ @Override
+ public void registerConverter(final Converter converter, final int priority) {
converters.add(converter, priority);
+ for (final Iterator> iter = typeToConverterMap.keySet().iterator(); iter.hasNext();) {
+ final Class> type = iter.next();
+ if (converter.canConvert(type)) {
+ iter.remove();
+ }
+ }
}
+ @Override
+ public void flushCache() {
+ typeToConverterMap.clear();
+ for (final Converter converter : converters) {
+ if (converter instanceof Caching) {
+ ((Caching)converter).flushCache();
+ }
+ }
+ }
+
+ private Object readResolve() {
+ // TODO: Use ConcurrentMap
+ typeToConverterMap = Collections.synchronizedMap(new WeakHashMap, Converter>());
+ return this;
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/JVM.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/JVM.java (.../JVM.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/JVM.java (.../JVM.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,97 +1,555 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 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. May 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.text.AttributedString;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Comparator;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+
+import com.thoughtworks.xstream.converters.reflection.FieldDictionary;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
+import com.thoughtworks.xstream.core.util.CustomObjectOutputStream;
+import com.thoughtworks.xstream.core.util.DependencyInjectionFactory;
+import com.thoughtworks.xstream.core.util.PresortedMap;
+import com.thoughtworks.xstream.core.util.PresortedSet;
-import java.security.AccessControlException;
-public class JVM {
+public class JVM implements Caching {
private ReflectionProvider reflectionProvider;
- private static final float majorJavaVersion = getMajorJavaVersion(System.getProperty("java.version"));
+ private static final boolean isAWTAvailable;
+ private static final boolean isSwingAvailable;
+ private static final boolean isSQLAvailable;
+ private static final boolean canAllocateWithUnsafe;
+ private static final boolean canWriteWithUnsafe;
+ private static final boolean optimizedTreeSetAddAll;
+ private static final boolean optimizedTreeMapPutAll;
+ private static final boolean canParseUTCDateFormat;
+ private static final boolean canCreateDerivedObjectOutputStream;
- static final float DEFAULT_JAVA_VERSION = 1.3f;
-
+ private static final String vendor = System.getProperty("java.vm.vendor");
+ private static final float majorJavaVersion = getMajorJavaVersion();
+ private static final float DEFAULT_JAVA_VERSION = 1.4f;
+ private static final boolean reverseFieldOrder = false;
+ private static final Class extends ReflectionProvider> reflectionProviderType;
+
+ static class Test {
+ @SuppressWarnings("unused")
+ private Object o;
+ @SuppressWarnings("unused")
+ private char c;
+ @SuppressWarnings("unused")
+ private byte b;
+ @SuppressWarnings("unused")
+ private short s;
+ @SuppressWarnings("unused")
+ private int i;
+ @SuppressWarnings("unused")
+ private long l;
+ @SuppressWarnings("unused")
+ private float f;
+ @SuppressWarnings("unused")
+ private double d;
+ @SuppressWarnings("unused")
+ private boolean bool;
+
+ Test() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ static {
+ boolean test = true;
+ Object unsafe = null;
+ try {
+ final Class> unsafeClass = Class.forName("sun.misc.Unsafe");
+ final Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ unsafe = unsafeField.get(null);
+ final Method allocateInstance = unsafeClass.getDeclaredMethod("allocateInstance", new Class[]{Class.class});
+ allocateInstance.setAccessible(true);
+ test = allocateInstance.invoke(unsafe, new Object[]{Test.class}) != null;
+ } catch (final Exception e) {
+ test = false;
+ } catch (final Error e) {
+ test = false;
+ }
+ canAllocateWithUnsafe = test;
+ test = false;
+ Class extends ReflectionProvider> type = PureJavaReflectionProvider.class;
+ if (canUseSunUnsafeReflectionProvider()) {
+ Class extends ReflectionProvider> cls = loadClassForName("com.thoughtworks.xstream.converters.reflection.SunUnsafeReflectionProvider");
+ if (cls != null) {
+ try {
+ final ReflectionProvider provider = DependencyInjectionFactory.newInstance(cls);
+ final Test t = (Test)provider.newInstance(Test.class);
+ try {
+ provider.writeField(t, "o", "object", Test.class);
+ provider.writeField(t, "c", new Character('c'), Test.class);
+ provider.writeField(t, "b", new Byte((byte)1), Test.class);
+ provider.writeField(t, "s", new Short((short)1), Test.class);
+ provider.writeField(t, "i", new Integer(1), Test.class);
+ provider.writeField(t, "l", new Long(1), Test.class);
+ provider.writeField(t, "f", new Float(1), Test.class);
+ provider.writeField(t, "d", new Double(1), Test.class);
+ provider.writeField(t, "bool", Boolean.TRUE, Test.class);
+ test = true;
+ } catch (final IncompatibleClassChangeError e) {
+ cls = null;
+ } catch (final ObjectAccessException e) {
+ cls = null;
+ }
+ if (cls == null) {
+ cls = loadClassForName("com.thoughtworks.xstream.converters.reflection.SunLimitedUnsafeReflectionProvider");
+ }
+ type = cls;
+ } catch (final ObjectAccessException e) {
+ }
+ }
+ }
+ reflectionProviderType = type;
+ canWriteWithUnsafe = test;
+ final Comparator comparator = new Comparator() {
+ @Override
+ public int compare(final Object o1, final Object o2) {
+ throw new RuntimeException();
+ }
+ };
+ final SortedMap map = new PresortedMap(comparator);
+ map.put("one", null);
+ map.put("two", null);
+ try {
+ new TreeMap(comparator).putAll(map);
+ test = true;
+ } catch (final RuntimeException e) {
+ test = false;
+ }
+ optimizedTreeMapPutAll = test;
+ final SortedSet set = new PresortedSet(comparator);
+ set.addAll(map.keySet());
+ try {
+ new TreeSet(comparator).addAll(set);
+ test = true;
+ } catch (final RuntimeException e) {
+ test = false;
+ }
+ optimizedTreeSetAddAll = test;
+ try {
+ new SimpleDateFormat("z").parse("UTC");
+ test = true;
+ } catch (final ParseException e) {
+ test = false;
+ }
+ canParseUTCDateFormat = test;
+ try {
+ test = new CustomObjectOutputStream(null) != null;
+ } catch (final RuntimeException e) {
+ test = false;
+ } catch (final IOException e) {
+ test = false;
+ }
+ canCreateDerivedObjectOutputStream = test;
+
+ isAWTAvailable = loadClassForName("java.awt.Color", false) != null;
+ isSwingAvailable = loadClassForName("javax.swing.LookAndFeel", false) != null;
+ isSQLAvailable = loadClassForName("java.sql.Date") != null;
+ }
+
/**
- * Parses the java version system property to determine the major java version,
- * ie 1.x
+ * @deprecated As of 1.4.5 use the static methods of JVM.
+ */
+ @Deprecated
+ public JVM() {
+ }
+
+ /**
+ * Parses the java version system property to determine the major java version, i.e. 1.x
*
- * @param javaVersion the system property 'java.version'
* @return A float of the form 1.x
*/
- static final float getMajorJavaVersion(String javaVersion) {
- try {
- return Float.parseFloat(javaVersion.substring(0, 3));
- } catch ( NumberFormatException e ){
+ private static final float getMajorJavaVersion() {
+ try {
+ return isAndroid() ? 1.5f : Float.parseFloat(System.getProperty("java.specification.version"));
+ } catch (final NumberFormatException e) {
// Some JVMs may not conform to the x.y.z java.version format
return DEFAULT_JAVA_VERSION;
}
}
+ /**
+ * @deprecated As of 1.4.4, minimal JDK version is 1.4 already
+ */
+ @Deprecated
public static boolean is14() {
return majorJavaVersion >= 1.4f;
}
+ /**
+ * @deprecated As of 1.4.4, minimal JDK version will be 1.6 for next major release
+ */
+ @Deprecated
public static boolean is15() {
return majorJavaVersion >= 1.5f;
}
- private static boolean isSun() {
- return System.getProperty("java.vm.vendor").indexOf("Sun") != -1;
+ /**
+ * @deprecated As of 1.4.4, minimal JDK version will be 1.6 for next major release
+ */
+ @Deprecated
+ public static boolean is16() {
+ return majorJavaVersion >= 1.6f;
}
- private static boolean isApple() {
- return System.getProperty("java.vm.vendor").indexOf("Apple") != -1;
+ /**
+ * @since 1.4
+ */
+ public static boolean is17() {
+ return majorJavaVersion >= 1.7f;
}
- private static boolean isHPUX() {
- return System.getProperty("java.vm.vendor").indexOf("Hewlett-Packard Company") != -1;
+ /**
+ * @since 1.4
+ */
+ public static boolean is18() {
+ return majorJavaVersion >= 1.8f;
}
private static boolean isIBM() {
- return System.getProperty("java.vm.vendor").indexOf("IBM") != -1;
+ return vendor.indexOf("IBM") != -1;
}
- private static boolean isBlackdown() {
- return System.getProperty("java.vm.vendor").indexOf("Blackdown") != -1;
+ /**
+ * @since 1.4
+ */
+ private static boolean isAndroid() {
+ return vendor.indexOf("Android") != -1;
}
- private static boolean isBEA() {
- return System.getProperty("java.vm.vendor").indexOf("BEA") != -1;
+ /**
+ * Load a XStream class for the given name.
+ *
+ * This method is not meant to use loading arbitrary classes. It is used by XStream bootstrap until it is able to
+ * use the user provided or the default {@link ClassLoader}.
+ *
+ *
+ * @since 1.4.5
+ */
+ public static Class extends T> loadClassForName(final String name) {
+ return loadClassForName(name, true);
}
- public Class loadClass(String name) {
+ /**
+ * @deprecated As of 1.4.5 use {@link #loadClassForName(String)}
+ */
+ @Deprecated
+ public Class extends T> loadClass(final String name) {
+ return loadClassForName(name, true);
+ }
+
+ /**
+ * Load a XStream class for the given name.
+ *
+ * This method is not meant to use loading arbitrary classes. It is used by XStream bootstrap until it is able to
+ * use the user provided or the default {@link ClassLoader}.
+ *
+ *
+ * @since 1.4.5
+ */
+ public static Class extends T> loadClassForName(final String name, final boolean initialize) {
try {
- return Class.forName(name, false, getClass().getClassLoader());
- } catch (ClassNotFoundException e) {
+ @SuppressWarnings("unchecked")
+ final Class extends T> clazz = (Class extends T>)Class.forName(name, initialize, JVM.class
+ .getClassLoader());
+ return clazz;
+ } catch (final LinkageError e) {
return null;
+ } catch (final ClassNotFoundException e) {
+ return null;
}
}
-
+
+ /**
+ * @since 1.4.4
+ * @deprecated As of 1.4.5 use {@link #loadClassForName(String, boolean)}
+ */
+ @Deprecated
+ public Class extends T> loadClass(final String name, final boolean initialize) {
+ return loadClassForName(name, initialize);
+ }
+
+ /**
+ * Create the best matching ReflectionProvider.
+ *
+ * @return a new instance
+ * @since 1.4.5
+ */
+ public static ReflectionProvider newReflectionProvider() {
+ return DependencyInjectionFactory.newInstance(reflectionProviderType);
+ }
+
+ /**
+ * Create the best matching ReflectionProvider.
+ *
+ * @param dictionary the FieldDictionary to use by the ReflectionProvider
+ * @return a new instance
+ * @since 1.4.5
+ */
+ public static ReflectionProvider newReflectionProvider(final FieldDictionary dictionary) {
+ return DependencyInjectionFactory.newInstance(reflectionProviderType, dictionary);
+ }
+
+ /**
+ * Get the XMLInputFactory implementation used normally by the current Java runtime as standard.
+ *
+ * In contrast to XMLInputFactory.newFactory() this method will ignore any implementations provided with the system
+ * property javax.xml.stream.XMLInputFactory, implementations configured in lib/stax.properties or
+ * registered with the Service API.
+ *
+ *
+ * @return the XMLInputFactory implementation or null
+ * @throws ClassNotFoundException if the standard class cannot be found
+ * @since 1.4.5
+ */
+ @SuppressWarnings("unchecked")
+ public static Class extends XMLInputFactory> getStaxInputFactory() throws ClassNotFoundException {
+ if (is16()) {
+ if (isIBM()) {
+ return (Class extends XMLInputFactory>)Class.forName("com.ibm.xml.xlxp.api.stax.XMLInputFactoryImpl");
+ } else {
+ return (Class extends XMLInputFactory>)Class
+ .forName("com.sun.xml.internal.stream.XMLInputFactoryImpl");
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the XMLOutputFactory implementation used normally by the current Java runtime as standard.
+ *
+ * In contrast to XMLOutputFactory.newFactory() this method will ignore any implementations provided with the system
+ * property javax.xml.stream.XMLOutputFactory, implementations configured in lib/stax.properties
+ * or registered with the Service API.
+ *
+ *
+ * @return the XMLOutputFactory implementation or null
+ * @throws ClassNotFoundException if the standard class cannot be found
+ * @since 1.4.5
+ */
+ @SuppressWarnings("unchecked")
+ public static Class extends XMLOutputFactory> getStaxOutputFactory() throws ClassNotFoundException {
+ if (is16()) {
+ if (isIBM()) {
+ return (Class extends XMLOutputFactory>)Class
+ .forName("com.ibm.xml.xlxp.api.stax.XMLOutputFactoryImpl");
+ } else {
+ return (Class extends XMLOutputFactory>)Class
+ .forName("com.sun.xml.internal.stream.XMLOutputFactoryImpl");
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated As of 1.4.5 use {@link #newReflectionProvider()}
+ */
+ @Deprecated
public synchronized ReflectionProvider bestReflectionProvider() {
if (reflectionProvider == null) {
- try {
- if ( canUseSun14ReflectionProvider() ) {
- String cls = "com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider";
- reflectionProvider = (ReflectionProvider) loadClass(cls).newInstance();
- } else {
- reflectionProvider = new PureJavaReflectionProvider();
- }
- } catch (InstantiationException e) {
- reflectionProvider = new PureJavaReflectionProvider();
- } catch (IllegalAccessException e) {
- reflectionProvider = new PureJavaReflectionProvider();
- } catch (AccessControlException e) {
- // thrown when trying to access sun.misc package in Applet context.
- reflectionProvider = new PureJavaReflectionProvider();
- }
+ reflectionProvider = newReflectionProvider();
}
return reflectionProvider;
}
- private boolean canUseSun14ReflectionProvider() {
- return (isSun() || isApple() || isHPUX() || isIBM() || isBlackdown()) && is14() && loadClass("sun.misc.Unsafe") != null;
- }
+ private static boolean canUseSunUnsafeReflectionProvider() {
+ return canAllocateWithUnsafe && is14();
+ }
+ private static boolean canUseSunLimitedUnsafeReflectionProvider() {
+ return canWriteWithUnsafe;
+ }
+
+ /**
+ * @deprecated As of 1.4.5
+ */
+ @Deprecated
+ public static boolean reverseFieldDefinition() {
+ return reverseFieldOrder;
+ }
+
+ /**
+ * Checks if AWT is available.
+ *
+ * @since 1.4.5
+ */
+ public static boolean isAWTAvailable() {
+ return isAWTAvailable;
+ }
+
+ /**
+ * Checks if the jvm supports awt.
+ *
+ * @deprecated As of 1.4.5 use {@link #isAWTAvailable()}
+ */
+ @Deprecated
+ public boolean supportsAWT() {
+ return isAWTAvailable;
+ }
+
+ /**
+ * Checks if Swing is available.
+ *
+ * @since 1.4.5
+ */
+ public static boolean isSwingAvailable() {
+ return isSwingAvailable;
+ }
+
+ /**
+ * Checks if the jvm supports swing.
+ *
+ * @deprecated As of 1.4.5 use {@link #isSwingAvailable()}
+ */
+ @Deprecated
+ public boolean supportsSwing() {
+ return isSwingAvailable;
+ }
+
+ /**
+ * Checks if SQL is available.
+ *
+ * @since 1.4.5
+ */
+ public static boolean isSQLAvailable() {
+ return isSQLAvailable;
+ }
+
+ /**
+ * Checks if the jvm supports sql.
+ *
+ * @deprecated As of 1.4.5 use {@link #isSQLAvailable()}
+ */
+ @Deprecated
+ public boolean supportsSQL() {
+ return isSQLAvailable;
+ }
+
+ /**
+ * Checks if TreeSet.addAll is optimized for SortedSet argument.
+ *
+ * @since 1.4
+ */
+ public static boolean hasOptimizedTreeSetAddAll() {
+ return optimizedTreeSetAddAll;
+ }
+
+ /**
+ * Checks if TreeMap.putAll is optimized for SortedMap argument.
+ *
+ * @since 1.4
+ */
+ public static boolean hasOptimizedTreeMapPutAll() {
+ return optimizedTreeMapPutAll;
+ }
+
+ public static boolean canParseUTCDateFormat() {
+ return canParseUTCDateFormat;
+ }
+
+ /**
+ * @since 1.4.6
+ */
+ public static boolean canCreateDerivedObjectOutputStream() {
+ return canCreateDerivedObjectOutputStream;
+ }
+
+ /**
+ * @deprecated As of 1.4.5 no functionality
+ */
+ @Deprecated
+ @Override
+ public void flushCache() {
+ }
+
+ public static void main(final String... args) {
+ boolean reverseJDK = false;
+ Field[] fields = AttributedString.class.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals("text")) {
+ reverseJDK = i > 3;
+ break;
+ }
+ }
+
+ boolean reverseLocal = false;
+ fields = Test.class.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals("o")) {
+ reverseLocal = i > 3;
+ break;
+ }
+ }
+
+ String staxInputFactory = null;
+ try {
+ staxInputFactory = getStaxInputFactory().getName();
+ } catch (final ClassNotFoundException e) {
+ staxInputFactory = e.getMessage();
+ } catch (final NullPointerException e) {
+ }
+
+ String staxOutputFactory = null;
+ try {
+ staxOutputFactory = getStaxOutputFactory().getName();
+ } catch (final ClassNotFoundException e) {
+ staxOutputFactory = e.getMessage();
+ } catch (final NullPointerException e) {
+ }
+
+ System.out.println("XStream JVM diagnostics");
+ System.out.println("java.specification.version: " + System.getProperty("java.specification.version"));
+ System.out.println("java.specification.vendor: " + System.getProperty("java.specification.vendor"));
+ System.out.println("java.specification.name: " + System.getProperty("java.specification.name"));
+ System.out.println("java.vm.vendor: " + vendor);
+ System.out.println("java.vendor: " + System.getProperty("java.vendor"));
+ System.out.println("java.vm.name: " + System.getProperty("java.vm.name"));
+ System.out.println("Version: " + majorJavaVersion);
+ System.out.println("XStream support for enhanced Mode: " + canUseSunUnsafeReflectionProvider());
+ System.out.println("XStream support for reduced Mode: " + canUseSunLimitedUnsafeReflectionProvider());
+ System.out.println("Supports AWT: " + isAWTAvailable());
+ System.out.println("Supports Swing: " + isSwingAvailable());
+ System.out.println("Supports SQL: " + isSQLAvailable());
+ System.out.println("Java Beans EventHandler present: " + (loadClassForName("java.beans.EventHandler") != null));
+ System.out.println("Standard StAX XMLInputFactory: " + staxInputFactory);
+ System.out.println("Standard StAX XMLOutputFactory: " + staxOutputFactory);
+ System.out.println("Optimized TreeSet.addAll: " + hasOptimizedTreeSetAddAll());
+ System.out.println("Optimized TreeMap.putAll: " + hasOptimizedTreeMapPutAll());
+ System.out.println("Can parse UTC date format: " + canParseUTCDateFormat());
+ System.out.println("Can create derive ObjectOutputStream: " + canCreateDerivedObjectOutputStream());
+ System.out.println("Reverse field order detected for JDK: " + reverseJDK);
+ System.out
+ .println("Reverse field order detected (only if JVM class itself has been compiled): " + reverseLocal);
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/MapBackedDataHolder.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/MapBackedDataHolder.java (.../MapBackedDataHolder.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/MapBackedDataHolder.java (.../MapBackedDataHolder.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,32 +1,47 @@
+/*
+ * Copyright (C) 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 04. October 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.converters.DataHolder;
-
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import com.thoughtworks.xstream.converters.DataHolder;
+
+
public class MapBackedDataHolder implements DataHolder {
- private final Map map;
+ private final Map map;
public MapBackedDataHolder() {
- this(new HashMap());
+ this(new HashMap());
}
- public MapBackedDataHolder(Map map) {
+ public MapBackedDataHolder(final Map map) {
this.map = map;
}
- public Object get(Object key) {
+ @Override
+ public Object get(final Object key) {
return map.get(key);
}
- public void put(Object key, Object value) {
+ @Override
+ public void put(final Object key, final Object value) {
map.put(key, value);
}
- public Iterator keys() {
+ @Override
+ public Iterator keys() {
return Collections.unmodifiableCollection(map.keySet()).iterator();
}
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdMarshaller.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdMarshaller.java (.../ReferenceByIdMarshaller.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdMarshaller.java (.../ReferenceByIdMarshaller.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,51 +1,57 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 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 15. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.alias.ClassMapper;
-import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
-import com.thoughtworks.xstream.core.util.ObjectIdDictionary;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.io.path.Path;
+import com.thoughtworks.xstream.mapper.Mapper;
-public class ReferenceByIdMarshaller extends TreeMarshaller {
- private ObjectIdDictionary references = new ObjectIdDictionary();
- private IDGenerator idGenerator;
+public class ReferenceByIdMarshaller extends AbstractReferenceMarshaller {
+ private final IDGenerator idGenerator;
+
public static interface IDGenerator {
- String next();
+ String next(Object item);
}
- public ReferenceByIdMarshaller(HierarchicalStreamWriter writer,
- ConverterLookup converterLookup,
- ClassMapper classMapper,
- IDGenerator idGenerator) {
- super(writer, converterLookup, classMapper);
+ public ReferenceByIdMarshaller(
+ final HierarchicalStreamWriter writer, final ConverterLookup converterLookup, final Mapper mapper,
+ final IDGenerator idGenerator) {
+ super(writer, converterLookup, mapper);
this.idGenerator = idGenerator;
}
- public ReferenceByIdMarshaller(HierarchicalStreamWriter writer,
- ConverterLookup converterLookup,
- ClassMapper classMapper) {
- this(writer, converterLookup, classMapper, new SequenceGenerator(1));
+ public ReferenceByIdMarshaller(
+ final HierarchicalStreamWriter writer, final ConverterLookup converterLookup, final Mapper mapper) {
+ this(writer, converterLookup, mapper, new SequenceGenerator(1));
}
- public void convertAnother(Object item) {
- Converter converter = converterLookup.lookupConverterForType(item.getClass());
+ @Override
+ protected String createReference(final Path currentPath, final String existingReferenceKey) {
+ return existingReferenceKey.toString();
+ }
- if (classMapper.isImmutableValueType(item.getClass())) {
- // strings, ints, dates, etc... don't bother using references.
- converter.marshal(item, writer, this);
- } else {
- Object idOfExistingReference = references.lookupId(item);
- if (idOfExistingReference != null) {
- writer.addAttribute("reference", idOfExistingReference.toString());
- } else {
- String newId = idGenerator.next();
- writer.addAttribute("id", newId);
- references.associateId(item, newId);
- converter.marshal(item, writer, this);
- }
- }
+ @Override
+ protected String createReferenceKey(final Path currentPath, final Object item) {
+ return idGenerator.next(item);
}
+ @Override
+ protected void fireValidReference(final String referenceKey) {
+ final String attributeName = getMapper().aliasForSystemAttribute("id");
+ if (attributeName != null) {
+ writer.addAttribute(attributeName, referenceKey.toString());
+ }
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdMarshallingStrategy.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdMarshallingStrategy.java (.../ReferenceByIdMarshallingStrategy.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdMarshallingStrategy.java (.../ReferenceByIdMarshallingStrategy.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,22 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 16. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.MarshallingStrategy;
-import com.thoughtworks.xstream.alias.ClassMapper;
-import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
-public class ReferenceByIdMarshallingStrategy implements MarshallingStrategy {
- public Object unmarshal(Object root, HierarchicalStreamReader reader, DataHolder dataHolder, DefaultConverterLookup converterLookup, ClassMapper classMapper) {
- return new ReferenceByIdUnmarshaller(
- root, reader, converterLookup,
- classMapper).start(dataHolder);
- }
+public class ReferenceByIdMarshallingStrategy extends AbstractTreeMarshallingStrategy {
- public void marshal(HierarchicalStreamWriter writer, Object obj, DefaultConverterLookup converterLookup, ClassMapper classMapper, DataHolder dataHolder) {
- new ReferenceByIdMarshaller(
- writer, converterLookup, classMapper).start(obj, dataHolder);
+ @Override
+ protected TreeUnmarshaller createUnmarshallingContext(final Object root, final HierarchicalStreamReader reader,
+ final ConverterLookup converterLookup, final Mapper mapper) {
+ return new ReferenceByIdUnmarshaller(root, reader, converterLookup, mapper);
}
+ @Override
+ protected TreeMarshaller createMarshallingContext(final HierarchicalStreamWriter writer,
+ final ConverterLookup converterLookup, final Mapper mapper) {
+ return new ReferenceByIdMarshaller(writer, converterLookup, mapper);
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdUnmarshaller.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdUnmarshaller.java (.../ReferenceByIdUnmarshaller.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByIdUnmarshaller.java (.../ReferenceByIdUnmarshaller.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,41 +1,37 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 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 15. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.alias.ClassMapper;
import com.thoughtworks.xstream.converters.ConverterLookup;
-import com.thoughtworks.xstream.core.util.FastStack;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.mapper.Mapper;
-import java.util.HashMap;
-import java.util.Map;
-public class ReferenceByIdUnmarshaller extends TreeUnmarshaller {
+public class ReferenceByIdUnmarshaller extends AbstractReferenceUnmarshaller {
- private Map values = new HashMap();
- private FastStack parentIdStack = new FastStack(16);
-
- public ReferenceByIdUnmarshaller(Object root, HierarchicalStreamReader reader,
- ConverterLookup converterLookup, ClassMapper classMapper) {
- super(root, reader, converterLookup, classMapper);
+ public ReferenceByIdUnmarshaller(
+ final Object root, final HierarchicalStreamReader reader, final ConverterLookup converterLookup,
+ final Mapper mapper) {
+ super(root, reader, converterLookup, mapper);
}
- public Object convertAnother(Object parent, Class type) {
- if (parentIdStack.size() > 0) { // handles circular references
- Object parentId = parentIdStack.peek();
- if (!values.containsKey(parentId)) { // see AbstractCircularReferenceTest.testWeirdCircularReference()
- values.put(parentId, parent);
- }
- }
- String reference = reader.getAttribute("reference");
- if (reference != null) {
- return values.get(reference);
- } else {
- String currentId = reader.getAttribute("id");
- parentIdStack.push(currentId);
- Object result = super.convertAnother(parent, type);
- values.put(currentId, result);
- parentIdStack.popSilently();
- return result;
- }
+ @Override
+ protected String getReferenceKey(final String reference) {
+ return reference;
}
+ @Override
+ protected String getCurrentReferenceKey() {
+ final String attributeName = getMapper().aliasForSystemAttribute("id");
+ return attributeName == null ? null : reader.getAttribute(attributeName);
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathMarshaller.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathMarshaller.java (.../ReferenceByXPathMarshaller.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathMarshaller.java (.../ReferenceByXPathMarshaller.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,41 +1,50 @@
+/*
+ * Copyright (C) 2004, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 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 03. April 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.alias.ClassMapper;
-import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
-import com.thoughtworks.xstream.core.util.ObjectIdDictionary;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.path.Path;
-import com.thoughtworks.xstream.io.path.PathTracker;
-import com.thoughtworks.xstream.io.path.PathTrackingWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
-public class ReferenceByXPathMarshaller extends TreeMarshaller {
- private PathTracker pathTracker = new PathTracker();
- private ObjectIdDictionary references = new ObjectIdDictionary();
+public class ReferenceByXPathMarshaller extends AbstractReferenceMarshaller {
- public ReferenceByXPathMarshaller(HierarchicalStreamWriter writer, ConverterLookup converterLookup, ClassMapper classMapper) {
- super(writer, converterLookup, classMapper);
- this.writer = new PathTrackingWriter(writer, pathTracker);
+ private final int mode;
+
+ public ReferenceByXPathMarshaller(
+ final HierarchicalStreamWriter writer, final ConverterLookup converterLookup, final Mapper mapper,
+ final int mode) {
+ super(writer, converterLookup, mapper);
+ this.mode = mode;
}
- public void convertAnother(Object item) {
- Converter converter = converterLookup.lookupConverterForType(item.getClass());
+ @Override
+ protected String createReference(final Path currentPath, final Path existingReferenceKey) {
+ final Path existingPath = existingReferenceKey;
+ final Path referencePath = (mode & ReferenceByXPathMarshallingStrategy.ABSOLUTE) > 0
+ ? existingPath
+ : currentPath.relativeTo(existingPath);
+ return (mode & ReferenceByXPathMarshallingStrategy.SINGLE_NODE) > 0 ? referencePath.explicit() : referencePath
+ .toString();
+ }
- if (classMapper.isImmutableValueType(item.getClass())) {
- // strings, ints, dates, etc... don't bother using references.
- converter.marshal(item, writer, this);
- } else {
- Path currentPath = pathTracker.getPath();
- Path pathOfExistingReference = (Path) references.lookupId(item);
- if (pathOfExistingReference != null) {
- Path absolutePath = currentPath.relativeTo(pathOfExistingReference);
- writer.addAttribute("reference", absolutePath.toString());
- } else {
- references.associateId(item, currentPath);
- converter.marshal(item, writer, this);
- }
- }
+ @Override
+ protected Path createReferenceKey(final Path currentPath, final Object item) {
+ return currentPath;
}
+ @Override
+ protected void fireValidReference(final Path referenceKey) {
+ // nothing to do
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathMarshallingStrategy.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathMarshallingStrategy.java (.../ReferenceByXPathMarshallingStrategy.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathMarshallingStrategy.java (.../ReferenceByXPathMarshallingStrategy.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,19 +1,42 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2009, 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 03. April 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.MarshallingStrategy;
-import com.thoughtworks.xstream.alias.ClassMapper;
-import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
-public class ReferenceByXPathMarshallingStrategy implements MarshallingStrategy {
- public Object unmarshal(Object root, HierarchicalStreamReader reader, DataHolder dataHolder, DefaultConverterLookup converterLookup, ClassMapper classMapper) {
- return new ReferenceByXPathUnmarshaller(root, reader, converterLookup,
- classMapper).start(dataHolder);
+public class ReferenceByXPathMarshallingStrategy extends AbstractTreeMarshallingStrategy {
+
+ public static int RELATIVE = 0;
+ public static int ABSOLUTE = 1;
+ public static int SINGLE_NODE = 2;
+ private final int mode;
+
+ public ReferenceByXPathMarshallingStrategy(final int mode) {
+ this.mode = mode;
}
- public void marshal(HierarchicalStreamWriter writer, Object obj, DefaultConverterLookup converterLookup, ClassMapper classMapper, DataHolder dataHolder) {
- new ReferenceByXPathMarshaller(writer, converterLookup, classMapper).start(obj, dataHolder);
+ @Override
+ protected TreeUnmarshaller createUnmarshallingContext(final Object root, final HierarchicalStreamReader reader,
+ final ConverterLookup converterLookup, final Mapper mapper) {
+ return new ReferenceByXPathUnmarshaller(root, reader, converterLookup, mapper);
}
+
+ @Override
+ protected TreeMarshaller createMarshallingContext(final HierarchicalStreamWriter writer,
+ final ConverterLookup converterLookup, final Mapper mapper) {
+ return new ReferenceByXPathMarshaller(writer, converterLookup, mapper, mode);
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathUnmarshaller.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathUnmarshaller.java (.../ReferenceByXPathUnmarshaller.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferenceByXPathUnmarshaller.java (.../ReferenceByXPathUnmarshaller.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,46 +1,50 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2009, 2011, 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 03. April 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.alias.ClassMapper;
import com.thoughtworks.xstream.converters.ConverterLookup;
-import com.thoughtworks.xstream.core.util.FastStack;
+import com.thoughtworks.xstream.io.AbstractReader;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.path.Path;
import com.thoughtworks.xstream.io.path.PathTracker;
import com.thoughtworks.xstream.io.path.PathTrackingReader;
+import com.thoughtworks.xstream.mapper.Mapper;
-import java.util.HashMap;
-import java.util.Map;
-public class ReferenceByXPathUnmarshaller extends TreeUnmarshaller {
+public class ReferenceByXPathUnmarshaller extends AbstractReferenceUnmarshaller {
- private Map values = new HashMap();
- private FastStack parentPathStack = new FastStack(16);
- private PathTracker pathTracker = new PathTracker();
+ private final PathTracker pathTracker = new PathTracker();
+ protected boolean isNameEncoding;
- public ReferenceByXPathUnmarshaller(Object root, HierarchicalStreamReader reader,
- ConverterLookup converterLookup, ClassMapper classMapper) {
- super(root, reader, converterLookup, classMapper);
+ public ReferenceByXPathUnmarshaller(
+ final Object root, final HierarchicalStreamReader reader, final ConverterLookup converterLookup,
+ final Mapper mapper) {
+ super(root, reader, converterLookup, mapper);
this.reader = new PathTrackingReader(reader, pathTracker);
+ isNameEncoding = reader.underlyingReader() instanceof AbstractReader;
}
- public Object convertAnother(Object parent, Class type) {
- if (parentPathStack.size() > 0) { // handles circular references
- Object parentPath = parentPathStack.peek();
- if (!values.containsKey(parentPath)) { // see AbstractCircularReferenceTest.testWeirdCircularReference()
- values.put(parentPath, parent);
- }
- }
- String relativePathOfReference = reader.getAttribute("reference");
- Path currentPath = pathTracker.getPath();
- if (relativePathOfReference != null) {
- return values.get(currentPath.apply(new Path(relativePathOfReference)));
- } else {
- parentPathStack.push(currentPath);
- Object result = super.convertAnother(parent, type);
- values.put(currentPath, result);
- parentPathStack.popSilently();
- return result;
- }
+ @Override
+ protected Path getReferenceKey(final String reference) {
+ final Path path = new Path(isNameEncoding
+ ? ((AbstractReader)reader.underlyingReader()).decodeNode(reference)
+ : reference);
+ // We have absolute references, if path starts with '/'
+ return reference.charAt(0) != '/' ? pathTracker.getPath().apply(path) : path;
}
+ @Override
+ protected Path getCurrentReferenceKey() {
+ return pathTracker.getPath();
+ }
+
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferencingMarshallingContext.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferencingMarshallingContext.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/ReferencingMarshallingContext.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009, 2011, 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 06. May 2009 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core;
+
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.io.path.Path;
+
+
+/**
+ * A {@link MarshallingContext} that manages references.
+ *
+ * @author Jörg Schaible
+ * @since 1.4
+ */
+public interface ReferencingMarshallingContext extends MarshallingContext {
+
+ /**
+ * Retrieve the current path.
+ *
+ * @return the current path
+ * @since 1.4
+ * @deprecated As of 1.4.2
+ */
+ @Deprecated
+ Path currentPath();
+
+ /**
+ * Request the reference key for the given item
+ *
+ * @param item the item to lookup
+ * @return the reference key or null
+ * @since 1.4
+ */
+ K lookupReference(Object item);
+
+ /**
+ * Replace the currently marshalled item.
+ *
+ * Use this method only, if you know exactly what you do! It is a special solution for Serializable
+ * types that make usage of the writeReplace method where the replacing object itself is referenced.
+ *
+ *
+ * @param original the original item to convert
+ * @param replacement the replacement item that is converted instead
+ * @since 1.4
+ */
+ void replace(Object original, Object replacement);
+
+ /**
+ * Register an implicit element. This is typically some kind of collection. Note, that this object may not be
+ * referenced anywhere else in the object stream.
+ *
+ * @param item the object that is implicit
+ * @since 1.4
+ */
+ void registerImplicit(Object item);
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/SequenceGenerator.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/SequenceGenerator.java (.../SequenceGenerator.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/SequenceGenerator.java (.../SequenceGenerator.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,14 +1,26 @@
+/*
+ * Copyright (C) 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 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 16. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
public class SequenceGenerator implements ReferenceByIdMarshaller.IDGenerator {
private int counter;
- public SequenceGenerator(int startsAt) {
- this.counter = startsAt;
+ public SequenceGenerator(final int startsAt) {
+ counter = startsAt;
}
- public String next() {
+ @Override
+ public String next(final Object item) {
return String.valueOf(counter++);
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeMarshaller.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeMarshaller.java (.../TreeMarshaller.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeMarshaller.java (.../TreeMarshaller.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,64 +1,103 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2009, 2011, 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 15. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.alias.ClassMapper;
+import java.util.Iterator;
+
+import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.converters.DataHolder;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.core.util.ObjectIdDictionary;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
-import java.util.Iterator;
public class TreeMarshaller implements MarshallingContext {
protected HierarchicalStreamWriter writer;
protected ConverterLookup converterLookup;
- protected ClassMapper classMapper;
- private ObjectIdDictionary parentObjects = new ObjectIdDictionary();
+ private final Mapper mapper;
+ private final ObjectIdDictionary parentObjects = new ObjectIdDictionary();
private DataHolder dataHolder;
- public TreeMarshaller(HierarchicalStreamWriter writer,
- ConverterLookup converterLookup,
- ClassMapper classMapper) {
+ public TreeMarshaller(
+ final HierarchicalStreamWriter writer, final ConverterLookup converterLookup, final Mapper mapper) {
this.writer = writer;
this.converterLookup = converterLookup;
- this.classMapper = classMapper;
+ this.mapper = mapper;
}
- public void convertAnother(Object item) {
+ @Override
+ public void convertAnother(final Object item) {
+ convertAnother(item, null);
+ }
+
+ @Override
+ public void convertAnother(final Object item, Converter converter) {
+ if (converter == null) {
+ converter = converterLookup.lookupConverterForType(item.getClass());
+ } else {
+ if (!converter.canConvert(item.getClass())) {
+ final ConversionException e = new ConversionException("Explicit selected converter cannot handle item");
+ e.add("item-type", item.getClass().getName());
+ e.add("converter-type", converter.getClass().getName());
+ throw e;
+ }
+ }
+ convert(item, converter);
+ }
+
+ protected void convert(final Object item, final Converter converter) {
if (parentObjects.containsId(item)) {
- throw new CircularReferenceException();
+ final ConversionException e = new CircularReferenceException("Recursive reference to parent object");
+ e.add("item-type", item.getClass().getName());
+ e.add("converter-type", converter.getClass().getName());
+ throw e;
}
parentObjects.associateId(item, "");
- Converter converter = converterLookup.lookupConverterForType(item.getClass());
converter.marshal(item, writer, this);
parentObjects.removeId(item);
}
- public void start(Object item, DataHolder dataHolder) {
+ public void start(final Object item, final DataHolder dataHolder) {
this.dataHolder = dataHolder;
if (item == null) {
- writer.startNode(classMapper.serializedClass(ClassMapper.Null.class));
+ writer.startNode(mapper.serializedClass(null));
writer.endNode();
} else {
- writer.startNode(classMapper.serializedClass(item.getClass()));
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(item.getClass()), item
+ .getClass());
convertAnother(item);
writer.endNode();
}
}
- public Object get(Object key) {
+ @Override
+ public Object get(final Object key) {
lazilyCreateDataHolder();
return dataHolder.get(key);
}
- public void put(Object key, Object value) {
+ @Override
+ public void put(final Object key, final Object value) {
lazilyCreateDataHolder();
dataHolder.put(key, value);
}
- public Iterator keys() {
+ @Override
+ public Iterator keys() {
lazilyCreateDataHolder();
return dataHolder.keys();
}
@@ -69,7 +108,14 @@
}
}
- public static class CircularReferenceException extends RuntimeException {
+ protected Mapper getMapper() {
+ return mapper;
}
+ public static class CircularReferenceException extends ConversionException {
+
+ public CircularReferenceException(final String msg) {
+ super(msg);
+ }
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeMarshallingStrategy.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeMarshallingStrategy.java (.../TreeMarshallingStrategy.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeMarshallingStrategy.java (.../TreeMarshallingStrategy.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,21 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 16. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.MarshallingStrategy;
-import com.thoughtworks.xstream.alias.ClassMapper;
-import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
-public class TreeMarshallingStrategy implements MarshallingStrategy {
- public Object unmarshal(Object root, HierarchicalStreamReader reader, DataHolder dataHolder, DefaultConverterLookup converterLookup, ClassMapper classMapper) {
- return new TreeUnmarshaller(
- root, reader, converterLookup,
- classMapper).start(dataHolder);
- }
+public class TreeMarshallingStrategy extends AbstractTreeMarshallingStrategy {
- public void marshal(HierarchicalStreamWriter writer, Object obj, DefaultConverterLookup converterLookup, ClassMapper classMapper, DataHolder dataHolder) {
- new TreeMarshaller(writer, converterLookup, classMapper).start(obj, dataHolder);
+ @Override
+ protected TreeUnmarshaller createUnmarshallingContext(final Object root, final HierarchicalStreamReader reader,
+ final ConverterLookup converterLookup, final Mapper mapper) {
+ return new TreeUnmarshaller(root, reader, converterLookup, mapper);
}
+ @Override
+ protected TreeMarshaller createMarshallingContext(final HierarchicalStreamWriter writer,
+ final ConverterLookup converterLookup, final Mapper mapper) {
+ return new TreeMarshaller(writer, converterLookup, mapper);
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeUnmarshaller.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeUnmarshaller.java (.../TreeUnmarshaller.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/TreeUnmarshaller.java (.../TreeUnmarshaller.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,82 +1,131 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 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 15. March 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core;
-import com.thoughtworks.xstream.alias.ClassMapper;
+import java.util.Iterator;
+
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.converters.ErrorReporter;
import com.thoughtworks.xstream.converters.ErrorWriter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.core.util.ClassStack;
+import com.thoughtworks.xstream.core.util.FastStack;
+import com.thoughtworks.xstream.core.util.HierarchicalStreams;
import com.thoughtworks.xstream.core.util.PrioritizedList;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.mapper.Mapper;
-import java.util.Iterator;
public class TreeUnmarshaller implements UnmarshallingContext {
- private Object root;
+ private final Object root;
protected HierarchicalStreamReader reader;
- private ConverterLookup converterLookup;
- private ClassMapper classMapper;
- private ClassStack types = new ClassStack(16);
+ private final ConverterLookup converterLookup;
+ private final Mapper mapper;
+ private final FastStack> types = new FastStack>(16);
private DataHolder dataHolder;
- private final PrioritizedList validationList = new PrioritizedList();
+ private final PrioritizedList validationList = new PrioritizedList();
- public TreeUnmarshaller(Object root, HierarchicalStreamReader reader,
- ConverterLookup converterLookup, ClassMapper classMapper) {
+ public TreeUnmarshaller(
+ final Object root, final HierarchicalStreamReader reader, final ConverterLookup converterLookup,
+ final Mapper mapper) {
this.root = root;
this.reader = reader;
this.converterLookup = converterLookup;
- this.classMapper = classMapper;
+ this.mapper = mapper;
}
- public Object convertAnother(Object parent, Class type) {
+ @Override
+ public Object convertAnother(final Object parent, final Class> type) {
+ return convertAnother(parent, type, null);
+ }
+
+ @Override
+ public Object convertAnother(final Object parent, Class> type, Converter converter) {
+ type = mapper.defaultImplementationOf(type);
+ if (converter == null) {
+ converter = converterLookup.lookupConverterForType(type);
+ } else {
+ if (!converter.canConvert(type)) {
+ final ConversionException e = new ConversionException("Explicit selected converter cannot handle type");
+ e.add("item-type", type.getName());
+ e.add("converter-type", converter.getClass().getName());
+ throw e;
+ }
+ }
+ return convert(parent, type, converter);
+ }
+
+ protected Object convert(final Object parent, final Class> type, final Converter converter) {
try {
- Converter converter = converterLookup.lookupConverterForType(type);
- types.push(classMapper.defaultImplementationOf(type));
- Object result = converter.unmarshal(reader, this);
+ types.push(type);
+ final Object result = converter.unmarshal(reader, this);
types.popSilently();
return result;
- } catch (ConversionException conversionException) {
- addInformationTo(conversionException, type);
+ } catch (final ConversionException conversionException) {
+ addInformationTo(conversionException, type, converter, parent);
throw conversionException;
- } catch (RuntimeException e) {
- ConversionException conversionException = new ConversionException(e);
- addInformationTo(conversionException, type);
+ } catch (final RuntimeException e) {
+ final ConversionException conversionException = new ConversionException(e);
+ addInformationTo(conversionException, type, converter, parent);
throw conversionException;
}
}
- private void addInformationTo(ErrorWriter errorWriter, Class type) {
+ private void addInformationTo(final ErrorWriter errorWriter, final Class> type, final Converter converter,
+ final Object parent) {
errorWriter.add("class", type.getName());
errorWriter.add("required-type", getRequiredType().getName());
+ errorWriter.add("converter-type", converter.getClass().getName());
+ if (converter instanceof ErrorReporter) {
+ ((ErrorReporter)converter).appendErrors(errorWriter);
+ }
+ if (parent instanceof ErrorReporter) {
+ ((ErrorReporter)parent).appendErrors(errorWriter);
+ }
reader.appendErrors(errorWriter);
}
- public void addCompletionCallback(Runnable work, int priority) {
+ @Override
+ public void addCompletionCallback(final Runnable work, final int priority) {
validationList.add(work, priority);
}
+ @Override
public Object currentObject() {
return types.size() == 1 ? root : null;
}
- public Class getRequiredType() {
+ @Override
+ public Class> getRequiredType() {
return types.peek();
}
- public Object get(Object key) {
+ @Override
+ public Object get(final Object key) {
lazilyCreateDataHolder();
return dataHolder.get(key);
}
- public void put(Object key, Object value) {
+ @Override
+ public void put(final Object key, final Object value) {
lazilyCreateDataHolder();
dataHolder.put(key, value);
}
- public Iterator keys() {
+ @Override
+ public Iterator keys() {
lazilyCreateDataHolder();
return dataHolder.keys();
}
@@ -87,22 +136,18 @@
}
}
- public Object start(DataHolder dataHolder) {
+ public Object start(final DataHolder dataHolder) {
this.dataHolder = dataHolder;
- String classAttribute = reader.getAttribute(classMapper.attributeForImplementationClass());
- Class type;
- if (classAttribute == null) {
- type = classMapper.realClass(reader.getNodeName());
- } else {
- type = classMapper.realClass(classAttribute);
- }
- Object result = convertAnother(root, type);
- Iterator validations = validationList.iterator();
- while (validations.hasNext()) {
- Runnable runnable = (Runnable) validations.next();
+ final Class> type = HierarchicalStreams.readClassType(reader, mapper);
+ final Object result = convertAnother(null, type);
+ for (final Runnable runnable : validationList) {
runnable.run();
}
return result;
}
+ protected Mapper getMapper() {
+ return mapper;
+ }
+
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/ArrayIterator.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/ArrayIterator.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/ArrayIterator.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011, 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 29.07.2011 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core.util;
+
+import java.lang.reflect.Array;
+import java.util.Iterator;
+
+
+/**
+ * Iterator for an array of arbitrary type.
+ *
+ * @author Jörg Schaible
+ * @since 1.4
+ */
+public class ArrayIterator implements Iterator {
+ private final Object array;
+ private int idx;
+ private final int length;
+
+ public ArrayIterator(final Object array) {
+ this.array = array;
+ length = Array.getLength(array);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return idx < length;
+ }
+
+ @Override
+ public Object next() {
+ return Array.get(array, idx++);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Remove from array");
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/Base64Encoder.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/Base64Encoder.java (.../Base64Encoder.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/Base64Encoder.java (.../Base64Encoder.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,3 +1,14 @@
+/*
+ * Copyright (C) 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007 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 06. August 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core.util;
import java.io.ByteArrayOutputStream;
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/ClassLoaderReference.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/ClassLoaderReference.java (.../ClassLoaderReference.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/ClassLoaderReference.java (.../ClassLoaderReference.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,29 +1,75 @@
+/*
+ * Copyright (C) 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 07. March 2005 by Joe Walnes
+ */
package com.thoughtworks.xstream.core.util;
/**
- * ClassLoader that refers to another ClassLoader, allowing a single instance to be passed around the codebase that
- * can later have its destination changed.
- *
+ * ClassLoader that refers to another ClassLoader, allowing a single instance to be passed around the codebase that can
+ * later have its destination changed.
+ *
* @author Joe Walnes
+ * @author Jörg Schaible
* @since 1.1.1
+ * @deprecated As of 1.4.5 use {@link com.thoughtworks.xstream.core.ClassLoaderReference} instead
*/
+@Deprecated
public class ClassLoaderReference extends ClassLoader {
- private ClassLoader reference;
+ private transient ClassLoader reference;
- public ClassLoaderReference(ClassLoader reference) {
+ /**
+ * @deprecated As of 1.4.5 use
+ * {@link com.thoughtworks.xstream.core.ClassLoaderReference#ClassLoaderReference(ClassLoader)} instead
+ */
+ @Deprecated
+ public ClassLoaderReference(final ClassLoader reference) {
this.reference = reference;
}
- public Class loadClass(String name) throws ClassNotFoundException {
+ /**
+ * @deprecated As of 1.4.5 use {@link com.thoughtworks.xstream.core.ClassLoaderReference#getReference()}
+ * .loadClass(String) instead
+ */
+ @Deprecated
+ @Override
+ public Class> loadClass(final String name) throws ClassNotFoundException {
return reference.loadClass(name);
}
+ /**
+ * @deprecated As of 1.4.5 use {@link com.thoughtworks.xstream.core.ClassLoaderReference#getReference()} instead
+ */
+ @Deprecated
public ClassLoader getReference() {
return reference;
}
- public void setReference(ClassLoader reference) {
+ /**
+ * @deprecated As of 1.4.5 use {@link com.thoughtworks.xstream.core.ClassLoaderReference#setReference(ClassLoader)}
+ * instead
+ */
+ @Deprecated
+ public void setReference(final ClassLoader reference) {
this.reference = reference;
}
+
+ private Object writeReplace() {
+ return new Replacement();
+ }
+
+ static class Replacement {
+
+ private Object readResolve() {
+ return new ClassLoaderReference(new CompositeClassLoader());
+ }
+
+ };
}
Fisheye: Tag c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8 refers to a dead (removed) revision in file `3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/ClassStack.java'.
Fisheye: No comparison available. Pass `N' to diff?
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/Cloneables.java
===================================================================
diff -u
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/Cloneables.java (revision 0)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/Cloneables.java (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009, 2010, 2011, 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 29. August 2009 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.core.util;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
+
+/**
+ * Utility functions for {@link Cloneable} objects.
+ *
+ * @author Jörg Schaible
+ * @since 1.4
+ */
+public class Cloneables {
+
+ @SuppressWarnings("unchecked")
+ public static T clone(final T o) {
+ if (o instanceof Cloneable) {
+ if (o.getClass().isArray()) {
+ final Class> componentType = o.getClass().getComponentType();
+ if (!componentType.isPrimitive()) {
+ return (T)((Object[])o).clone();
+ } else {
+ int length = Array.getLength(o);
+ final Object clone = Array.newInstance(componentType, length);
+ while (length-- > 0) {
+ Array.set(clone, length, Array.get(o, length));
+ }
+ return (T)clone;
+ }
+ } else {
+ try {
+ final Method clone = o.getClass().getMethod("clone");
+ return (T)clone.invoke(o);
+ } catch (final NoSuchMethodException e) {
+ throw new ObjectAccessException("Cloneable type has no clone method", e);
+ } catch (final IllegalAccessException e) {
+ throw new ObjectAccessException("Cannot clone Cloneable type", e);
+ } catch (final InvocationTargetException e) {
+ throw new ObjectAccessException("Exception cloning Cloneable type", e.getCause());
+ }
+ }
+ }
+ return null;
+ }
+
+ public static T cloneIfPossible(final T o) {
+ final T clone = clone(o);
+ return clone == null ? o : clone;
+ }
+}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CompositeClassLoader.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CompositeClassLoader.java (.../CompositeClassLoader.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CompositeClassLoader.java (.../CompositeClassLoader.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,10 +1,26 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2011, 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 16. November 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core.util;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import com.thoughtworks.xstream.core.JVM;
+
/**
* ClassLoader that is composed of other classloaders. Each loader will be used to try to load the particular class, until
* one of them succeeds. Note: The loaders will always be called in the REVERSE order they were added in.
@@ -28,47 +44,103 @@
*
The thread's context classloader (and all its parents)
*
The classloader for XStream (and all its parents)
*
+ *
+ *
The added classloaders are kept with weak references to allow an application container to reload classes.
*
* @author Joe Walnes
+ * @author Jörg Schaible
* @since 1.0.3
*/
public class CompositeClassLoader extends ClassLoader {
+ static {
+ if (JVM.is17()) {
+ // see http://www.cs.duke.edu/csed/java/jdk1.7/technotes/guides/lang/cl-mt.html
+ try {
+ final Method m = ClassLoader.class.getDeclaredMethod("registerAsParallelCapable");
+ if (!m.isAccessible()) {
+ m.setAccessible(true);
+ }
+ m.invoke(null);
+ } catch (final Exception e) {
+ // ignore errors, JVM will synchronize class for Java 7 or higher
+ }
+ }
+ }
- private final List classLoaders = Collections.synchronizedList(new ArrayList());
+ private final ReferenceQueue queue = new ReferenceQueue();
+ private final List> classLoaders = new ArrayList>();
public CompositeClassLoader() {
- add(Object.class.getClassLoader()); // bootstrap loader.
- add(getClass().getClassLoader()); // whichever classloader loaded this jar.
+ addInternal(Object.class.getClassLoader()); // bootstrap loader.
+ addInternal(getClass().getClassLoader()); // whichever classloader loaded this jar.
}
/**
* Add a loader to the n
* @param classLoader
*/
- public void add(ClassLoader classLoader) {
+ public synchronized void add(final ClassLoader classLoader) {
+ cleanup();
if (classLoader != null) {
- classLoaders.add(0, classLoader);
+ addInternal(classLoader);
}
}
- public Class loadClass(String name) throws ClassNotFoundException {
- for (Iterator iterator = classLoaders.iterator(); iterator.hasNext();) {
- ClassLoader classLoader = (ClassLoader) iterator.next();
+ private void addInternal(final ClassLoader classLoader) {
+ WeakReference refClassLoader = null;
+ for (final Iterator> iterator = classLoaders.iterator(); iterator.hasNext();) {
+ final WeakReference ref = iterator.next();
+ final ClassLoader cl = ref.get();
+ if (cl == null) {
+ iterator.remove();
+ } else if (cl == classLoader) {
+ iterator.remove();
+ refClassLoader = ref;
+ }
+ }
+ classLoaders.add(0, refClassLoader != null ? refClassLoader : new WeakReference(classLoader, queue));
+ }
+
+ @Override
+ public Class> loadClass(final String name) throws ClassNotFoundException {
+ final List copy = new ArrayList(classLoaders.size());
+ synchronized(this) {
+ cleanup();
+ for(final WeakReference ref : classLoaders) {
+ final ClassLoader cl = ref.get();
+ if (cl != null) {
+ copy.add(cl);
+ }
+ }
+ }
+
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ for (final ClassLoader classLoader : copy) {
+ if (classLoader == contextClassLoader) {
+ contextClassLoader = null;
+ }
try {
return classLoader.loadClass(name);
- } catch (ClassNotFoundException notFound) {
+ } catch (final ClassNotFoundException notFound) {
// ok.. try another one
}
}
+
// One last try - the context class loader associated with the current thread. Often used in j2ee servers.
// Note: The contextClassLoader cannot be added to the classLoaders list up front as the thread that constructs
// XStream is potentially different to thread that uses it.
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader != null) {
return contextClassLoader.loadClass(name);
} else {
throw new ClassNotFoundException(name);
}
}
+ private void cleanup() {
+ Reference extends ClassLoader> ref;
+ while ((ref = queue.poll()) != null)
+ {
+ classLoaders.remove(ref);
+ }
+ }
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java (.../CustomObjectInputStream.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java (.../CustomObjectInputStream.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,236 +1,358 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2010, 2011, 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 23. August 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core.util;
-import com.thoughtworks.xstream.converters.ConversionException;
-import com.thoughtworks.xstream.converters.DataHolder;
-
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.NotActiveException;
import java.io.ObjectInputStream;
import java.io.ObjectInputValidation;
import java.io.ObjectStreamClass;
+import java.io.StreamCorruptedException;
import java.util.Map;
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.core.ClassLoaderReference;
+
+
public class CustomObjectInputStream extends ObjectInputStream {
- private StreamCallback callback;
+ private final FastStack callbacks = new FastStack(1);
+ private final ClassLoaderReference classLoaderReference;
private static final String DATA_HOLDER_KEY = CustomObjectInputStream.class.getName();
public static interface StreamCallback {
Object readFromStream() throws IOException;
- Map readFieldsFromStream() throws IOException;
+
+ Map readFieldsFromStream() throws IOException;
+
void defaultReadObject() throws IOException;
- void registerValidation(ObjectInputValidation validation, int priority) throws NotActiveException, InvalidObjectException;
+
+ void registerValidation(ObjectInputValidation validation, int priority)
+ throws NotActiveException, InvalidObjectException;
+
void close() throws IOException;
}
- public static synchronized CustomObjectInputStream getInstance(DataHolder whereFrom, CustomObjectInputStream.StreamCallback callback) {
+ /**
+ * @deprecated As of 1.4 use {@link #getInstance(DataHolder, StreamCallback, ClassLoader)}
+ */
+ @Deprecated
+ public static CustomObjectInputStream getInstance(final DataHolder whereFrom,
+ final CustomObjectInputStream.StreamCallback callback) {
+ return getInstance(whereFrom, callback, (ClassLoader)null);
+ }
+
+ /**
+ * @deprecated As of 1.4.5 use {@link #getInstance(DataHolder, StreamCallback, ClassLoaderReference)}
+ */
+ @Deprecated
+ public static synchronized CustomObjectInputStream getInstance(final DataHolder whereFrom,
+ final CustomObjectInputStream.StreamCallback callback, final ClassLoader classLoader) {
+ return getInstance(whereFrom, callback, new ClassLoaderReference(classLoader));
+ }
+
+ public static synchronized CustomObjectInputStream getInstance(final DataHolder whereFrom,
+ final CustomObjectInputStream.StreamCallback callback, final ClassLoaderReference classLoaderReference) {
try {
- CustomObjectInputStream result = (CustomObjectInputStream) whereFrom.get(DATA_HOLDER_KEY);
+ CustomObjectInputStream result = (CustomObjectInputStream)whereFrom.get(DATA_HOLDER_KEY);
if (result == null) {
- result = new CustomObjectInputStream(callback);
+ result = new CustomObjectInputStream(callback, classLoaderReference);
whereFrom.put(DATA_HOLDER_KEY, result);
} else {
- result.setCallback(callback);
+ result.pushCallback(callback);
}
return result;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new ConversionException("Cannot create CustomObjectStream", e);
}
}
/**
- * Warning, this object is expensive to create (due to functionality inherited from superclass).
- * Use the static fetch() method instead, wherever possible.
- *
- * @see #getInstance(com.thoughtworks.xstream.converters.DataHolder, com.thoughtworks.xstream.core.util.CustomObjectInputStream.StreamCallback)
+ * Warning, this object is expensive to create (due to functionality inherited from superclass). Use the static
+ * fetch() method instead, wherever possible.
+ *
+ * @see #getInstance(DataHolder, StreamCallback, ClassLoaderReference)
*/
- public CustomObjectInputStream(StreamCallback callback) throws IOException, SecurityException {
+ public CustomObjectInputStream(final StreamCallback callback, final ClassLoaderReference classLoaderReference)
+ throws IOException, SecurityException {
super();
- this.callback = callback;
+ callbacks.push(callback);
+ this.classLoaderReference = classLoaderReference;
}
/**
+ * @deprecated As of 1.4.5 use {@link #CustomObjectInputStream(StreamCallback, ClassLoaderReference)}
+ */
+ @Deprecated
+ public CustomObjectInputStream(final StreamCallback callback, final ClassLoader classLoader)
+ throws IOException, SecurityException {
+ this(callback, new ClassLoaderReference(classLoader));
+ }
+
+ /**
* Allows the CustomObjectInputStream (which is expensive to create) to be reused.
*/
- public void setCallback(StreamCallback callback) {
- this.callback = callback;
+ public void pushCallback(final StreamCallback callback) {
+ callbacks.push(callback);
}
- public void defaultReadObject() throws IOException, ClassNotFoundException {
- callback.defaultReadObject();
+ public StreamCallback popCallback() {
+ return callbacks.pop();
}
- protected Object readObjectOverride() throws IOException, ClassNotFoundException {
- return callback.readFromStream();
+ public StreamCallback peekCallback() {
+ return callbacks.peek();
}
+ @Override
+ protected Class> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ final ClassLoader classLoader = classLoaderReference.getReference();
+ if (classLoader == null) {
+ return super.resolveClass(desc);
+ } else {
+ return Class.forName(desc.getName(), false, classLoader);
+ }
+ }
+
+ @Override
+ public void defaultReadObject() throws IOException {
+ peekCallback().defaultReadObject();
+ }
+
+ @Override
+ protected Object readObjectOverride() throws IOException {
+ return peekCallback().readFromStream();
+ }
+
+ @Override
+ public Object readUnshared() throws IOException, ClassNotFoundException {
+ return readObject();
+ }
+
+ @Override
public boolean readBoolean() throws IOException {
- return ((Boolean)callback.readFromStream()).booleanValue();
+ return ((Boolean)peekCallback().readFromStream()).booleanValue();
}
+ @Override
public byte readByte() throws IOException {
- return ((Byte)callback.readFromStream()).byteValue();
+ return ((Byte)peekCallback().readFromStream()).byteValue();
}
+ @Override
+ public int readUnsignedByte() throws IOException {
+ int b = ((Byte)peekCallback().readFromStream()).byteValue();
+ if (b < 0) {
+ b += Byte.MAX_VALUE;
+ }
+ return b;
+ }
+
+ @Override
public int readInt() throws IOException {
- return ((Integer)callback.readFromStream()).intValue();
+ return ((Integer)peekCallback().readFromStream()).intValue();
}
+ @Override
public char readChar() throws IOException {
- return ((Character)callback.readFromStream()).charValue();
+ return ((Character)peekCallback().readFromStream()).charValue();
}
+ @Override
public float readFloat() throws IOException {
- return ((Float)callback.readFromStream()).floatValue();
+ return ((Float)peekCallback().readFromStream()).floatValue();
}
+ @Override
public double readDouble() throws IOException {
- return ((Double)callback.readFromStream()).doubleValue();
+ return ((Double)peekCallback().readFromStream()).doubleValue();
}
+ @Override
public long readLong() throws IOException {
- return ((Long)callback.readFromStream()).longValue();
+ return ((Long)peekCallback().readFromStream()).longValue();
}
+ @Override
public short readShort() throws IOException {
- return ((Short)callback.readFromStream()).shortValue();
+ return ((Short)peekCallback().readFromStream()).shortValue();
}
+ @Override
+ public int readUnsignedShort() throws IOException {
+ int b = ((Short)peekCallback().readFromStream()).shortValue();
+ if (b < 0) {
+ b += Short.MAX_VALUE;
+ }
+ return b;
+ }
+
+ @Override
public String readUTF() throws IOException {
- return (String) callback.readFromStream();
+ return (String)peekCallback().readFromStream();
}
- public void readFully(byte[] buf) throws IOException {
+ @Override
+ public void readFully(final byte[] buf) throws IOException {
readFully(buf, 0, buf.length);
}
- public void readFully(byte[] buf, int off, int len) throws IOException {
- byte[] b = (byte[])callback.readFromStream();
+ @Override
+ public void readFully(final byte[] buf, final int off, final int len) throws IOException {
+ final byte[] b = (byte[])peekCallback().readFromStream();
System.arraycopy(b, 0, buf, off, len);
}
- public GetField readFields() throws IOException, ClassNotFoundException {
- return new CustomGetField(callback.readFieldsFromStream());
+ @Override
+ public int read() throws IOException {
+ return readUnsignedByte();
}
+ @Override
+ public int read(final byte[] buf, final int off, final int len) throws IOException {
+ final byte[] b = (byte[])peekCallback().readFromStream();
+ if (b.length != len) {
+ throw new StreamCorruptedException("Expected " + len + " bytes from stream, got " + b.length);
+ }
+ System.arraycopy(b, 0, buf, off, len);
+ return len;
+ }
+
+ @Override
+ public int read(final byte b[]) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public GetField readFields() throws IOException {
+ return new CustomGetField(peekCallback().readFieldsFromStream());
+ }
+
private class CustomGetField extends GetField {
- private Map fields;
+ private final Map fields;
- public CustomGetField(Map fields) {
+ public CustomGetField(final Map fields) {
this.fields = fields;
}
+ @Override
public ObjectStreamClass getObjectStreamClass() {
throw new UnsupportedOperationException();
}
- private Object get(String name) {
+ private Object get(final String name) {
return fields.get(name);
}
- public boolean defaulted(String name) throws IOException {
+ @Override
+ public boolean defaulted(final String name) {
return !fields.containsKey(name);
}
- public byte get(String name, byte val) throws IOException {
+ @Override
+ public byte get(final String name, final byte val) {
return defaulted(name) ? val : ((Byte)get(name)).byteValue();
}
- public char get(String name, char val) throws IOException {
+ @Override
+ public char get(final String name, final char val) {
return defaulted(name) ? val : ((Character)get(name)).charValue();
}
- public double get(String name, double val) throws IOException {
+ @Override
+ public double get(final String name, final double val) {
return defaulted(name) ? val : ((Double)get(name)).doubleValue();
}
- public float get(String name, float val) throws IOException {
+ @Override
+ public float get(final String name, final float val) {
return defaulted(name) ? val : ((Float)get(name)).floatValue();
}
- public int get(String name, int val) throws IOException {
+ @Override
+ public int get(final String name, final int val) {
return defaulted(name) ? val : ((Integer)get(name)).intValue();
}
- public long get(String name, long val) throws IOException {
+ @Override
+ public long get(final String name, final long val) {
return defaulted(name) ? val : ((Long)get(name)).longValue();
}
- public short get(String name, short val) throws IOException {
+ @Override
+ public short get(final String name, final short val) {
return defaulted(name) ? val : ((Short)get(name)).shortValue();
}
- public boolean get(String name, boolean val) throws IOException {
+ @Override
+ public boolean get(final String name, final boolean val) {
return defaulted(name) ? val : ((Boolean)get(name)).booleanValue();
}
- public Object get(String name, Object val) throws IOException {
+ @Override
+ public Object get(final String name, final Object val) {
return defaulted(name) ? val : get(name);
}
}
- public void registerValidation(ObjectInputValidation validation, int priority) throws NotActiveException, InvalidObjectException {
- callback.registerValidation(validation, priority);
+ @Override
+ public void registerValidation(final ObjectInputValidation validation, final int priority)
+ throws NotActiveException, InvalidObjectException {
+ peekCallback().registerValidation(validation, priority);
}
- /****** Unsupported methods ******/
-
- public int available() throws IOException {
- throw new UnsupportedOperationException();
- }
-
+ @Override
public void close() throws IOException {
- callback.close();
+ peekCallback().close();
}
- public int readUnsignedByte() throws IOException {
- throw new UnsupportedOperationException();
- }
+ /****** Unsupported methods ******/
- public String readLine() throws IOException {
+ @Override
+ public int available() {
throw new UnsupportedOperationException();
}
- public Object readUnshared() throws IOException, ClassNotFoundException {
+ @Override
+ public String readLine() {
throw new UnsupportedOperationException();
}
- public int readUnsignedShort() throws IOException {
+ @Override
+ public int skipBytes(final int len) {
throw new UnsupportedOperationException();
}
- public int read() throws IOException {
+ @Override
+ public long skip(final long n) {
throw new UnsupportedOperationException();
}
- public int read(byte[] buf, int off, int len) throws IOException {
+ @Override
+ public synchronized void mark(final int readlimit) {
throw new UnsupportedOperationException();
}
- public int skipBytes(int len) throws IOException {
+ @Override
+ public synchronized void reset() {
throw new UnsupportedOperationException();
}
- public int read(byte b[]) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public long skip(long n) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public void mark(int readlimit) {
- throw new UnsupportedOperationException();
- }
-
- public void reset() throws IOException {
- throw new UnsupportedOperationException();
- }
-
+ @Override
public boolean markSupported() {
return false;
}
Index: 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java
===================================================================
diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8
--- 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java (.../CustomObjectOutputStream.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d)
+++ 3rdParty_sources/xstream/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java (.../CustomObjectOutputStream.java) (revision c6b29814cfe36cd678a7cdd1d7ed0aab7d0fbec8)
@@ -1,209 +1,268 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 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 23. August 2004 by Joe Walnes
+ */
package com.thoughtworks.xstream.core.util;
-import com.thoughtworks.xstream.converters.ConversionException;
-import com.thoughtworks.xstream.converters.DataHolder;
-
import java.io.IOException;
-import java.io.ObjectOutputStream;
import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.HashMap;
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.DataHolder;
+
+
public class CustomObjectOutputStream extends ObjectOutputStream {
- private StreamCallback callback;
- private FastStack customFields = new FastStack(1);
+ private final FastStack callbacks = new FastStack(1);
+ private final FastStack customFields = new FastStack(1);
private static final String DATA_HOLDER_KEY = CustomObjectOutputStream.class.getName();
- public static synchronized CustomObjectOutputStream getInstance(DataHolder whereFrom, StreamCallback callback) {
+ public static synchronized CustomObjectOutputStream getInstance(final DataHolder whereFrom,
+ final StreamCallback callback) {
try {
- CustomObjectOutputStream result = (CustomObjectOutputStream) whereFrom.get(DATA_HOLDER_KEY);
+ CustomObjectOutputStream result = (CustomObjectOutputStream)whereFrom.get(DATA_HOLDER_KEY);
if (result == null) {
result = new CustomObjectOutputStream(callback);
whereFrom.put(DATA_HOLDER_KEY, result);
} else {
- result.setCallback(callback);
+ result.pushCallback(callback);
}
return result;
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new ConversionException("Cannot create CustomObjectStream", e);
}
}
public static interface StreamCallback {
void writeToStream(Object object) throws IOException;
- void writeFieldsToStream(Map fields) throws IOException;
+
+ void writeFieldsToStream(Map