diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1420aca
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,17 @@
+* text=auto
+
+*.css text
+*.diff text
+*.htm* text
+*.java text
+*.js text
+*.md text
+*.patch text
+*.txt text
+*.xml text
+
+*.gif binary
+*.jpg binary
+*.png binary
+*.psp binary
+*.vsd binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0b870e1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.*
+target
+*.iml
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b4b4a4d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: java
+jdk:
+ - oraclejdk8
+ - oraclejdk7
+ - openjdk6
+install: true
+script: "mvn -V -B -e clean package"
+cache:
+ directories:
+ - $HOME/.m2
diff --git a/BUILD.txt b/BUILD.txt
index 7ccabf6..5547b4d 100644
--- a/BUILD.txt
+++ b/BUILD.txt
@@ -1,4 +1,5 @@
-For Java 5 or higher build with Maven 2.2 or 3
+For Java 6 or higher build with Maven 3.2.5 or higher
+For Java 5 build with Maven 3.0.5
For Java 1.4 build with Maven 2.0.11
Before building:
@@ -9,7 +10,8 @@
Before deploying:
-copy settings-template.xml to ~/.m2/settings.xml adding your Codehaus DAV username and passwords.
+copy settings-template.xml to ~/.m2/settings.xml adding your Sonatype OSSRH
+username and passwords.
To deploy (optionally adding sources and javadoc jars):
mvn deploy
diff --git a/LICENSE.txt b/LICENSE.txt
index fa11e38..a9cd276 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,7 +1,7 @@
(BSD Style License)
Copyright (c) 2003-2006, Joe Walnes
-Copyright (c) 2006-2011, XStream Committers
+Copyright (c) 2006-2015, XStream Committers
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..999ac08
--- /dev/null
+++ b/README.md
@@ -0,0 +1,27 @@
+[![Build Status](https://travis-ci.org/x-stream/xstream.svg?branch=v-1.4.x)](https://travis-ci.org/x-stream/xstream)
+----
+# XStream
+_Java to XML Serialization, and back again_
+
+## Binaries
+All binary artifacts are bundled in the -bin archive. It includes
+the XStream jars and any other library used at build time, or
+optional runtime extras. Xpp3 is recommend for use as it will
+greatly improve the performance of XStream.
+
+## Documentation
+Documentation can be found at [GitHub](http://x-stream.github.io). This
+includes:
+* Introduction and tutorial
+* JavaDoc
+* Change log
+* Frequently asked questions
+
+## Source
+The complete source for XStream is bundled in the -src archive. This includes:
+* Main API [xstream/src/java]
+* Unit tests [xstream/src/test]
+* Maven build files [pom.xml]
+* Hibernate module [xstream-hibernate]
+* Web site [xstream-distribution]
+
diff --git a/README.txt b/README.txt
index 0639a48..01b7797 100644
--- a/README.txt
+++ b/README.txt
@@ -8,14 +8,15 @@
--[ Binaries ]-----------------------------------------------
-All binary artifacts are in the 'lib' directory. These include the
-xstream jars and any other library used at build time,
-or optional runtime extras. kXML2 is recommend for use as it will
+All binary artifacts are bundled in the -bin archive. It includes
+the XStream jars and any other library used at build time, or
+optional runtime extras. Xpp3 is recommend for use as it will
greatly improve the performance of XStream.
--[ Documentation ]------------------------------------------
-Documentation can be found in docs/index.html. This includes:
+Documentation can be found at http://x-stream.github.io. This
+includes:
* Introduction and tutorial
* JavaDoc
* Change log
@@ -23,15 +24,17 @@
--[ Source ]-------------------------------------------------
-The complete source for XStream is bundled. This includes:
- * Main API [src/java]
- * Unit tests [src/test]
+The complete source for XStream is bundled in the -src archive.
+This includes:
+ * Main API [xstream/src/java]
+ * Unit tests [xstream/src/test]
* Maven build files [pom.xml]
- * Dependencies [lib]
+ * Hibernate module [xstream-hibernate]
+ * Web site [xstream-distribution]
-------------------------------------------------------------
--XStream Ccommitters
+- XStream Committers
- http://xstream.codehaus.org/
+ http://x-stream.github.io/
diff --git a/pom.xml b/pom.xml
index e77fd16..8224a37 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@
4.0.0
-
- org.codehaus
- codehaus-parent
- 3
-
-
com.thoughtworks.xstream
xstream-parent
pom
- 1.4.8
+ 1.4.9
XStream Parent
+ http://x-stream.github.io
XStream is a serialization library from Java objects to XML and back.
@@ -29,8 +24,16 @@
2004
XStream
- http://xstream.codehaus.org
+ http://x-stream.github.io
+
+
+
+ xstream
+ XStream Committers
+ http://x-stream.github.io/team.html
+
+
@@ -53,32 +56,18 @@
- jdk15-ge
+
+ jdk16-ge
- [1.5,)
+ [1.6,)
-
-
-
- org.apache.felix
- maven-bundle-plugin
-
-
- bundle-manifest
- process-classes
-
- manifest
-
-
-
-
-
-
-
+ xstream-jmh
+ xstream-distribution
+
jdk15
1.5
@@ -97,6 +86,7 @@
1.3
1.3
+ 1.0-beta-1
http://docs.oracle.com/javase/1.4.2/docs/api/
1.8.0.10
@@ -113,6 +103,10 @@
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
org.apache.maven.plugins
maven-enforcer-plugin
@@ -138,6 +132,57 @@
+ osgi
+
+ [1.6,)
+
+ profiles/osgi
+
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+
+
+ bundle-manifest
+ process-classes
+
+ manifest
+
+
+
+
+
+ ${bundle.export.package}
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ default-jar
+
+ jar
+
+
+
+ ${project.build.directory}/OSGi/MANIFEST.MF
+
+
+
+
+
+
+
+
+ ${project.groupId}.*;-noimport:=true
+
+
+
xstream-release
[1.8,1.9)
@@ -166,28 +211,70 @@
xstream
xstream-hibernate
xstream-benchmark
- xstream-distribution
BSD style
- http://xstream.codehaus.org/license.html
+ http://x-stream.github.io/license.html
repo
+
+ github
+ https://github.com/x-stream/xstream/issues/
+
+
+ Travis
+ https://travis-ci.org/x-stream/xstream
+
+
+
+ XStream Users List
+ xstream-user+subscribe@googlegroups.com
+ xstream-user+unsubscribe@googlegroups.com
+ xstream-user@googlegroups.com
+ https://groups.google.com/forum/#!forum/xstream-user
+
+ http://news.gmane.org/gmane.comp.java.xstream.user
+ http://markmail.org/search/list:org.codehaus.xstream.user
+
+
+
+ XStream Notifications List
+ xstream-notifications+subscribe@googlegroups.com
+ xstream-notifications+unsubscribe@googlegroups.com
+ xstream-notifications@googlegroups.com
+ https://groups.google.com/forum/#!forum/xstream-notifications
+
+ http://news.gmane.org/gmane.comp.java.xstream.scm
+
+
+
+ Former (pre-2015-06) Development List
+ http://news.gmane.org/gmane.comp.java.xstream.dev
+
+ http://markmail.org/search/list:org.codehaus.xstream.dev
+
+
+
+ Former (pre-2015-06) Announcements List
+ http://markmail.org/search/list:org.codehaus.xstream.announce
+
+
+
com.thoughtworks.xstream
xstream
- 1.4.8
+ 1.4.9
com.thoughtworks.xstream
xstream
- 1.4.8
+ 1.4.9
tests
test-jar
test
@@ -195,31 +282,43 @@
com.thoughtworks.xstream
xstream
- 1.4.8
+ 1.4.9
javadoc
provided
com.thoughtworks.xstream
xstream-hibernate
- 1.4.8
+ 1.4.9
com.thoughtworks.xstream
xstream-hibernate
- 1.4.8
+ 1.4.9
javadoc
provided
com.thoughtworks.xstream
- xstream-benchmark
- 1.4.8
+ xstream-jmh
+ 1.4.9
+
+
+ com.thoughtworks.xstream
+ xstream-jmh
+ 1.4.9
+ javadoc
+ provided
com.thoughtworks.xstream
xstream-benchmark
- 1.4.8
+ 1.4.9
+
+
+ com.thoughtworks.xstream
+ xstream-benchmark
+ 1.4.9
javadoc
provided
@@ -387,6 +486,13 @@
+ javax.activation
+ activation
+ ${version.javax.activation}
+ provided
+
+
+
org.hibernate
hibernate-core
${version.org.hibernate.core}
@@ -420,6 +526,18 @@
runtime
+
+ org.openjdk.jmh
+ jmh-core
+ ${version.org.openjdk.jmh}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${version.org.openjdk.jmh}
+ provided
+
+
junit
@@ -427,7 +545,6 @@
${version.junit}
test
-
jmock
jmock
@@ -575,9 +692,10 @@
maven-release-plugin
${version.plugin.maven.release}
+ forked-path
deploy
true
-
+ false
-Pxstream-release
@@ -739,25 +857,30 @@
-
-
- codehaus.org
- Codehaus XStream Site
- dav:https://dav.codehaus.org/xstream
-
+
+ ossrh-staging
+ http://oss.sonatype.org/service/local/staging/deploy/maven2
+
+
+ ossrh-snapshots
+ http://oss.sonatype.org/content/repositories/snapshots
+
+
- scm:svn:http://svn.codehaus.org/xstream/tags/XSTREAM_1_4_8
- scm:svn:https://svn.codehaus.org/xstream/tags/XSTREAM_1_4_8
- http://fisheye.codehaus.org/browse/xstream/tags/XSTREAM_1_4_8
+ http://github.com/x-stream/xstream
+ scm:git:https://github.com/x-stream/xstream.git
+ scm:git:https://github.com/x-stream/xstream.git
+ v-1.4.x
+ UTF-8
+
1.5
1.5
[1.4,)
@@ -794,6 +917,7 @@
1.6.1
2.2.8
3.12.1.GA
+ 1.1.1
1.0.1
1.6
3.8.1
@@ -805,6 +929,7 @@
1.1.3
2.0.5
20080701
+ 1.11.1
1.6.1
2.0.8
1.2.0
diff --git a/settings-template.xml b/settings-template.xml
index b67ae92..ffea412 100644
--- a/settings-template.xml
+++ b/settings-template.xml
@@ -1,6 +1,6 @@
@@ -310,9 +315,11 @@
**/Lambda**
+ **/extended/PathConverter*
**/Lambda**
+ **/acceptance/Extended17TypesTest*
**/extended/*17Test*
@@ -381,6 +388,7 @@
**/basic/UUID*
**/core/util/Types*
**/extended/*15*
+ **/extended/PathConverter*
**/io/xml/JDom2*
@@ -393,6 +401,7 @@
**/io/xml/JDom2*Test*
**/acceptance/Basic15TypesTest*
**/acceptance/Concurrent15TypesTest*
+ **/acceptance/Extended17TypesTest*
@@ -429,4 +438,8 @@
+
+ !com.thoughtworks.xstream.core.util,com.thoughtworks.xstream.*;-noimport:=true
+
+
diff --git a/xstream/profiles/osgi b/xstream/profiles/osgi
new file mode 100644
index 0000000..e69de29
diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java
index 40f83d2..a2b7feb 100644
--- a/xstream/src/java/com/thoughtworks/xstream/XStream.java
+++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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;
@@ -343,7 +343,7 @@
* 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() {
@@ -370,7 +370,7 @@
* 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
*/
@@ -600,8 +600,9 @@
mapper = new LocalConversionMapper(mapper);
mapper = new ImmutableTypesMapper(mapper);
if (JVM.is18()) {
- mapper = buildMapperDynamically("com.thoughtworks.xstream.mapper.LambdaMapper", new Class[]{Mapper.class},
- new Object[]{mapper});
+ mapper =
+ buildMapperDynamically("com.thoughtworks.xstream.mapper.LambdaMapper", new Class[]{Mapper.class},
+ new Object[]{mapper});
}
mapper = new SecurityMapper(mapper);
if (JVM.is15()) {
@@ -734,6 +735,12 @@
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"));
+
+ // only available in Java 5 when javax.activation:activation is available on CP
+ Class type = JVM.loadClassForName("javax.activation.ActivationDataFlavor");
+ if (type != null) {
+ alias("activation-data-flavor", type);
+ }
}
if (JVM.isSQLAvailable()) {
@@ -763,6 +770,11 @@
alias("string-builder", JVM.loadClassForName("java.lang.StringBuilder"));
alias("uuid", JVM.loadClassForName("java.util.UUID"));
}
+
+ if (JVM.is17()) {
+ aliasType("path", JVM.loadClassForName("java.nio.file.Path"));
+ }
+
if (JVM.loadClassForName("java.lang.invoke.SerializedLambda") != null) {
aliasDynamically("serialized-lambda", "java.lang.invoke.SerializedLambda");
}
@@ -893,6 +905,14 @@
"com.thoughtworks.xstream.converters.basic.UUIDConverter", PRIORITY_NORMAL,
null, null);
}
+ if (JVM.loadClassForName("javax.activation.ActivationDataFlavor") != null) {
+ registerConverterDynamically("com.thoughtworks.xstream.converters.extended.ActivationDataFlavorConverter",
+ PRIORITY_NORMAL, null, null);
+ }
+ if (JVM.is17()) {
+ registerConverterDynamically("com.thoughtworks.xstream.converters.extended.PathConverter",
+ PRIORITY_NORMAL, null, null);
+ }
if (JVM.is18()) {
registerConverterDynamically("com.thoughtworks.xstream.converters.reflection.LambdaConverter",
PRIORITY_NORMAL, new Class[]{Mapper.class, ReflectionProvider.class, ClassLoaderReference.class},
@@ -929,52 +949,56 @@
}
// primitives are always immutable
- addImmutableType(boolean.class);
- addImmutableType(Boolean.class);
- addImmutableType(byte.class);
- addImmutableType(Byte.class);
- addImmutableType(char.class);
- addImmutableType(Character.class);
- addImmutableType(double.class);
- addImmutableType(Double.class);
- addImmutableType(float.class);
- addImmutableType(Float.class);
- addImmutableType(int.class);
- addImmutableType(Integer.class);
- addImmutableType(long.class);
- addImmutableType(Long.class);
- addImmutableType(short.class);
- addImmutableType(Short.class);
+ addImmutableType(boolean.class, false);
+ addImmutableType(Boolean.class, false);
+ addImmutableType(byte.class, false);
+ addImmutableType(Byte.class, false);
+ addImmutableType(char.class, false);
+ addImmutableType(Character.class, false);
+ addImmutableType(double.class, false);
+ addImmutableType(Double.class, false);
+ addImmutableType(float.class, false);
+ addImmutableType(Float.class, false);
+ addImmutableType(int.class, false);
+ addImmutableType(Integer.class, false);
+ addImmutableType(long.class, false);
+ addImmutableType(Long.class, false);
+ addImmutableType(short.class, false);
+ addImmutableType(Short.class, false);
// additional types
- addImmutableType(Mapper.Null.class);
- addImmutableType(BigDecimal.class);
- addImmutableType(BigInteger.class);
- addImmutableType(String.class);
- addImmutableType(URI.class);
- addImmutableType(URL.class);
- addImmutableType(File.class);
- addImmutableType(Class.class);
-
- addImmutableType(Collections.EMPTY_LIST.getClass());
- addImmutableType(Collections.EMPTY_SET.getClass());
- addImmutableType(Collections.EMPTY_MAP.getClass());
+ addImmutableType(Mapper.Null.class, false);
+ addImmutableType(BigDecimal.class, false);
+ addImmutableType(BigInteger.class, false);
+ addImmutableType(String.class, false);
+ addImmutableType(URL.class, false);
+ addImmutableType(File.class, false);
+ addImmutableType(Class.class, false);
if (JVM.isAWTAvailable()) {
- addImmutableTypeDynamically("java.awt.font.TextAttribute");
+ addImmutableTypeDynamically("java.awt.font.TextAttribute", false);
}
if (JVM.is14()) {
// late bound types - allows XStream to be compiled on earlier JDKs
- addImmutableTypeDynamically("java.nio.charset.Charset");
- addImmutableTypeDynamically("java.util.Currency");
- }
- }
-
- private void addImmutableTypeDynamically(String className) {
+ addImmutableTypeDynamically("java.nio.charset.Charset", true);
+ addImmutableTypeDynamically("java.util.Currency", true);
+ }
+
+ if (JVM.is15()) {
+ addImmutableTypeDynamically("java.util.UUID", true);
+ }
+
+ addImmutableType(URI.class, true);
+ addImmutableType(Collections.EMPTY_LIST.getClass(), true);
+ addImmutableType(Collections.EMPTY_SET.getClass(), true);
+ addImmutableType(Collections.EMPTY_MAP.getClass(), true);
+ }
+
+ private void addImmutableTypeDynamically(String className, boolean isReferenceable) {
Class type = JVM.loadClassForName(className);
if (type != null) {
- addImmutableType(type);
+ addImmutableType(type, isReferenceable);
}
}
@@ -984,7 +1008,7 @@
/**
* Serialize an object to a pretty-printed XML String.
- *
+ *
* @throws XStreamException if the object cannot be serialized
*/
public String toXML(Object obj) {
@@ -1025,7 +1049,7 @@
/**
* 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) {
@@ -1045,7 +1069,7 @@
/**
* Deserialize an object from an XML String.
- *
+ *
* @throws XStreamException if the object cannot be deserialized
*/
public Object fromXML(String xml) {
@@ -1054,7 +1078,7 @@
/**
* Deserialize an object from an XML Reader.
- *
+ *
* @throws XStreamException if the object cannot be deserialized
*/
public Object fromXML(Reader reader) {
@@ -1063,7 +1087,7 @@
/**
* Deserialize an object from an XML InputStream.
- *
+ *
* @throws XStreamException if the object cannot be deserialized
*/
public Object fromXML(InputStream input) {
@@ -1171,7 +1195,7 @@
/**
* Deserialize an object from a hierarchical data structure (such as XML).
- *
+ *
* @throws XStreamException if the object cannot be deserialized
*/
public Object unmarshal(HierarchicalStreamReader reader) {
@@ -1216,7 +1240,7 @@
/**
* Alias a Class to a shorter name to be used in XML elements.
- *
+ *
* @param name Short name
* @param type Type to be aliased
* @throws InitializationException if no {@link ClassAliasingMapper} is available
@@ -1250,7 +1274,7 @@
/**
* Alias a Class to a shorter name to be used in XML elements.
- *
+ *
* @param name Short name
* @param type Type to be aliased
* @param defaultImplementation Default implementation of type to use if no other specified.
@@ -1264,7 +1288,7 @@
/**
* 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
@@ -1282,7 +1306,7 @@
/**
* 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
@@ -1299,7 +1323,7 @@
/**
* 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
@@ -1335,7 +1359,7 @@
/**
* 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
@@ -1349,7 +1373,7 @@
/**
* 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
@@ -1366,7 +1390,7 @@
/**
* 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
@@ -1383,7 +1407,7 @@
/**
* 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
@@ -1416,18 +1440,38 @@
}
/**
- * Add immutable types. The value of the instances of these types will always be written
- * into the stream even if they appear multiple times.
- *
+ * Add immutable types. The value of the instances of these types will always be written into the stream even if
+ * they appear multiple times. However, references are still supported at deserialization time.
+ *
* @throws InitializationException if no {@link ImmutableTypesMapper} is available
+ * @deprecated As of 1.4.9 use {@link #addImmutableType(Class, boolean)}
*/
public void addImmutableType(Class type) {
+ addImmutableType(type, true);
+ }
+
+ /**
+ * Add immutable types. The value of the instances of these types will always be written into the stream even if
+ * they appear multiple times.
+ *
+ * Note, while a reference-keeping marshaller will not write references for immutable types into the stream, a
+ * reference-keeping unmarshaller can still support such references in the stream for compatibility reasons at the
+ * expense of memory consumption. Therefore declare these types only as referenceable if your already persisted
+ * streams do contain such references. Otherwise you may waste a lot of memory during deserialization.
+ *
+ *
+ * @param isReferenceable true
if support at deserialization time is required for compatibility at the
+ * cost of a higher memory footprint, false
otherwise
+ * @throws InitializationException if no {@link ImmutableTypesMapper} is available
+ * @since 1.4.9
+ */
+ public void addImmutableType(final Class type, final boolean isReferenceable) {
if (immutableTypesMapper == null) {
throw new com.thoughtworks.xstream.InitializationException("No "
+ ImmutableTypesMapper.class.getName()
+ " available");
}
- immutableTypesMapper.addImmutableType(type);
+ immutableTypesMapper.addImmutableType(type, isReferenceable);
}
public void registerConverter(Converter converter) {
@@ -1453,7 +1497,7 @@
/**
* 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
@@ -1470,7 +1514,7 @@
/**
* 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
@@ -1495,7 +1539,7 @@
/**
* Retrieve the {@link ReflectionProvider} in use.
- *
+ *
* @return the mapper
* @since 1.2.1
*/
@@ -1551,7 +1595,7 @@
/**
* Adds a default implicit collection which is used for any unmapped XML tag.
- *
+ *
* @param ownerType class owning the implicit collection
* @param fieldName name of the field in the ownerType. This field must be a concrete
* collection type or matching the default implementation type of the collection
@@ -1563,7 +1607,7 @@
/**
* Adds implicit collection which is used for all items of the given itemType.
- *
+ *
* @param ownerType class owning the implicit collection
* @param fieldName name of the field in the ownerType. This field must be a concrete
* collection type or matching the default implementation type of the collection
@@ -1594,7 +1638,7 @@
/**
* Adds an implicit array.
- *
+ *
* @param ownerType class owning the implicit array
* @param fieldName name of the array field
* @since 1.4
@@ -1634,7 +1678,7 @@
/**
* 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
@@ -1649,7 +1693,7 @@
/**
* 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
@@ -1673,7 +1717,7 @@
* 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() {
@@ -1776,7 +1820,7 @@
* be incomplete.
*
* Example
- *
+ *
*
* ObjectOutputStream out = xstream.createObjectOutputStream(aWriter, "things");
* out.writeInt(123);
@@ -1784,7 +1828,7 @@
* out.writeObject(someObject)
* out.close();
*
- *
+ *
* @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)
@@ -1908,7 +1952,7 @@
/**
* Retrieve the ClassLoader XStream uses to load classes.
- *
+ *
* @since 1.1.1
*/
public ClassLoader getClassLoader() {
@@ -1945,7 +1989,7 @@
/**
* Ignore all unknown elements.
- *
+ *
* @since 1.4.5
*/
public void ignoreUnknownElements() {
@@ -1954,7 +1998,7 @@
/**
* Add pattern for unknown element names to ignore.
- *
+ *
* @param pattern the name pattern as regular expression
* @since 1.4.5
*/
@@ -1964,7 +2008,7 @@
/**
* Add pattern for unknown element names to ignore.
- *
+ *
* @param pattern the name pattern as regular expression
* @since 1.4.5
*/
@@ -1979,7 +2023,7 @@
/**
* Process the annotations of the given types and configure the XStream.
- *
+ *
* @param types the types with XStream annotations
* @since 1.3
*/
@@ -2025,7 +2069,7 @@
* 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
*/
@@ -2037,7 +2081,7 @@
/**
* Add security permission for explicit types by name.
- *
+ *
* @param names the type names to allow
* @since 1.4.7
*/
@@ -2047,7 +2091,7 @@
/**
* Add security permission for explicit types.
- *
+ *
* @param types the types to allow
* @since 1.4.7
*/
@@ -2057,7 +2101,7 @@
/**
* Add security permission for a type hierarchy.
- *
+ *
* @param type the base type to allow
* @since 1.4.7
*/
@@ -2067,7 +2111,7 @@
/**
* 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
*/
@@ -2077,7 +2121,7 @@
/**
* 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
*/
@@ -2095,7 +2139,7 @@
* *: 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
*/
@@ -2105,7 +2149,7 @@
/**
* Add security permission denying another one.
- *
+ *
* @param permission the permission to deny
* @since 1.4.7
*/
@@ -2115,7 +2159,7 @@
/**
* Add security permission forbidding explicit types by name.
- *
+ *
* @param names the type names to forbid
* @since 1.4.7
*/
@@ -2125,7 +2169,7 @@
/**
* Add security permission forbidding explicit types.
- *
+ *
* @param types the types to forbid
* @since 1.4.7
*/
@@ -2135,7 +2179,7 @@
/**
* Add security permission forbidding a type hierarchy.
- *
+ *
* @param type the base type to forbid
* @since 1.4.7
*/
@@ -2145,7 +2189,7 @@
/**
* 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
*/
@@ -2155,7 +2199,7 @@
/**
* 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
*/
@@ -2173,7 +2217,7 @@
* *: 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
*/
diff --git a/xstream/src/java/com/thoughtworks/xstream/XStreamException.java b/xstream/src/java/com/thoughtworks/xstream/XStreamException.java
index 002a605..b6fdcdf 100644
--- a/xstream/src/java/com/thoughtworks/xstream/XStreamException.java
+++ b/xstream/src/java/com/thoughtworks/xstream/XStreamException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 XStream Committers.
+ * Copyright (C) 2007, 2008, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,15 +14,13 @@
/**
- * Base exception for all thrown exceptions with XStream. JDK 1.3 friendly cause handling.
+ * Base exception for all thrown exceptions with XStream.
*
* @author Joe Walnes
* @author Jörg Schaible
* @since 1.3
*/
public class XStreamException extends BaseException {
-
- private Throwable cause;
/**
* Default constructor.
@@ -62,12 +60,6 @@
* @since 1.3
*/
public XStreamException(String message, Throwable cause) {
- super(message + (cause == null ? "" : " : " + cause.getMessage()));
- this.cause = cause;
+ super(message, cause);
}
-
- public Throwable getCause() {
- return cause;
- }
-
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/XStreamer.java b/xstream/src/java/com/thoughtworks/xstream/XStreamer.java
index 6d40890..ebf41a8 100644
--- a/xstream/src/java/com/thoughtworks/xstream/XStreamer.java
+++ b/xstream/src/java/com/thoughtworks/xstream/XStreamer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2014, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,7 +21,6 @@
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;
@@ -33,6 +32,7 @@
import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.StreamException;
import com.thoughtworks.xstream.io.naming.NameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.mapper.Mapper;
@@ -85,7 +85,7 @@
} catch (final ObjectStreamException e) {
throw e;
} catch (final IOException e) {
- throw new ConversionException("Unexpected IO error from a StringWriter", e);
+ throw new StreamException("Unexpected IO error from a StringWriter", e);
}
return writer.toString();
}
@@ -135,7 +135,7 @@
} catch (final ObjectStreamException e) {
throw e;
} catch (final IOException e) {
- throw new ConversionException("Unexpected IO error from a StringReader", e);
+ throw new StreamException("Unexpected IO error from a StringReader", e);
}
}
@@ -157,7 +157,7 @@
} catch (final ObjectStreamException e) {
throw e;
} catch (final IOException e) {
- throw new ConversionException("Unexpected IO error from a StringReader", e);
+ throw new StreamException("Unexpected IO error from a StringReader", e);
}
}
@@ -179,7 +179,7 @@
} catch (final ObjectStreamException e) {
throw e;
} catch (final IOException e) {
- throw new ConversionException("Unexpected IO error from a StringReader", e);
+ throw new StreamException("Unexpected IO error from a StringReader", e);
}
}
@@ -202,7 +202,7 @@
} catch (final ObjectStreamException e) {
throw e;
} catch (final IOException e) {
- throw new ConversionException("Unexpected IO error from a StringReader", e);
+ throw new StreamException("Unexpected IO error from a StringReader", e);
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/annotations/Annotations.java b/xstream/src/java/com/thoughtworks/xstream/annotations/Annotations.java
old file mode 100644
new file mode 100755
index 1e48132..1e48132 100755
diff --git a/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamAlias.java b/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamAlias.java
old file mode 100644
new file mode 100755
index 88d3c4c..88d3c4c 100755
diff --git a/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamContainedType.java b/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamContainedType.java
old file mode 100644
new file mode 100755
index 6f2bc9e..6f2bc9e 100755
diff --git a/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamConverter.java b/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamConverter.java
index c0ef961..87a2c67 100644
--- a/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/annotations/XStreamConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -106,4 +106,12 @@
double[] doubles() default {};
boolean[] booleans() default {};
+
+ /**
+ * Provide null types as arguments for the converter's constructor arguments.
+ *
+ * @return the types provided as null values
+ * @since 1.4.9
+ */
+ Class>[] nulls() default {};
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/ConversionException.java b/xstream/src/java/com/thoughtworks/xstream/converters/ConversionException.java
index cd920be..283d5bd 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/ConversionException.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/ConversionException.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2003, 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,12 +10,6 @@
* Created on 26. September 2003 by Joe Walnes
*/
package com.thoughtworks.xstream.converters;
-
-import com.thoughtworks.xstream.XStreamException;
-import com.thoughtworks.xstream.core.util.OrderRetainingMap;
-
-import java.util.Iterator;
-import java.util.Map;
/**
* Thrown by {@link Converter} implementations when they cannot convert an object
@@ -29,20 +23,10 @@
*
* @see ErrorWriter
*/
-public class ConversionException extends XStreamException implements ErrorWriter {
-
- private static final String SEPARATOR = "\n-------------------------------";
- private Map stuff = new OrderRetainingMap();
+public class ConversionException extends ErrorWritingException {
public ConversionException(String msg, Throwable cause) {
super(msg, cause);
- if (msg != null) {
- add("message", msg);
- }
- if (cause != null) {
- add("cause-exception", cause.getClass().getName());
- add("cause-message", cause instanceof ConversionException ? ((ConversionException)cause).getShortMessage() : cause.getMessage());
- }
}
public ConversionException(String msg) {
@@ -50,61 +34,6 @@
}
public ConversionException(Throwable cause) {
- this(cause.getMessage(), cause);
- }
-
- public String get(String errorKey) {
- return (String) stuff.get(errorKey);
- }
-
- public void add(String name, String information) {
- String key = name;
- int i = 0;
- while (stuff.containsKey(key)) {
- String value = (String)stuff.get(key);
- if (information.equals(value))
- return;
- key = name + "[" + ++i +"]";
- }
- stuff.put(key, information);
- }
-
- public void set(String name, 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 +"]";
- }
- }
-
- public Iterator keys() {
- return stuff.keySet().iterator();
- }
-
- public String getMessage() {
- StringBuffer result = new StringBuffer();
- if (super.getMessage() != null) {
- result.append(super.getMessage());
- }
- if (!result.toString().endsWith(SEPARATOR)) {
- result.append("\n---- Debugging information ----");
- }
- for (Iterator iterator = keys(); iterator.hasNext();) {
- String k = (String) iterator.next();
- String v = get(k);
- result.append('\n').append(k);
- result.append(" ".substring(Math.min(20, k.length())));
- result.append(": ").append(v);
- }
- result.append(SEPARATOR);
- return result.toString();
- }
-
- public String getShortMessage() {
- return super.getMessage();
+ super(cause);
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/ErrorWritingException.java b/xstream/src/java/com/thoughtworks/xstream/converters/ErrorWritingException.java
new file mode 100644
index 0000000..e0eed51
--- /dev/null
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/ErrorWritingException.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2003, 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2016 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. February 2016 by Joerg Schaible, factored out of ConversionException.
+ */
+package com.thoughtworks.xstream.converters;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.core.util.OrderRetainingMap;
+
+
+/**
+ * Abstract base class for exceptions supporting an ErrorWriter. It can be passed around to things accepting an
+ * ErrorWriter to add diagnostics.
+ *
+ * @author Jörg Schaible
+ * @see ErrorWriter
+ * @since 1.4.9
+ */
+public abstract class ErrorWritingException extends XStreamException implements ErrorWriter {
+
+ private static final String SEPARATOR = "\n-------------------------------";
+ private final Map stuff = new OrderRetainingMap();
+
+ /**
+ * Constructs a ErrorWritingException.
+ *
+ * @param message the error message
+ * @since 1.4.9
+ */
+ public ErrorWritingException(String message) {
+ super(message);
+ addData(message, null);
+ }
+
+ /**
+ * Constructs a ErrorWritingException.
+ *
+ * @param cause the causing exception
+ * @since 1.4.9
+ */
+ public ErrorWritingException(Throwable cause) {
+ super(cause);
+ addData(null, cause);
+ }
+
+ /**
+ * Constructs a ErrorWritingException.
+ *
+ * @param message the error message
+ * @param cause the causing exception
+ * @since 1.4.9
+ */
+ public ErrorWritingException(String message, Throwable cause) {
+ super(message, cause);
+ addData(message, cause);
+ }
+
+ private void addData(String msg, Throwable cause) {
+ if (msg != null) {
+ add("message", msg);
+ }
+ if (cause != null) {
+ add("cause-exception", cause.getClass().getName());
+ add("cause-message", cause instanceof ErrorWritingException ? ((ErrorWritingException)cause).getShortMessage() : cause.getMessage());
+ }
+ }
+
+ public String get(String errorKey) {
+ return (String) stuff.get(errorKey);
+ }
+
+ public void add(String name, String information) {
+ String key = name;
+ int i = 0;
+ while (stuff.containsKey(key)) {
+ String value = (String)stuff.get(key);
+ if (information.equals(value))
+ return;
+ key = name + "[" + ++i +"]";
+ }
+ stuff.put(key, information);
+ }
+
+ public void set(String name, 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 +"]";
+ }
+ }
+
+ public Iterator keys() {
+ return stuff.keySet().iterator();
+ }
+
+ public String getMessage() {
+ StringBuffer result = new StringBuffer();
+ if (super.getMessage() != null) {
+ result.append(super.getMessage());
+ }
+ if (!result.toString().endsWith(SEPARATOR)) {
+ result.append("\n---- Debugging information ----");
+ }
+ for (Iterator iterator = keys(); iterator.hasNext();) {
+ String k = (String) iterator.next();
+ String v = get(k);
+ result.append('\n').append(k);
+ result.append(" ".substring(Math.min(20, k.length())));
+ result.append(": ").append(v);
+ }
+ result.append(SEPARATOR);
+ return result.toString();
+ }
+
+ public String getShortMessage() {
+ return super.getMessage();
+ }
+
+}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/basic/DateConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/basic/DateConverter.java
index ad111ed..5f0bffa 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/basic/DateConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/basic/DateConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2003, 2004 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -227,7 +227,9 @@
}
}
// no dateFormats left to try
- throw new ConversionException("Cannot parse date " + str);
+ ConversionException exception = new ConversionException("Cannot parse date");
+ exception.add("date", str);
+ throw exception;
}
public String toString(Object obj) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/collections/AbstractCollectionConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/collections/AbstractCollectionConverter.java
index 0909417..a7e46d1 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/collections/AbstractCollectionConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/collections/AbstractCollectionConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2003, 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -13,8 +13,10 @@
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.ErrorWritingException;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@@ -72,13 +74,17 @@
}
protected Object createCollection(Class type) {
+ ErrorWritingException ex = null;
Class defaultType = mapper().defaultImplementationOf(type);
try {
return defaultType.newInstance();
} catch (InstantiationException e) {
- throw new ConversionException("Cannot instantiate " + defaultType.getName(), e);
+ ex = new ConversionException("Cannot instantiate default collection", e);
} catch (IllegalAccessException e) {
- throw new ConversionException("Cannot instantiate " + defaultType.getName(), e);
+ ex = new ObjectAccessException("Cannot instantiate default collection", e);
}
+ ex.add("collection-type", type.getName());
+ ex.add("default-type", defaultType.getName());
+ throw ex;
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeMapConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeMapConverter.java
index a79f4f5..30a5c51 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeMapConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeMapConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2010, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2010, 2011, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,9 +11,9 @@
*/
package com.thoughtworks.xstream.converters.collections;
-import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.core.util.Fields;
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
@@ -128,7 +128,7 @@
result.putAll(sortedMap); // will use comparator for already sorted map
}
} catch (final IllegalAccessException e) {
- throw new ConversionException("Cannot set comparator of TreeMap", e);
+ throw new ObjectAccessException("Cannot set comparator of TreeMap", e);
}
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeSetConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeSetConverter.java
index 7e9e630..d22815c 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeSetConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/collections/TreeSetConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2010, 2011, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2010, 2011, 2013, 2014, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,9 +11,9 @@
*/
package com.thoughtworks.xstream.converters.collections;
-import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.core.util.Fields;
import com.thoughtworks.xstream.core.util.PresortedSet;
@@ -99,7 +99,7 @@
try {
backingMap = sortedMapField.get(possibleResult);
} catch (IllegalAccessException e) {
- throw new ConversionException("Cannot get backing map of TreeSet", e);
+ throw new ObjectAccessException("Cannot get backing map of TreeSet", e);
}
if (backingMap instanceof TreeMap) {
treeMap = (TreeMap)backingMap;
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/enums/EnumToStringConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/enums/EnumToStringConverter.java
index 90fea84..6a4e048 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/enums/EnumToStringConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/enums/EnumToStringConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 XStream Committers.
+ * Copyright (C) 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -13,9 +13,9 @@
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
+import com.thoughtworks.xstream.InitializationException;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
@@ -53,7 +53,7 @@
Map strings = new HashMap(values.size());
for (T value : values) {
if (strings.put(value.toString(), value) != null) {
- throw new IllegalArgumentException("Enum type "
+ throw new InitializationException("Enum type "
+ type.getName()
+ " does not have unique string representations for its values");
}
@@ -63,7 +63,7 @@
private static void checkType(Class type) {
if (!Enum.class.isAssignableFrom(type) && type != Enum.class) {
- throw new IllegalArgumentException("Converter can only handle enum types");
+ throw new InitializationException("Converter can only handle enum types");
}
}
@@ -94,11 +94,10 @@
}
T result = strings.get(str);
if (result == null) {
- throw new ConversionException("Invalid string representation for enum type "
- + enumType.getName()
- + ": <"
- + str
- + ">");
+ ConversionException exception = new ConversionException("Invalid string representation for enum type");
+ exception.add("enum-type", enumType.getName());
+ exception.add("enum-string", str);
+ throw exception;
}
return result;
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/ActivationDataFlavorConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ActivationDataFlavorConverter.java
new file mode 100644
index 0000000..4e20cb3
--- /dev/null
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ActivationDataFlavorConverter.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 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.06.2015 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.extended;
+
+import javax.activation.ActivationDataFlavor;
+
+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;
+
+
+/**
+ * Converts an {@link ActivationDataFlavor}.
+ *
+ * @author Jörg Schaible
+ * @since 1.4.9
+ */
+public class ActivationDataFlavorConverter implements Converter {
+
+ public boolean canConvert(final Class type) {
+ return type == ActivationDataFlavor.class;
+ }
+
+ public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
+ final ActivationDataFlavor dataFlavor = (ActivationDataFlavor)source;
+ final String mimeType = dataFlavor.getMimeType();
+ if (mimeType != null) {
+ writer.startNode("mimeType");
+ writer.setValue(mimeType);
+ writer.endNode();
+ }
+ final String name = dataFlavor.getHumanPresentableName();
+ if (name != null) {
+ writer.startNode("humanRepresentableName");
+ writer.setValue(name);
+ writer.endNode();
+ }
+ final Class representationClass = dataFlavor.getRepresentationClass();
+ if (representationClass != null) {
+ writer.startNode("representationClass");
+ context.convertAnother(representationClass);
+ writer.endNode();
+ }
+ }
+
+ public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
+ String mimeType = null;
+ String name = null;
+ Class type = null;
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+
+ final String elementName = reader.getNodeName();
+ if (elementName.equals("mimeType")) {
+ mimeType = reader.getValue();
+ } else if (elementName.equals("humanRepresentableName")) {
+ name = reader.getValue();
+ } else if (elementName.equals("representationClass")) {
+ type = (Class)context.convertAnother(null, Class.class);
+ } else {
+ final ConversionException exception = new ConversionException("Unknown child element");
+ exception.add("element", reader.getNodeName());
+ throw exception;
+ }
+ reader.moveUp();
+ }
+ ActivationDataFlavor dataFlavor = null;
+ try {
+ if (type == null) {
+ dataFlavor = new ActivationDataFlavor(mimeType, name);
+ } else if (mimeType == null) {
+ dataFlavor = new ActivationDataFlavor(type, name);
+ } else {
+ dataFlavor = new ActivationDataFlavor(type, mimeType, name);
+ }
+ } catch (final IllegalArgumentException ex) {
+ throw new ConversionException(ex);
+ } catch (final NullPointerException ex) {
+ throw new ConversionException(ex);
+ }
+ return dataFlavor;
+ }
+}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/ISO8601GregorianCalendarConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ISO8601GregorianCalendarConverter.java
index 1d0da42..ddb0cd8 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/extended/ISO8601GregorianCalendarConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ISO8601GregorianCalendarConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2011, 2013, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2011, 2013, 2014, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -109,7 +109,9 @@
// try with next formatter
}
}
- throw new ConversionException("Cannot parse date " + str);
+ ConversionException exception = new ConversionException("Cannot parse date");
+ exception.add("date", str);
+ throw exception;
}
public String toString(Object obj) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java
index 24f6e0e..b6fda6e 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedMapConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 XStream Committers.
+ * Copyright (C) 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -247,10 +247,10 @@
SingleValueConverter keyConverter = null;
SingleValueConverter valueConverter = null;
if (keyAsAttribute) {
- keyConverter = getSingleValueConverter(keyType);
+ keyConverter = getSingleValueConverter(keyType, "key");
}
if (valueAsAttribute || valueName == null) {
- valueConverter = getSingleValueConverter(valueType);
+ valueConverter = getSingleValueConverter(valueType, "value");
}
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry)iterator.next();
@@ -287,10 +287,10 @@
SingleValueConverter keyConverter = null;
SingleValueConverter valueConverter = null;
if (keyAsAttribute) {
- keyConverter = getSingleValueConverter(keyType);
+ keyConverter = getSingleValueConverter(keyType, "key");
}
if (valueAsAttribute || valueName == null) {
- valueConverter = getSingleValueConverter(valueType);
+ valueConverter = getSingleValueConverter(valueType, "value");
}
while (reader.hasMoreChildren()) {
@@ -336,7 +336,7 @@
}
reader.moveUp();
} else if (!valueAsAttribute) {
- value = reader.getValue();
+ value = valueConverter.fromString(reader.getValue());
}
target.put(key, value);
@@ -347,7 +347,7 @@
}
}
- private SingleValueConverter getSingleValueConverter(Class type) {
+ private SingleValueConverter getSingleValueConverter(Class type, String part) {
SingleValueConverter conv = UseAttributeForEnumMapper.isEnum(type) ? enumMapper
.getConverterFromItemType(null, type, null) : mapper().getConverterFromItemType(
null, type, null);
@@ -356,7 +356,7 @@
if (converter instanceof SingleValueConverter) {
conv = (SingleValueConverter)converter;
} else {
- throw new ConversionException("No SingleValueConverter for key available");
+ throw new ConversionException("No SingleValueConverter for " + part + " available");
}
}
return conv;
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/PathConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/PathConverter.java
new file mode 100644
index 0000000..aaa70a3
--- /dev/null
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/PathConverter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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 7. February 2016 by Aaron Johnson
+ */
+package com.thoughtworks.xstream.converters.extended;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
+
+
+/**
+ * Converts a {@link Path} to string.
+ *
+ * @author Aaron Johnson
+ * @author Jörg Schaible
+ */
+public class PathConverter extends AbstractSingleValueConverter {
+
+ @Override
+ public boolean canConvert(final Class type) {
+ return Path.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public Object fromString(final String str) {
+ try {
+ final URI uri = new URI(str);
+ if (uri.getScheme() == null) {
+ return Paths.get(str);
+ } else {
+ return Paths.get(uri);
+ }
+ } catch (final URISyntaxException e) {
+ throw new ConversionException(e);
+ }
+ }
+
+ @Override
+ public String toString(final Object obj) {
+ final Path path = (Path)obj;
+ if (path.getFileSystem() == FileSystems.getDefault()) {
+ return path.toString();
+ } else {
+ return path.toUri().toString();
+ }
+ }
+}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/StackTraceElementFactory.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/StackTraceElementFactory.java
index 7154c8a..c480653 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/extended/StackTraceElementFactory.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/StackTraceElementFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2014, 2016 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 30. May 2004 by Joe Walnes
*/
package com.thoughtworks.xstream.converters.extended;
-import com.thoughtworks.xstream.converters.ConversionException;
-
import java.lang.reflect.Field;
+import com.thoughtworks.xstream.core.util.Fields;
+
+
/**
- * Factory for creating StackTraceElements.
* Factory for creating StackTraceElements.
*
* @author B. K. Oxley (binkley)
@@ -25,24 +25,26 @@
*/
public class StackTraceElementFactory {
- public StackTraceElement nativeMethodElement(String declaringClass, String methodName) {
+ public StackTraceElement nativeMethodElement(final String declaringClass, final String methodName) {
return create(declaringClass, methodName, "Native Method", -2);
}
- public StackTraceElement unknownSourceElement(String declaringClass, String methodName) {
+ public StackTraceElement unknownSourceElement(final String declaringClass, final String methodName) {
return create(declaringClass, methodName, "Unknown Source", -1);
}
- public StackTraceElement element(String declaringClass, String methodName, String fileName) {
+ public StackTraceElement element(final String declaringClass, final String methodName, final String fileName) {
return create(declaringClass, methodName, fileName, -1);
}
- public StackTraceElement element(String declaringClass, String methodName, String fileName, int lineNumber) {
+ public StackTraceElement element(final String declaringClass, final String methodName, final String fileName,
+ final int lineNumber) {
return create(declaringClass, methodName, fileName, lineNumber);
}
- protected StackTraceElement create(String declaringClass, String methodName, String fileName, int lineNumber) {
- StackTraceElement result = new Throwable().getStackTrace()[0];
+ protected StackTraceElement create(final String declaringClass, final String methodName, final String fileName,
+ final int lineNumber) {
+ final StackTraceElement result = new Throwable().getStackTrace()[0];
setField(result, "declaringClass", declaringClass);
setField(result, "methodName", methodName);
setField(result, "fileName", fileName);
@@ -50,14 +52,9 @@
return result;
}
- private void setField(StackTraceElement element, String fieldName, Object value) {
- try {
- final Field field = StackTraceElement.class.getDeclaredField(fieldName);
- field.setAccessible(true);
- field.set(element, value);
- } catch (Exception e) {
- throw new ConversionException(e);
- }
+ private void setField(final StackTraceElement element, final String fieldName, final Object value) {
+ final Field field = Fields.find(StackTraceElement.class, fieldName);
+ Fields.write(field, element, value);
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java
index df5f483..e4fa6c1 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013 XStream Committers.
+ * Copyright (C) 2011, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -60,6 +60,23 @@
/**
* Creates a new ToAttributedValueConverter instance.
*
+ * All field elements will be attributes, the element itself will have no value.
+ *
+ * @param type the type that is handled by this converter instance
+ * @param mapper the mapper in use
+ * @param reflectionProvider the reflection provider in use
+ * @param lookup the converter lookup in use
+ * @since 1.4.9
+ */
+ public ToAttributedValueConverter(
+ final Class type, final Mapper mapper, final ReflectionProvider reflectionProvider,
+ final ConverterLookup lookup) {
+ this(type, mapper, reflectionProvider, lookup, null, null);
+ }
+
+ /**
+ * Creates a new ToAttributedValueConverter instance.
+ *
* @param type the type that is handled by this converter instance
* @param mapper the mapper in use
* @param reflectionProvider the reflection provider in use
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToStringConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToStringConverter.java
index 852f264..cb177ee 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToStringConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToStringConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -12,6 +12,7 @@
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -26,12 +27,13 @@
* @author Paul Hammant
*/
public class ToStringConverter extends AbstractSingleValueConverter {
+ private static final Class[] STRING_PARAMETER = {String.class};
private final Class clazz;
private final Constructor ctor;
public ToStringConverter(Class clazz) throws NoSuchMethodException {
this.clazz = clazz;
- ctor = clazz.getConstructor(new Class[] {String.class});
+ ctor = clazz.getConstructor(STRING_PARAMETER);
}
public boolean canConvert(Class type) {
return type.equals(clazz);
@@ -46,7 +48,7 @@
} catch (InstantiationException e) {
throw new ConversionException("Unable to instantiate single String param constructor", e);
} catch (IllegalAccessException e) {
- throw new ConversionException("Unable to access single String param constructor", e);
+ throw new ObjectAccessException("Unable to access single String param constructor", e);
} catch (InvocationTargetException e) {
throw new ConversionException("Unable to target single String param constructor", e.getTargetException());
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/javabean/BeanProvider.java b/xstream/src/java/com/thoughtworks/xstream/converters/javabean/BeanProvider.java
index 82fd9c1..2e7e3e3 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/javabean/BeanProvider.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/javabean/BeanProvider.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,8 @@
import java.util.Iterator;
import java.util.List;
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.ErrorWritingException;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
@@ -60,22 +62,26 @@
}
public Object newInstance(Class type) {
+ ErrorWritingException ex = null;
try {
return type.newInstance();
} catch (InstantiationException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ ex = new ConversionException("Cannot construct type", e);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ ex = new ObjectAccessException("Cannot construct type", e);
} catch (SecurityException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ ex = new ObjectAccessException("Cannot construct type", e);
} catch (ExceptionInInitializerError e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ ex = new ConversionException("Cannot construct type", e);
}
+ ex.add("construction-type", type.getName());
+ throw ex;
}
public void visitSerializableProperties(Object object, JavaBeanProvider.Visitor visitor) {
PropertyDescriptor[] propertyDescriptors = getSerializableProperties(object);
for (int i = 0; i < propertyDescriptors.length; i++ ) {
+ ErrorWritingException ex = null;
PropertyDescriptor property = propertyDescriptors[i];
try {
Method readMethod = property.getReadMethod();
@@ -86,43 +92,34 @@
visitor.visit(name, property.getPropertyType(), definedIn, value);
}
} catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not get property "
- + object.getClass()
- + "."
- + property.getName(), e);
+ ex = new ConversionException("Cannot get property", e);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not get property "
- + object.getClass()
- + "."
- + property.getName(), e);
+ ex = new ObjectAccessException("Cannot access property", e);
} catch (InvocationTargetException e) {
- throw new ObjectAccessException("Could not get property "
- + object.getClass()
- + "."
- + property.getName(), e);
+ ex = new ConversionException("Cannot get property", e.getTargetException());
+ }
+ if (ex != null) {
+ ex.add("property", object.getClass() + "." + property.getName());
+ throw ex;
}
}
}
public void writeProperty(Object object, String propertyName, Object value) {
+ ErrorWritingException ex = null;
PropertyDescriptor property = getProperty(propertyName, object.getClass());
try {
property.getWriteMethod().invoke(object, new Object[]{value});
} catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not set property "
- + object.getClass()
- + "."
- + property.getName(), e);
+ ex = new ConversionException("Cannot set property", e);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not set property "
- + object.getClass()
- + "."
- + property.getName(), e);
+ ex = new ObjectAccessException("Cannot access property", e);
} catch (InvocationTargetException e) {
- throw new ObjectAccessException("Could not set property "
- + object.getClass()
- + "."
- + property.getName(), e);
+ ex = new ConversionException("Cannot set property", e.getTargetException());
+ }
+ if (ex != null) {
+ ex.add("property", object.getClass() + "." + property.getName());
+ throw ex;
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java
index 9109597..e0e5d6e 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 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;
@@ -20,14 +20,15 @@
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.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.mapper.Mapper;
+
/**
- * 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.
+ * 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 {
@@ -82,7 +83,7 @@
}
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
- final String classAttributeName = classAttributeIdentifier != null ? classAttributeIdentifier : mapper.aliasForSystemAttribute("class");
+ final String classAttributeName = mapper.aliasForSystemAttribute("class");
beanProvider.visitSerializableProperties(source, new JavaBeanProvider.Visitor() {
public boolean shouldVisit(String name, Class definedIn) {
return mapper.shouldSerializeMember(definedIn, name);
@@ -90,20 +91,29 @@
public void visit(String propertyName, Class fieldType, Class definedIn, Object newObj) {
if (newObj != null) {
- writeField(propertyName, fieldType, newObj, definedIn);
+ writeField(propertyName, fieldType, newObj);
+ } else {
+ writeNullField(propertyName);
}
}
- private void writeField(String propertyName, Class fieldType, Object newObj, Class definedIn) {
+ private void writeField(String propertyName, Class fieldType, Object newObj) {
Class actualType = newObj.getClass();
Class defaultType = mapper.defaultImplementationOf(fieldType);
String serializedMember = mapper.serializedMember(source.getClass(), propertyName);
- ExtendedHierarchicalStreamWriterHelper.startNode(writer, serializedMember, actualType);
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, serializedMember, actualType);
if (!actualType.equals(defaultType) && classAttributeName != null) {
writer.addAttribute(classAttributeName, mapper.serializedClass(actualType));
}
context.convertAnother(newObj);
+ writer.endNode();
+ }
+
+ private void writeNullField(final String propertyName) {
+ final String serializedMember = mapper.serializedMember(source.getClass(), propertyName);
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, serializedMember, Mapper.Null.class);
+ writer.addAttribute(classAttributeName, mapper.serializedClass(Mapper.Null.class));
writer.endNode();
}
});
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/javabean/PropertyDictionary.java b/xstream/src/java/com/thoughtworks/xstream/converters/javabean/PropertyDictionary.java
index c5c6b19..4d4eeae 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/javabean/PropertyDictionary.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/javabean/PropertyDictionary.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -107,8 +107,9 @@
try {
beanInfo = Introspector.getBeanInfo(type, Object.class);
} catch (IntrospectionException e) {
- throw new ObjectAccessException(
- "Cannot get BeanInfo of type " + type.getName(), e);
+ ObjectAccessException oaex = new ObjectAccessException("Cannot get BeanInfo of type", e);
+ oaex.add("bean-type", type.getName());
+ throw oaex;
}
nameMap = new OrderRetainingMap();
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractAttributedCharacterIteratorAttributeConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractAttributedCharacterIteratorAttributeConverter.java
index ac65fab..67116d4 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractAttributedCharacterIteratorAttributeConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractAttributedCharacterIteratorAttributeConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2013 XStream Committers.
+ * Copyright (C) 2007, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -89,14 +89,19 @@
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);
+ ConversionException exception = new ConversionException("Cannot find name of attribute", ex);
+ exception.add("attribute-type", className);
+ throw exception;
}
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);
+ ConversionException exception = new ConversionException("Cannot find attribute");
+ exception.add("attribute-type", type.getName());
+ exception.add("attribute-name", str);
+ throw exception;
}
private Object readResolve() {
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java
index ffde863..04dfd76 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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;
@@ -20,6 +20,7 @@
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.Fields;
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
import com.thoughtworks.xstream.core.util.Primitives;
import com.thoughtworks.xstream.core.util.SerializationMembers;
@@ -94,6 +95,7 @@
final MarshallingContext context) {
final List fields = new ArrayList();
final Map defaultFieldDefinition = new HashMap();
+ final Class sourceType = source.getClass();
// Attributes might be preferred to child elements ...
reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
@@ -106,7 +108,7 @@
if (!defaultFieldDefinition.containsKey(fieldName)) {
Class lookupType = source.getClass();
// See XSTR-457 and OmitFieldsTest
- if (definedIn != source.getClass()
+ if (definedIn != sourceType
&& !mapper.shouldSerializeMember(lookupType, fieldName)) {
lookupType = definedIn;
}
@@ -120,18 +122,19 @@
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());
+ if (writtenAttributes.contains(fieldName)) {
+ ConversionException exception =
+ new ConversionException("Cannot write field as attribute for object, attribute name already in use");
+ exception.add("field-name", fieldName);
+ exception.add("object-type", sourceType.getName());
+ throw exception;
}
final String str = converter.toString(value);
if (str != null) {
writer.addAttribute(attribute, str);
}
}
- writtenAttributes.add(fieldName); // TODO: use attribute
+ writtenAttributes.add(fieldName);
} else {
fields.add(new FieldInfo(fieldName, type, definedIn, value));
}
@@ -140,12 +143,27 @@
new Object() {
{
+ final Map hiddenMappers = new HashMap();
for (Iterator fieldIter = fields.iterator(); fieldIter.hasNext();) {
FieldInfo info = (FieldInfo)fieldIter.next();
if (info.value != null) {
+ final Field defaultField = (Field)defaultFieldDefinition.get(info.fieldName);
Mapper.ImplicitCollectionMapping mapping = mapper
.getImplicitCollectionDefForFieldName(
- source.getClass(), info.fieldName);
+ defaultField.getDeclaringClass() == info.definedIn ? sourceType : info.definedIn,
+ info.fieldName);
+ if (mapping != null) {
+ Set mappings = (Set)hiddenMappers.get(info.fieldName);
+ if (mappings == null) {
+ mappings = new HashSet();
+ mappings.add(mapping);
+ hiddenMappers.put(info.fieldName, mappings);
+ } else {
+ if (!mappings.add(mapping)) {
+ mapping = null;
+ }
+ }
+ }
if (mapping != null) {
if (context instanceof ReferencingMarshallingContext) {
if (info.value != Collections.EMPTY_LIST
@@ -205,7 +223,7 @@
Class actualType = newObj != null ? newObj.getClass() : fieldType;
ExtendedHierarchicalStreamWriterHelper.startNode(writer, aliasName != null
? aliasName
- : mapper.serializedMember(source.getClass(), fieldName), actualType);
+ : mapper.serializedMember(sourceType, fieldName), actualType);
if (newObj != null) {
Class defaultType = mapper.defaultImplementationOf(fieldType);
@@ -300,10 +318,10 @@
type = Primitives.box(type);
}
if (value != null && !type.isAssignableFrom(value.getClass())) {
- throw new ConversionException("Cannot convert type "
- + value.getClass().getName()
- + " to type "
- + type.getName());
+ ConversionException exception = new ConversionException("Cannot convert type");
+ exception.add("source-type", value.getClass().getName());
+ exception.add("target-type", type.getName());
+ throw exception;
}
seenFields.add(new FastField(classDefiningField, attrName));
reflectionProvider.writeField(result, attrName, value, classDefiningField);
@@ -332,7 +350,7 @@
field = reflectionProvider.getFieldOrNull(fieldDeclaringClass, fieldName);
if (field == null) {
// it is not a field ... do we have a field alias?
- Class itemType = mapper.getItemTypeForItemFieldName(resultType, fieldName);
+ Class itemType = mapper.getItemTypeForItemFieldName(fieldDeclaringClass, fieldName);
if (itemType != null) {
String classAttribute = HierarchicalStreams.readClassAttribute(
reader, mapper);
@@ -347,7 +365,7 @@
try {
type = mapper.realClass(originalNodeName);
implicitFieldName = mapper.getFieldNameForItemTypeAndName(
- context.getRequiredType(), type, originalNodeName);
+ fieldDeclaringClass, type, originalNodeName);
} catch (CannotResolveClassException e) {
// type stays null ...
}
@@ -355,7 +373,7 @@
// either not a type or element is a type alias, but does not
// belong to an implicit field
handleUnknownField(
- explicitDeclaringClass, fieldName, resultType, originalNodeName);
+ explicitDeclaringClass, fieldName, fieldDeclaringClass, originalNodeName);
// element is unknown in declaring class, ignore it now
type = null;
@@ -400,7 +418,6 @@
if (field != null
&& (fieldAlreadyChecked || (shouldUnmarshalField(field) && mapper
.shouldSerializeMember(field.getDeclaringClass(), fieldName)))) {
-
String classAttribute = HierarchicalStreams.readClassAttribute(
reader, mapper);
if (classAttribute != null) {
@@ -446,7 +463,7 @@
if (implicitFieldName == null) {
// look for implicit field
implicitFieldName = mapper.getFieldNameForItemTypeAndName(
- context.getRequiredType(),
+ fieldDeclaringClass,
value != null ? value.getClass() : Mapper.Null.class,
originalNodeName);
}
@@ -454,7 +471,8 @@
implicitCollectionsForCurrentObject = new HashMap();
}
writeValueToImplicitCollection(
- value, implicitCollectionsForCurrentObject, result, implicitFieldName);
+ value, implicitCollectionsForCurrentObject, result, new FieldLocation(
+ implicitFieldName, fieldDeclaringClass));
}
reader.moveUp();
@@ -467,7 +485,12 @@
Object value = entry.getValue();
if (value instanceof ArraysList) {
Object array = ((ArraysList)value).toPhysicalArray();
- reflectionProvider.writeField(result, (String)entry.getKey(), array, null);
+ final FieldLocation fieldLocation = (FieldLocation)entry.getKey();
+ final Field field = reflectionProvider.getFieldOrNull(fieldLocation.definedIn,
+ fieldLocation.fieldName);
+ reflectionProvider.writeField(result, fieldLocation.fieldName, array, field != null
+ ? field.getDeclaringClass()
+ : null);
}
}
}
@@ -501,24 +524,24 @@
throw new UnknownFieldException(resultType.getName(), fieldName);
}
- private void writeValueToImplicitCollection(Object value, Map implicitCollections, Object result, String implicitFieldName) {
- Collection collection = (Collection)implicitCollections.get(implicitFieldName);
+ private void writeValueToImplicitCollection(Object value, Map implicitCollections, Object result, final FieldLocation fieldLocation) {
+ Collection collection = (Collection)implicitCollections.get(fieldLocation);
if (collection == null) {
- Class physicalFieldType = reflectionProvider.getFieldType(
- result, implicitFieldName, null);
+ final Field field = reflectionProvider.getFieldOrNull(fieldLocation.definedIn, fieldLocation.fieldName);
+ Class physicalFieldType = field != null
+ ? field.getType()
+ : reflectionProvider.getFieldType(result, fieldLocation.fieldName, null);
if (physicalFieldType.isArray()) {
collection = new ArraysList(physicalFieldType);
} else {
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());
+ ObjectAccessException oaex = new ObjectAccessException(
+ "Field is configured for an implicit Collection or Map, but is of an incompatible type");
+ oaex.add("field", result.getClass().getName() + "."+fieldLocation.fieldName);
+ oaex.add("field-type", fieldType.getName());
+ throw oaex;
}
if (pureJavaReflectionProvider == null) {
pureJavaReflectionProvider = new PureJavaReflectionProvider();
@@ -528,13 +551,15 @@
collection = (Collection)instance;
} else {
Mapper.ImplicitCollectionMapping implicitCollectionMapping = mapper
- .getImplicitCollectionDefForFieldName(result.getClass(), implicitFieldName);
+ .getImplicitCollectionDefForFieldName(fieldLocation.definedIn, fieldLocation.fieldName);
collection = new MappingList(
(Map)instance, implicitCollectionMapping.getKeyFieldName());
}
- reflectionProvider.writeField(result, implicitFieldName, instance, null);
- }
- implicitCollections.put(implicitFieldName, collection);
+ reflectionProvider.writeField(result, fieldLocation.fieldName, instance, field != null
+ ? field.getDeclaringClass()
+ : null);
+ }
+ implicitCollections.put(fieldLocation, collection);
}
collection.add(value);
}
@@ -584,16 +609,55 @@
}
}
- private static class FieldInfo {
+ private static class FieldLocation {
final String fieldName;
+ final Class definedIn;
+
+ FieldLocation(final String fieldName, final Class definedIn) {
+ this.fieldName = fieldName;
+ this.definedIn = definedIn;
+ }
+
+ public int hashCode() {
+ final int prime = 7;
+ int result = 1;
+ result = prime * result + (definedIn == null ? 0 : definedIn.getName().hashCode());
+ result = prime * result + (fieldName == null ? 0 : fieldName.hashCode());
+ return result;
+ }
+
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final FieldLocation other = (FieldLocation)obj;
+ if (definedIn != other.definedIn) {
+ return false;
+ }
+ if (fieldName == null) {
+ if (other.fieldName != null) {
+ return false;
+ }
+ } else if (!fieldName.equals(other.fieldName)) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private static class FieldInfo extends FieldLocation {
final Class type;
- final Class definedIn;
final Object value;
- FieldInfo(String fieldName, Class type, Class definedIn, Object value) {
- this.fieldName = fieldName;
+ FieldInfo(final String fieldName, final Class type, final Class definedIn, final Object value) {
+ super(fieldName, definedIn);
this.type = type;
- this.definedIn = definedIn;
this.value = value;
}
}
@@ -646,30 +710,19 @@
fieldCache.put(itemType, field);
}
if (field != null) {
- try {
- Object key = field.get(object);
- return map.put(key, object) == null;
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not get field "
- + field.getClass()
- + "."
- + field.getName(), e);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not get field "
- + field.getClass()
- + "."
- + field.getName(), e);
- }
+ Object key = Fields.read(field, object);
+ return map.put(key, object) == null;
}
} else if (object instanceof Map.Entry) {
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());
+ ConversionException exception =
+ new ConversionException("Element is not defined as entry for implicit map");
+ exception.add("map-type", map.getClass().getName());
+ exception.add("element-type", object.getClass().getName());
+ throw exception;
}
public Object get(int index) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java
index 6ba08cc..12c886d 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -125,8 +125,8 @@
} else {
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));
+ exception.add("proxy-superclass", type.getSuperclass().getName());
+ exception.add("number-of-callbacks", String.valueOf(callbacks.length));
throw exception;
}
writer.startNode("callbacks");
@@ -166,9 +166,9 @@
} catch (NoSuchFieldException e) {
// OK, ignore
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Access to serialVersionUID of "
- + type.getName()
- + " not allowed", e);
+ ObjectAccessException exception = new ObjectAccessException("Cannot access field", e);
+ exception.add("field", type.getName() + ".serialVersionUID");
+ throw exception;
}
if (hasInterceptor) {
writer.startNode("instance");
@@ -202,12 +202,9 @@
Object callback = field.get(source);
list.add(callback);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Access to "
- + type.getName()
- + "."
- + CALLBACK_MARKER
- + i
- + " not allowed", e);
+ ObjectAccessException exception = new ObjectAccessException("Cannot access field", e);
+ exception.add("field", type.getName() + "." + CALLBACK_MARKER + i);
+ throw exception;
}
}
return (Callback[])list.toArray(new Callback[list.size()]);
@@ -269,15 +266,15 @@
? (Object[])null
: createNullArguments(parameterTypes));
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Access to "
- + calledMethod
- + " not allowed", e);
+ ObjectAccessException exception = new ObjectAccessException("Cannot access method", e);
+ exception.add("method", calledMethod.toString());
+ throw exception;
} catch (InvocationTargetException e) {
// OK, ignore
} catch (NoSuchMethodException e) {
ConversionException exception = new ConversionException(
"CGLIB enhanced proxies wit abstract nethod that has not been implemented");
- exception.add("proxy superclass", type.getSuperclass().getName());
+ exception.add("proxy-superclass", type.getSuperclass().getName());
exception.add("method", method.toString());
throw exception;
}
@@ -336,7 +333,7 @@
if (iface == Callback.class) {
ConversionException exception = new ConversionException(
"Cannot handle CGLIB callback");
- exception.add("CGLIB callback type", callback.getClass().getName());
+ exception.add("CGLIB-callback-type", callback.getClass().getName());
throw exception;
}
interfaces = iface.getInterfaces();
@@ -488,7 +485,7 @@
if (!callbackIndexMap.containsKey(method)) {
ConversionException exception = new ConversionException(
"CGLIB callback not detected in reverse engineering");
- exception.add("CGLIB callback", method.toString());
+ exception.add("CGLIB-callback", method.toString());
throw exception;
}
return ((Integer)callbackIndexMap.get(method)).intValue();
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java
index cd8a585..05ab79c 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -25,6 +25,7 @@
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.io.StreamException;
import com.thoughtworks.xstream.mapper.Mapper;
import java.io.Externalizable;
@@ -124,7 +125,7 @@
externalizable.writeExternal(objectOutput);
objectOutput.popCallback();
} catch (IOException e) {
- throw new ConversionException("Cannot serialize " + source.getClass().getName() + " using Externalization", e);
+ throw new StreamException("Cannot serialize " + source.getClass().getName() + " using Externalization", e);
}
}
}
@@ -168,17 +169,17 @@
objectInput.popCallback();
return serializationMembers.callReadResolve(externalizable);
} catch (NoSuchMethodException e) {
- throw new ConversionException("Cannot construct " + type.getClass() + ", missing default constructor", e);
+ throw new ConversionException("Missing default constructor of type", e);
} catch (InvocationTargetException e) {
- throw new ConversionException("Cannot construct " + type.getClass(), e);
+ throw new ConversionException("Cannot construct type", e);
} catch (InstantiationException e) {
- throw new ConversionException("Cannot construct " + type.getClass(), e);
+ throw new ConversionException("Cannot construct type", e);
} catch (IllegalAccessException e) {
- throw new ConversionException("Cannot construct " + type.getClass(), e);
+ throw new ObjectAccessException("Cannot construct type", e);
} catch (IOException e) {
- throw new ConversionException("Cannot externalize " + type.getClass(), e);
+ throw new StreamException("Cannot externalize " + type.getClass(), e);
} catch (ClassNotFoundException e) {
- throw new ConversionException("Cannot externalize " + type.getClass(), e);
+ throw new ConversionException("Cannot construct type", e);
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/FieldDictionary.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/FieldDictionary.java
index a450e8f..77f01a4 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/FieldDictionary.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/FieldDictionary.java
@@ -1,25 +1,21 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 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 java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
+import java.util.LinkedList;
import java.util.Map;
-import java.util.Set;
import com.thoughtworks.xstream.core.Caching;
import com.thoughtworks.xstream.core.JVM;
@@ -28,47 +24,46 @@
/**
* 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 keyedByFieldNameCache;
- private transient Map keyedByFieldKeyCache;
+ private static final DictionaryEntry OBJECT_DICTIONARY_ENTRY = new DictionaryEntry(Collections.EMPTY_MAP,
+ Collections.EMPTY_MAP);
+
+ private transient Map dictionaryEntries;
private final FieldKeySorter sorter;
public FieldDictionary() {
this(new ImmutableFieldKeySorter());
}
- public FieldDictionary(FieldKeySorter sorter) {
+ public FieldDictionary(final FieldKeySorter sorter) {
this.sorter = sorter;
init();
}
private void init() {
- keyedByFieldNameCache = new HashMap();
- keyedByFieldKeyCache = new HashMap();
- keyedByFieldNameCache.put(Object.class, Collections.EMPTY_MAP);
- keyedByFieldKeyCache.put(Object.class, Collections.EMPTY_MAP);
+ dictionaryEntries = new HashMap();
}
/**
* Returns an iterator for all fields for some class
- *
+ *
* @param cls the class you are interested on
* @return an iterator for its fields
* @deprecated As of 1.3, use {@link #fieldsFor(Class)} instead
*/
- public Iterator serializableFieldsFor(Class cls) {
+ public Iterator serializableFieldsFor(final Class cls) {
return fieldsFor(cls);
}
/**
* Returns an iterator for all fields for some class
- *
+ *
* @param cls the class you are interested on
* @return an iterator for its fields
*/
@@ -77,19 +72,18 @@
}
/**
- * 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)
- *
+ * 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(Class cls, String name, Class definedIn) {
- Field field = fieldOrNull(cls, name, definedIn);
+ public Field field(final Class cls, final String name, final Class definedIn) {
+ final Field field = fieldOrNull(cls, name, definedIn);
if (field == null) {
throw new MissingFieldException(cls.getName(), name);
} else {
@@ -98,89 +92,98 @@
}
/**
- * 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)
- *
+ * 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(Class cls, String name, Class definedIn) {
- Map fields = buildMap(cls, definedIn != null);
- Field field = (Field)fields.get(definedIn != null
+ public Field fieldOrNull(final Class cls, final String name, final Class definedIn) {
+ final Map fields = buildMap(cls, definedIn != null);
+ final Field field = (Field)fields.get(definedIn != null
? (Object)new FieldKey(name, definedIn, -1)
: (Object)name);
return field;
}
- private Map buildMap(final Class type, boolean tupleKeyed) {
+ private Map 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();
+
+ DictionaryEntry lastDictionaryEntry = null;
+ final LinkedList superClasses = new LinkedList();
+ while (lastDictionaryEntry == null) {
+ if (Object.class.equals(cls) || cls == null) {
+ lastDictionaryEntry = OBJECT_DICTIONARY_ENTRY;
+ } else {
+ lastDictionaryEntry = getDictionaryEntry(cls);
+ }
+ if (lastDictionaryEntry == null) {
+ superClasses.addFirst(cls);
+ cls = cls.getSuperclass();
+ }
+ }
+
+ for (final Iterator iter = superClasses.iterator(); iter.hasNext();) {
+ cls = (Class)iter.next();
+ DictionaryEntry newDictionaryEntry = buildDictionaryEntryForClass(cls, lastDictionaryEntry);
+ synchronized (this) {
+ final DictionaryEntry concurrentEntry = getDictionaryEntry(cls);
+ if (concurrentEntry == null) {
+ dictionaryEntries.put(cls, newDictionaryEntry);
+ } else {
+ newDictionaryEntry = concurrentEntry;
}
- Map lastKeyedByFieldName = Collections.EMPTY_MAP;
- Map lastKeyedByFieldKey = Collections.EMPTY_MAP;
- for (final Iterator iter = superClasses.iterator(); iter.hasNext();) {
- cls = (Class)iter.next();
- if (!keyedByFieldNameCache.containsKey(cls)) {
- final Map keyedByFieldName = new HashMap(lastKeyedByFieldName);
- final Map keyedByFieldKey = new OrderRetainingMap(lastKeyedByFieldKey);
- 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];
- if (!field.isAccessible()) {
- field.setAccessible(true);
- }
- FieldKey fieldKey = new FieldKey(
- field.getName(), field.getDeclaringClass(), i);
- Field existent = (Field)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(fieldKey, field);
- }
- final Map sortedFieldKeys = sorter.sort(cls, keyedByFieldKey);
- keyedByFieldNameCache.put(cls, keyedByFieldName);
- keyedByFieldKeyCache.put(cls, sortedFieldKeys);
- lastKeyedByFieldName = keyedByFieldName;
- lastKeyedByFieldKey = sortedFieldKeys;
- } else {
- lastKeyedByFieldName = (Map)keyedByFieldNameCache.get(cls);
- lastKeyedByFieldKey = (Map)keyedByFieldKeyCache.get(cls);
- }
- }
- return tupleKeyed ? lastKeyedByFieldKey : lastKeyedByFieldName;
- }
- }
- return (Map)(tupleKeyed
- ? keyedByFieldKeyCache.get(type)
- : keyedByFieldNameCache.get(type));
+ }
+ lastDictionaryEntry = newDictionaryEntry;
+ }
+
+ return tupleKeyed ? lastDictionaryEntry.getKeyedByFieldKey() : lastDictionaryEntry.getKeyedByFieldName();
+
+ }
+
+ private DictionaryEntry buildDictionaryEntryForClass(final Class cls, final DictionaryEntry lastDictionaryEntry) {
+ final Map keyedByFieldName = new HashMap(lastDictionaryEntry.getKeyedByFieldName());
+ final Map keyedByFieldKey = new OrderRetainingMap(lastDictionaryEntry.getKeyedByFieldKey());
+ 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++) {
+ final Field field = fields[i];
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ final FieldKey fieldKey = new FieldKey(field.getName(), field.getDeclaringClass(), i);
+ final Field existent = (Field)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(fieldKey, field);
+ }
+ final Map sortedFieldKeys = sorter.sort(cls, keyedByFieldKey);
+ return new DictionaryEntry(keyedByFieldName, sortedFieldKeys);
+ }
+
+ private synchronized DictionaryEntry getDictionaryEntry(final Class cls) {
+ return (DictionaryEntry)dictionaryEntries.get(cls);
}
public synchronized void flushCache() {
- Set objectTypeSet = Collections.singleton(Object.class);
- keyedByFieldNameCache.keySet().retainAll(objectTypeSet);
- keyedByFieldKeyCache.keySet().retainAll(objectTypeSet);
+ dictionaryEntries.clear();
if (sorter instanceof Caching) {
((Caching)sorter).flushCache();
}
@@ -190,4 +193,24 @@
init();
return this;
}
+
+ private static final class DictionaryEntry {
+
+ private final Map keyedByFieldName;
+ private final Map keyedByFieldKey;
+
+ public DictionaryEntry(final Map keyedByFieldName, final Map keyedByFieldKey) {
+ super();
+ this.keyedByFieldName = keyedByFieldName;
+ this.keyedByFieldKey = keyedByFieldKey;
+ }
+
+ public Map getKeyedByFieldName() {
+ return keyedByFieldName;
+ }
+
+ public Map getKeyedByFieldKey() {
+ return keyedByFieldKey;
+ }
+ }
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/MissingFieldException.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/MissingFieldException.java
index 102fa92..1046d5c 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/MissingFieldException.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/MissingFieldException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 XStream Committers.
+ * Copyright (C) 2011, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -29,9 +29,10 @@
* @since 1.4.2
*/
public MissingFieldException(final String className, final String fieldName) {
- super("No field '" + fieldName + "' found in class '" + className + "'");
+ super("Field not found in class.");
this.className = className;
this.fieldName = fieldName;
+ add("field", className + "." + fieldName);
}
/**
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ObjectAccessException.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ObjectAccessException.java
index c3ac302..5ea05e8 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ObjectAccessException.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/ObjectAccessException.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,9 +11,9 @@
*/
package com.thoughtworks.xstream.converters.reflection;
-import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.converters.ErrorWritingException;
-public class ObjectAccessException extends XStreamException {
+public class ObjectAccessException extends ErrorWritingException {
public ObjectAccessException(String message) {
super(message);
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/PureJavaReflectionProvider.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/PureJavaReflectionProvider.java
index 8158e37..d2beebd 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/PureJavaReflectionProvider.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/PureJavaReflectionProvider.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2011, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -12,6 +12,7 @@
package com.thoughtworks.xstream.converters.reflection;
import com.thoughtworks.xstream.core.JVM;
+import com.thoughtworks.xstream.core.util.Fields;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -57,6 +58,7 @@
}
public Object newInstance(Class type) {
+ ObjectAccessException oaex = null;
try {
Constructor[] constructors = type.getDeclaredConstructors();
for (int i = 0; i < constructors.length; i++) {
@@ -71,25 +73,27 @@
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");
+ oaex = new ObjectAccessException("Cannot construct type as it does not have a no-args constructor");
}
} catch (InstantiationException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ oaex = new ObjectAccessException("Cannot construct type", e);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ oaex = new ObjectAccessException("Cannot construct type", 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.getTargetException());
- }
- }
+ oaex = new ObjectAccessException("Constructor for type threw an exception", e.getTargetException());
+ }
+ }
+ oaex.add("construction-type", type.getName());
+ throw oaex;
}
private Object instantiateUsingSerialization(final Class type) {
+ ObjectAccessException oaex = null;
try {
synchronized (serializedDataCache) {
byte[] data = (byte[]) serializedDataCache.get(type);
@@ -119,10 +123,12 @@
return in.readObject();
}
} catch (IOException e) {
- throw new ObjectAccessException("Cannot create " + type.getName() + " by JDK serialization", e);
+ oaex = new ObjectAccessException("Cannot create type by JDK serialization", e);
} catch (ClassNotFoundException e) {
- throw new ObjectAccessException("Cannot find class " + e.getMessage(), e);
- }
+ oaex = new ObjectAccessException("Cannot find class", e);
+ }
+ oaex.add("construction-type", type.getName());
+ throw oaex;
}
public void visitSerializableFields(Object object, ReflectionProvider.Visitor visitor) {
@@ -132,27 +138,15 @@
continue;
}
validateFieldAccess(field);
- try {
- Object value = field.get(object);
- visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- }
+ Object value = Fields.read(field, object);
+ visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
}
}
public void writeField(Object object, String fieldName, Object value, Class definedIn) {
Field field = fieldDictionary.field(object.getClass(), fieldName, definedIn);
validateFieldAccess(field);
- try {
- field.set(object, 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);
- }
+ Fields.write(field, object, value);
}
public Class getFieldType(Object object, String fieldName, Class definedIn) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java
index 2825980..6488069 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2014, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -32,10 +32,12 @@
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.Fields;
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.io.StreamException;
import com.thoughtworks.xstream.mapper.Mapper;
/**
@@ -151,8 +153,7 @@
ObjectStreamField field = objectStreamClass.getField(name);
Object value = fields.get(name);
if (field == null) {
- throw new ObjectAccessException("Class " + value.getClass().getName()
- + " may not write a field named '" + name + "'");
+ throw new MissingFieldException(value.getClass().getName(), name);
}
if (value != null) {
ExtendedHierarchicalStreamWriterHelper.startNode(
@@ -280,7 +281,7 @@
}
}
} catch (IOException e) {
- throw new ObjectAccessException("Could not call defaultWriteObject()", e);
+ throw new StreamException("Cannot write defaults", e);
}
}
@@ -291,21 +292,8 @@
}
private Object readField(ObjectStreamField field, Class type, Object instance) {
- try {
- Field javaField = type.getDeclaredField(field.getName());
- if (!javaField.isAccessible()) {
- javaField.setAccessible(true);
- }
- return javaField.get(instance);
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (NoSuchFieldException e) {
- throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- } catch (SecurityException e) {
- throw new ObjectAccessException("Could not get field " + field.getClass() + "." + field.getName(), e);
- }
+ Field javaField = Fields.find(type, field.getName());
+ return Fields.read(javaField, instance);
}
protected List hierarchyFor(Class type) {
@@ -426,7 +414,7 @@
try {
validation.validateObject();
} catch (InvalidObjectException e) {
- throw new ObjectAccessException("Cannot validate object : " + e.getMessage(), e);
+ throw new ObjectAccessException("Cannot validate object", e);
}
}
}, priority);
@@ -458,7 +446,7 @@
try {
callback.defaultReadObject();
} catch (IOException e) {
- throw new ObjectAccessException("Could not call defaultWriteObject()", e);
+ throw new StreamException("Cannot read defaults", e);
}
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorter.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorter.java
index f6bee5e..91333c8 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorter.java
@@ -1,41 +1,41 @@
/*
- * Copyright (C) 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2007, 2009, 2011, 2016 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 com.thoughtworks.xstream.core.Caching;
-import com.thoughtworks.xstream.core.util.OrderRetainingMap;
-import com.thoughtworks.xstream.io.StreamException;
import java.util.Arrays;
import java.util.Comparator;
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.OrderRetainingMap;
+
/**
- * The default implementation for sorting fields. Invoke registerFieldOrder in order to set the
- * field order for an specific type.
- *
+ * 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 static FieldKey[] EMPTY_FIELD_KEY_ARRAY = {};
private final Map map = new HashMap();
- public Map sort(Class type, Map keyedByFieldKey) {
+ public Map sort(final Class type, final Map keyedByFieldKey) {
if (map.containsKey(type)) {
- Map result = new OrderRetainingMap();
- FieldKey[] fieldKeys = (FieldKey[])keyedByFieldKey.keySet().toArray(
- new FieldKey[keyedByFieldKey.size()]);
+ final Map result = new OrderRetainingMap();
+ final FieldKey[] fieldKeys = (FieldKey[])keyedByFieldKey.keySet().toArray(EMPTY_FIELD_KEY_ARRAY);
Arrays.sort(fieldKeys, (Comparator)map.get(type));
for (int i = 0; i < fieldKeys.length; i++ ) {
result.put(fieldKeys[i], keyedByFieldKey.get(fieldKeys[i]));
@@ -47,28 +47,30 @@
}
/**
- * 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.
- *
+ * 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 a {@link ConversionException} during
+ * the serialization process.
+ *
* @param type the type
* @param fields the field order
*/
- public void registerFieldOrder(Class type, String[] fields) {
- map.put(type, new FieldComparator(fields));
+ public void registerFieldOrder(final Class type, final String[] fields) {
+ map.put(type, new FieldComparator(type, fields));
}
private class FieldComparator implements Comparator {
private final String[] fieldOrder;
+ private final Class type;
- public FieldComparator(String[] fields) {
- this.fieldOrder = fields;
+ public FieldComparator(final Class type, final String[] fields) {
+ this.type = type;
+ fieldOrder = fields;
}
- public int compare(String first, String second) {
+ public int compare(final String first, final String second) {
int firstPosition = -1, secondPosition = -1;
- for (int i = 0; i < fieldOrder.length; i++ ) {
+ for (int i = 0; i < fieldOrder.length; i++) {
if (fieldOrder[i].equals(first)) {
firstPosition = i;
}
@@ -78,14 +80,16 @@
}
if (firstPosition == -1 || secondPosition == -1) {
// field not defined!!!
- throw new StreamException(
- "You have not given XStream a list of all fields to be serialized.");
+ final ConversionException exception = new ConversionException(
+ "Incomplete list of serialized fields for type");
+ exception.add("sort-type", type.getName());
+ throw exception;
}
return firstPosition - secondPosition;
}
- public int compare(Object firstObject, Object secondObject) {
- FieldKey first = (FieldKey)firstObject, second = (FieldKey)secondObject;
+ public int compare(final Object firstObject, final Object secondObject) {
+ final FieldKey first = (FieldKey)firstObject, second = (FieldKey)secondObject;
return compare(first.getFieldName(), second.getFieldName());
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
index 4faef33..2c569ae 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers.
* All rights reserved.
*
* Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
@@ -8,6 +8,9 @@
package com.thoughtworks.xstream.converters.reflection;
import java.lang.reflect.Field;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.ErrorWritingException;
import sun.misc.Unsafe;
@@ -70,17 +73,22 @@
public Object newInstance(Class type) {
if (exception != null) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), exception);
+ ObjectAccessException ex = new ObjectAccessException("Cannot construct type", exception);
+ ex.add("construction-type", type.getName());
+ throw ex;
}
+ ErrorWritingException ex = null;
try {
return unsafe.allocateInstance(type);
} catch (SecurityException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ ex = new ObjectAccessException("Cannot construct type", e);
} catch (InstantiationException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ ex = new ConversionException("Cannot construct type", e);
} catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ ex = new ObjectAccessException("Cannot construct type", e);
}
+ ex.add("construction-type", type.getName());
+ throw ex;
}
protected void validateFieldAccess(Field field) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java
index c97c0c8..4c13023 100644
--- a/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java
+++ b/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -58,8 +58,9 @@
private void write(Field field, Object object, Object value) {
if (exception != null) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(),
- exception);
+ ObjectAccessException ex = new ObjectAccessException("Cannot set field", exception);
+ ex.add("field", object.getClass() + "." + field.getName());
+ throw ex;
}
try {
long offset = getFieldOffset(field);
@@ -82,19 +83,19 @@
} 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);
+ ObjectAccessException ex = new ObjectAccessException("Cannot set field of unknown type", exception);
+ ex.add("field", object.getClass() + "." + field.getName());
+ ex.add("unknown-type", type.getName());
+ throw ex;
}
} else {
unsafe.putObject(object, offset, value);
}
} catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
+ ObjectAccessException ex = new ObjectAccessException("Cannot set field", e);
+ ex.add("field", object.getClass() + "." + field.getName());
+ throw ex;
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/AbstractReferenceUnmarshaller.java b/xstream/src/java/com/thoughtworks/xstream/core/AbstractReferenceUnmarshaller.java
index d8218fd..791ca18 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/AbstractReferenceUnmarshaller.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/AbstractReferenceUnmarshaller.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2015 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;
@@ -22,7 +22,7 @@
/**
* Abstract base class for a TreeUnmarshaller, that resolves references.
- *
+ *
* @author Joe Walnes
* @author Jörg Schaible
* @author Mauro Talevi
@@ -49,16 +49,21 @@
}
}
final Object result;
- String attributeName = getMapper().aliasForSystemAttribute("reference");
- String reference = attributeName == null ? null : reader.getAttribute(attributeName);
+ final String attributeName = getMapper().aliasForSystemAttribute("reference");
+ final String reference = attributeName == null ? null : reader.getAttribute(attributeName);
+ final boolean isReferenceable = getMapper().isReferenceable(type);
if (reference != null) {
- Object cache = values.get(getReferenceKey(reference));
+ final Object cache = isReferenceable ? values.get(getReferenceKey(reference)) : null;
if (cache == null) {
final ConversionException ex = new ConversionException("Invalid reference");
ex.add("reference", reference);
+ ex.add("referenced-type", type.getName());
+ ex.add("referenceable", Boolean.toString(isReferenceable));
throw ex;
}
result = cache == NULL ? null : cache;
+ } else if (!isReferenceable) {
+ result = super.convert(parent, type, converter);
} else {
Object currentReferenceKey = getCurrentReferenceKey();
parentStack.push(currentReferenceKey);
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/BaseException.java b/xstream/src/java/com/thoughtworks/xstream/core/BaseException.java
index a1bdb51..de33aa6 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/BaseException.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/BaseException.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,7 +14,6 @@
import com.thoughtworks.xstream.XStreamException;
/**
- * JDK1.3 friendly exception that retains cause.
* @deprecated As of 1.3, use {@link XStreamException} instead
*/
public abstract class BaseException extends RuntimeException {
@@ -23,5 +22,7 @@
super(message);
}
- public abstract Throwable getCause();
+ protected BaseException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/DefaultConverterLookup.java b/xstream/src/java/com/thoughtworks/xstream/core/DefaultConverterLookup.java
index b4b955f..c89055a 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/DefaultConverterLookup.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/DefaultConverterLookup.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -58,7 +58,9 @@
return converter;
}
}
- throw new ConversionException("No converter specified for " + type);
+ ConversionException exception = new ConversionException("No converter specified");
+ exception.add("type", type.getName());
+ throw exception;
}
public void registerConverter(Converter converter, int priority) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java b/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java
index 5b47e5e..9ef7479 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectInputStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2010, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2010, 2011, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -20,9 +20,10 @@
import java.io.StreamCorruptedException;
import java.util.Map;
-import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.core.ClassLoaderReference;
+import com.thoughtworks.xstream.io.StreamException;
public class CustomObjectInputStream extends ObjectInputStream {
@@ -63,8 +64,10 @@
result.pushCallback(callback);
}
return result;
+ } catch (SecurityException e) {
+ throw new ObjectAccessException("Cannot create CustomObjectStream", e);
} catch (IOException e) {
- throw new ConversionException("Cannot create CustomObjectStream", e);
+ throw new StreamException("Cannot create CustomObjectStream", e);
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java b/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java
index 09a2cdf..a354005 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/util/CustomObjectOutputStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -16,8 +16,9 @@
import java.io.ObjectOutputStream;
import java.util.Map;
-import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.DataHolder;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
+import com.thoughtworks.xstream.io.StreamException;
public class CustomObjectOutputStream extends ObjectOutputStream {
@@ -36,8 +37,10 @@
result.pushCallback(callback);
}
return result;
+ } catch (SecurityException e) {
+ throw new ObjectAccessException("Cannot create CustomObjectStream", e);
} catch (IOException e) {
- throw new ConversionException("Cannot create CustomObjectStream", e);
+ throw new StreamException("Cannot create CustomObjectStream", e);
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/util/DependencyInjectionFactory.java b/xstream/src/java/com/thoughtworks/xstream/core/util/DependencyInjectionFactory.java
index b7cb672..293d4b6 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/util/DependencyInjectionFactory.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/util/DependencyInjectionFactory.java
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2007, 2009, 2010, 2011, 2012, 2013 XStream Committers.
+ * Copyright (c) 2007, 2009, 2010, 2011, 2012, 2013, 2016 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 30. March 2007 by Joerg Schaible
*/
package com.thoughtworks.xstream.core.util;
@@ -23,7 +23,7 @@
/**
* A dependency injection factory.
- *
+ *
* @author Jörg Schaible
* @since 1.2.2
*/
@@ -35,7 +35,7 @@
* matching the sequence of the dependencies' types match first. Otherwise all the types of the dependencies must
* match one of the the parameters although no dependency is used twice. Use a {@link TypedNull} instance to inject
* null
as parameter.
- *
+ *
* @param type the type to create an instance of
* @param dependencies the possible dependencies
* @return the instantiated object
@@ -46,14 +46,14 @@
public static Object newInstance(final Class type, final Object[] dependencies) {
return newInstance(type, dependencies, null);
}
-
+
/**
* Create an instance with dependency injection. The given dependencies are used to match the parameters of the
* constructors of the type. Constructors with most parameters are examined first. A parameter type sequence
* matching the sequence of the dependencies' types match first. Otherwise all the types of the dependencies must
* match one of the the parameters although no dependency is used twice. Use a {@link TypedNull} instance to inject
* null
as parameter.
- *
+ *
* @param type the type to create an instance of
* @param dependencies the possible dependencies
* @param usedDependencies bit mask set by the method for all used dependencies (may be null
)
@@ -85,7 +85,7 @@
}
final TypedValue[] typedDependencies = new TypedValue[dependencies.length];
- for (int i = 0; i < dependencies.length; i++ ) {
+ for (int i = 0; i < dependencies.length; i++) {
Object dependency = dependencies[i];
Class depType = dependency.getClass();
if (depType.isPrimitive()) {
@@ -100,7 +100,7 @@
Constructor possibleCtor = null;
int arity = Integer.MAX_VALUE;
- for (int i = 0; bestMatchingCtor == null && i < ctors.length; i++ ) {
+ for (int i = 0; bestMatchingCtor == null && i < ctors.length; i++) {
final Constructor constructor = ctors[i];
final Class[] parameterTypes = constructor.getParameterTypes();
if (parameterTypes.length > dependencies.length) {
@@ -118,7 +118,7 @@
arity = parameterTypes.length;
}
- for (int j = 0; j < parameterTypes.length; j++ ) {
+ for (int j = 0; j < parameterTypes.length; j++) {
if (parameterTypes[j].isPrimitive()) {
parameterTypes[j] = Primitives.box(parameterTypes[j]);
}
@@ -129,11 +129,11 @@
matchingDependencies.clear();
usedDeps = 0;
for (int j = 0, k = 0; j < parameterTypes.length
- && parameterTypes.length + k - j <= typedDependencies.length; k++ ) {
+ && parameterTypes.length + k - j <= typedDependencies.length; k++) {
if (parameterTypes[j].isAssignableFrom(typedDependencies[k].type)) {
matchingDependencies.add(typedDependencies[k].value);
- usedDeps |= 1L << k;
- if ( ++j == parameterTypes.length) {
+ usedDeps |= 1L << k;
+ if (++j == parameterTypes.length) {
bestMatchingCtor = constructor;
break;
}
@@ -151,7 +151,7 @@
usedDeps = 0;
for (int j = 0; j < parameterTypes.length; j++ ) {
int assignable = -1;
- for (int k = 0; k < deps.length; k++ ) {
+ for (int k = 0; k < deps.length; k++) {
if (deps[k] == null) {
continue;
}
@@ -162,8 +162,8 @@
} else if (parameterTypes[j].isAssignableFrom(deps[k].type)) {
// use most specific type
if (assignable < 0
- || (deps[assignable].type != deps[k].type && deps[assignable].type
- .isAssignableFrom(deps[k].type))) {
+ || deps[assignable].type != deps[k].type
+ && deps[assignable].type.isAssignableFrom(deps[k].type)) {
assignable = k;
}
}
@@ -178,7 +178,7 @@
break;
}
}
-
+
if (possible) {
// the smaller the value, the smaller the indices in the deps array
if (possibleCtor != null && usedDeps >= possibleUsedDeps) {
@@ -194,9 +194,10 @@
if (bestMatchingCtor == null) {
if (possibleCtor == null) {
usedDeps = 0;
- throw new ObjectAccessException("Cannot construct "
- + type.getName()
- + ", none of the dependencies match any constructor's parameters");
+ final ObjectAccessException ex = new ObjectAccessException(
+ "Cannot construct type, none of the arguments match any constructor's parameters");
+ ex.add("construction-type", type.getName());
+ throw ex;
} else {
bestMatchingCtor = possibleCtor;
matchingDependencies.clear();
@@ -206,6 +207,7 @@
}
}
+ Throwable th = null;
try {
final Object instance;
if (bestMatchingCtor == null) {
@@ -216,7 +218,7 @@
if (usedDependencies != null) {
usedDependencies.clear();
int i = 0;
- for(long l = 1; l < usedDeps; l <<= 1, ++i) {
+ for (long l = 1; l < usedDeps; l <<= 1, ++i) {
if ((usedDeps & l) > 0) {
usedDependencies.set(i);
}
@@ -224,16 +226,19 @@
}
return instance;
} catch (final InstantiationException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ th = e;
} catch (final IllegalAccessException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ th = e;
} catch (final InvocationTargetException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ th = e.getCause();
} catch (final SecurityException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ th = e;
} catch (final ExceptionInInitializerError e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- }
+ th = e;
+ }
+ final ObjectAccessException ex = new ObjectAccessException("Cannot construct type", th);
+ ex.add("construction-type", type.getName());
+ throw ex;
}
private static class TypedValue {
@@ -246,8 +251,7 @@
this.value = value;
}
- public String toString()
- {
+ public String toString() {
return type.getName() + ":" + value;
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/util/Fields.java b/xstream/src/java/com/thoughtworks/xstream/core/util/Fields.java
index 368353a..32d179c 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/util/Fields.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/util/Fields.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2016 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. April 2004 by Joe Walnes
*/
package com.thoughtworks.xstream.core.util;
@@ -16,18 +16,19 @@
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
+
/**
- * Slightly nicer way to find, get and set fields in classes. Wraps standard java.lang.reflect.Field calls but wraps
- * wraps exception in XStreamExceptions.
+ * Slightly nicer way to find, get and set fields in classes. Wraps standard java.lang.reflect.Field calls and turns
+ * exceptions into XStreamExceptions.
*
* @author Joe Walnes
* @author Jörg Schaible
*/
public class Fields {
- public static Field locate(Class definedIn, Class fieldType, boolean isStatic) {
+ public static Field locate(final Class definedIn, final Class fieldType, final boolean isStatic) {
Field field = null;
try {
- Field[] fields = definedIn.getDeclaredFields();
+ final Field[] fields = definedIn.getDeclaredFields();
for(int i = 0; i < fields.length; ++i) {
if (Modifier.isStatic(fields[i].getModifiers()) == isStatic) {
if (fieldType.isAssignableFrom(fields[i].getType())) {
@@ -38,45 +39,62 @@
if (field != null && !field.isAccessible()) {
field.setAccessible(true);
}
- } catch (SecurityException e) {
+ } catch (final SecurityException e) {
// active SecurityManager
- } catch (NoClassDefFoundError e) {
+ } catch (final NoClassDefFoundError e) {
// restricted type in GAE
}
return field;
}
- public static Field find(Class type, String name) {
+ public static Field find(final Class type, final String name) {
try {
- Field result = type.getDeclaredField(name);
+ final Field result = type.getDeclaredField(name);
if (!result.isAccessible()) {
result.setAccessible(true);
}
return result;
- } catch (NoSuchFieldException e) {
- throw new IllegalArgumentException("Could not access " + type.getName() + "." + name + " field: " + e.getMessage());
- } catch (NoClassDefFoundError e) {
- throw new ObjectAccessException("Could not access " + type.getName() + "." + name + " field: " + e.getMessage());
+ } catch (final SecurityException e) {
+ throw wrap("Cannot access field", type, name, e);
+ } catch (final NoSuchFieldException e) {
+ throw wrap("Cannot access field", type, name, e);
+ } catch (final NoClassDefFoundError e) {
+ throw wrap("Cannot access field", type, name, e);
}
}
- public static void write(Field field, Object instance, Object value) {
+ public static void write(final Field field, final Object instance, final Object value) {
try {
field.set(instance, value);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not write " + field.getType().getName() + "." + field.getName() + " field", e);
- } catch (NoClassDefFoundError e) {
- throw new ObjectAccessException("Could not write " + field.getType().getName() + "." + field.getName() + " field", e);
+ } catch (final SecurityException e) {
+ throw wrap("Cannot write field", field.getType(), field.getName(), e);
+ } catch (final IllegalArgumentException e) {
+ throw wrap("Cannot write field", field.getType(), field.getName(), e);
+ } catch (final IllegalAccessException e) {
+ throw wrap("Cannot write field", field.getType(), field.getName(), e);
+ } catch (final NoClassDefFoundError e) {
+ throw wrap("Cannot write field", field.getType(), field.getName(), e);
}
}
- public static Object read(Field field, Object instance) {
+ public static Object read(final Field field, final Object instance) {
try {
return field.get(instance);
- } catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not read " + field.getType().getName() + "." + field.getName() + " field", e);
- } catch (NoClassDefFoundError e) {
- throw new ObjectAccessException("Could not read " + field.getType().getName() + "." + field.getName() + " field", e);
+ } catch (final SecurityException e) {
+ throw wrap("Cannot read field", field.getType(), field.getName(), e);
+ } catch (final IllegalArgumentException e) {
+ throw wrap("Cannot read field", field.getType(), field.getName(), e);
+ } catch (final IllegalAccessException e) {
+ throw wrap("Cannot read field", field.getType(), field.getName(), e);
+ } catch (final NoClassDefFoundError e) {
+ throw wrap("Cannot read field", field.getType(), field.getName(), e);
}
}
+
+ private static ObjectAccessException wrap(final String message, final Class type, final String name,
+ final Throwable ex) {
+ final ObjectAccessException exception = new ObjectAccessException(message, ex);
+ exception.add("field", type.getName() + "." + name);
+ return exception;
+ }
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/util/SerializationMembers.java b/xstream/src/java/com/thoughtworks/xstream/core/util/SerializationMembers.java
index 505df5d..b8fc632 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/util/SerializationMembers.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/util/SerializationMembers.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2014, 2015 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2014, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -24,6 +24,7 @@
import java.util.Map;
import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.ErrorWritingException;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.core.Caching;
@@ -72,17 +73,16 @@
final Class resultType = result.getClass();
final Method readResolveMethod = getRRMethod(resultType, "readResolve");
if (readResolveMethod != null) {
+ ErrorWritingException ex = null;
try {
return readResolveMethod.invoke(result, EMPTY_ARGS);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not call "
- + resultType.getName()
- + ".readResolve()", e);
+ ex = new ObjectAccessException("Cannot access method", e);
} catch (InvocationTargetException e) {
- throw new ObjectAccessException("Could not call "
- + resultType.getName()
- + ".readResolve()", e.getTargetException());
- }
+ ex = new ConversionException("Failed calling method", e.getTargetException());
+ }
+ ex.add("method", resultType.getName() + ".readResolve()");
+ throw ex;
} else {
return result;
}
@@ -96,17 +96,16 @@
final Class objectType = object.getClass();
final Method writeReplaceMethod = getRRMethod(objectType, "writeReplace");
if (writeReplaceMethod != null) {
+ ErrorWritingException ex = null;
try {
return writeReplaceMethod.invoke(object, EMPTY_ARGS);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not call "
- + objectType.getName()
- + ".writeReplace()", e);
+ ex = new ObjectAccessException("Cannot access method", e);
} catch (InvocationTargetException e) {
- throw new ObjectAccessException("Could not call "
- + objectType.getName()
- + ".writeReplace()", e.getTargetException());
- }
+ ex = new ConversionException("Failed calling method", e.getTargetException());
+ }
+ ex.add("method", objectType.getName() + ".writeReplace()");
+ throw ex;
} else {
return object;
}
@@ -119,18 +118,19 @@
}
public void callReadObject(final Class type, final Object object, final ObjectInputStream stream) {
+ ErrorWritingException ex = null;
try {
Method readObjectMethod = getMethod(
type, "readObject", new Class[]{ObjectInputStream.class}, false);
readObjectMethod.invoke(object, new Object[]{stream});
} catch (IllegalAccessException e) {
- throw new ConversionException("Could not call "
- + object.getClass().getName()
- + ".readObject()", e);
+ ex = new ObjectAccessException("Cannot access method", e);
} catch (InvocationTargetException e) {
- throw new ConversionException("Could not call "
- + object.getClass().getName()
- + ".readObject()", e.getTargetException());
+ ex = new ConversionException("Failed calling method", e.getTargetException());
+ }
+ if (ex != null) {
+ ex.add("method", object.getClass().getName() + ".readObject()");
+ throw ex;
}
}
@@ -140,18 +140,19 @@
}
public void callWriteObject(final Class type, final Object instance, final ObjectOutputStream stream) {
+ ErrorWritingException ex = null;
try {
Method readObjectMethod = getMethod(
type, "writeObject", new Class[]{ObjectOutputStream.class}, false);
readObjectMethod.invoke(instance, new Object[]{stream});
} catch (IllegalAccessException e) {
- throw new ConversionException("Could not call "
- + instance.getClass().getName()
- + ".writeObject()", e);
+ ex = new ObjectAccessException("Cannot access method", e);
} catch (InvocationTargetException e) {
- throw new ConversionException("Could not call "
- + instance.getClass().getName()
- + ".writeObject()", e.getTargetException());
+ ex = new ConversionException("Failed calling method", e.getTargetException());
+ }
+ if (ex != null) {
+ ex.add("method", instance.getClass().getName() + ".writeObject()");
+ throw ex;
}
}
@@ -210,6 +211,7 @@
}
Map result = (Map)fieldCache.get(type.getName());
if (result == null) {
+ ErrorWritingException ex = null;
try {
final Field field = type.getDeclaredField("serialPersistentFields");
if ((field.getModifiers() & PERSISTENT_FIELDS_MODIFIER) == PERSISTENT_FIELDS_MODIFIER) {
@@ -224,9 +226,13 @@
}
} catch (final NoSuchFieldException e) {
} catch (final IllegalAccessException e) {
- throw new ObjectAccessException("Cannot get " + type.getName() + ".serialPersistentFields.", e);
+ ex = new ObjectAccessException("Cannot get field", e);
} catch (final ClassCastException e) {
- throw new ObjectAccessException("Cannot get " + type.getName() + ".serialPersistentFields.", e);
+ ex = new ConversionException("Incompatible field type", e);
+ }
+ if (ex != null) {
+ ex.add("field", type.getName() + ".serialPersistentFields");
+ throw ex;
}
if (result == null) {
result = NO_FIELDS;
diff --git a/xstream/src/java/com/thoughtworks/xstream/core/util/ThreadSafePropertyEditor.java b/xstream/src/java/com/thoughtworks/xstream/core/util/ThreadSafePropertyEditor.java
index 34c9953..af811ef 100644
--- a/xstream/src/java/com/thoughtworks/xstream/core/util/ThreadSafePropertyEditor.java
+++ b/xstream/src/java/com/thoughtworks/xstream/core/util/ThreadSafePropertyEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2008 XStream Committers.
+ * Copyright (c) 2007, 2008, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,6 +10,8 @@
*/
package com.thoughtworks.xstream.core.util;
+import com.thoughtworks.xstream.converters.ConversionException;
+import com.thoughtworks.xstream.converters.ErrorWritingException;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import java.beans.PropertyEditor;
@@ -44,15 +46,16 @@
editorType = type;
pool = new Pool(initialPoolSize, maxPoolSize, new Pool.Factory() {
public Object newInstance() {
+ ErrorWritingException ex = null;
try {
return editorType.newInstance();
} catch (InstantiationException e) {
- throw new ObjectAccessException("Could not call default constructor of "
- + editorType.getName(), e);
+ ex = new ConversionException("Faild to call default constructor", e);
} catch (IllegalAccessException e) {
- throw new ObjectAccessException("Could not call default constructor of "
- + editorType.getName(), e);
+ ex = new ObjectAccessException("Cannot call default constructor", e);
}
+ ex.add("construction-type", editorType.getName());
+ throw ex;
}
});
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/AbstractXppDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/AbstractXppDriver.java
index efcd59a..37d2a1f 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/AbstractXppDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/AbstractXppDriver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -52,8 +52,8 @@
public HierarchicalStreamReader createReader(Reader in) {
try {
return new XppReader(in, createParser(), getNameCoder());
- } catch (XmlPullParserException e) {
- throw new StreamException("Cannot create XmlPullParser");
+ } catch (final XmlPullParserException e) {
+ throw new StreamException("Cannot create XmlPullParser", e);
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/BEAStaxDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/BEAStaxDriver.java
index 3c67699..01efa8f 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/BEAStaxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/BEAStaxDriver.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2014, 2015 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. April 2009 by Joerg Schaible
*/
package com.thoughtworks.xstream.io.xml;
@@ -19,7 +19,7 @@
/**
* A driver using the BEA StAX implementation.
- *
+ *
* @author Jörg Schaible
* @since 1.4
*/
@@ -62,7 +62,11 @@
}
protected XMLInputFactory createInputFactory() {
- return new MXParserFactory();
+ final XMLInputFactory instance = new MXParserFactory();
+ instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+// if (instance.isPropertySupported(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES))
+// throw new IllegalStateException("Should not support external entities now!");
+ return instance;
}
protected XMLOutputFactory createOutputFactory() {
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JDriver.java
index bce7cff..7018f42 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JDriver.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2011, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -26,6 +26,7 @@
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
+import org.xml.sax.SAXException;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@@ -89,8 +90,7 @@
public HierarchicalStreamReader createReader(Reader text) {
try {
- SAXReader reader = new SAXReader();
- Document document = reader.read(text);
+ final Document document = createReader().read(text);
return new Dom4JReader(document, getNameCoder());
} catch (DocumentException e) {
throw new StreamException(e);
@@ -99,8 +99,7 @@
public HierarchicalStreamReader createReader(InputStream in) {
try {
- SAXReader reader = new SAXReader();
- Document document = reader.read(in);
+ final Document document = createReader().read(in);
return new Dom4JReader(document, getNameCoder());
} catch (DocumentException e) {
throw new StreamException(e);
@@ -112,8 +111,7 @@
*/
public HierarchicalStreamReader createReader(URL in) {
try {
- SAXReader reader = new SAXReader();
- Document document = reader.read(in);
+ final Document document = createReader().read(in);
return new Dom4JReader(document, getNameCoder());
} catch (DocumentException e) {
throw new StreamException(e);
@@ -125,8 +123,7 @@
*/
public HierarchicalStreamReader createReader(File in) {
try {
- SAXReader reader = new SAXReader();
- Document document = reader.read(in);
+ final Document document = createReader().read(in);
return new Dom4JReader(document, getNameCoder());
} catch (DocumentException e) {
throw new StreamException(e);
@@ -148,4 +145,21 @@
final Writer writer = new OutputStreamWriter(out);
return createWriter(writer);
}
+
+ /**
+ * Create and initialize the SAX reader.
+ *
+ * @return the SAX reader instance.
+ * @throws DocumentException if DOCTYPE processing cannot be disabled
+ * @since 1.4.9
+ */
+ protected SAXReader createReader() throws DocumentException {
+ final SAXReader reader = new SAXReader();
+ try {
+ reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ } catch (SAXException e) {
+ throw new DocumentException("Cannot disable DOCTYPE processing", e);
+ }
+ return reader;
+ }
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/DomDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/DomDriver.java
index 7b1709e..ae50fbe 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/DomDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/DomDriver.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2014, 2015 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.io.xml;
@@ -19,6 +19,8 @@
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
@@ -30,6 +32,8 @@
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.StreamException;
@@ -39,7 +43,7 @@
public class DomDriver extends AbstractXmlDriver {
private final String encoding;
- private final DocumentBuilderFactory documentBuilderFactory;
+ private DocumentBuilderFactory documentBuilderFactory;
/**
* Construct a DomDriver.
@@ -61,7 +65,6 @@
*/
public DomDriver(String encoding, NameCoder nameCoder) {
super(nameCoder);
- documentBuilderFactory = DocumentBuilderFactory.newInstance();
this.encoding = encoding;
}
@@ -91,7 +94,14 @@
private HierarchicalStreamReader createReader(InputSource source) {
try {
- DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ if (documentBuilderFactory == null) {
+ synchronized (this) {
+ if (documentBuilderFactory == null) {
+ documentBuilderFactory = createDocumentBuilderFactory();
+ }
+ }
+ }
+ final DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
if (encoding != null) {
source.setEncoding(encoding);
}
@@ -121,4 +131,34 @@
throw new StreamException(e);
}
}
+
+ /**
+ * Create the DocumentBuilderFactory instance.
+ *
+ * @return the new instance
+ * @since 1.4.9
+ */
+ protected DocumentBuilderFactory createDocumentBuilderFactory() {
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ if (JVM.is15()) {
+ try {
+ Method method = DocumentBuilderFactory.class.getMethod("setFeature",
+ new Class[]{ String.class, boolean.class });
+ method.invoke(factory, new Object[]{ "http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE });
+ } catch (NoSuchMethodException e) {
+ // Ignore
+ } catch (IllegalAccessException e) {
+ throw new ObjectAccessException("Cannot set feature of DocumentBuilderFactory.", e);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (JVM.is16()
+ || (cause instanceof ParserConfigurationException
+ && cause.getMessage().indexOf("disallow-doctype-decl") < 0)) {
+ throw new StreamException(cause);
+ }
+ }
+ }
+ factory.setExpandEntityReferences(false);
+ return factory;
+ }
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Driver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Driver.java
index 876630e..86f4170 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Driver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Driver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 XStream Committers.
+ * Copyright (C) 2013, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -47,8 +47,8 @@
public HierarchicalStreamReader createReader(Reader reader) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(reader);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(reader);
return new JDom2Reader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -59,8 +59,8 @@
public HierarchicalStreamReader createReader(InputStream in) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(in);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(in);
return new JDom2Reader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -71,8 +71,8 @@
public HierarchicalStreamReader createReader(URL in) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(in);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(in);
return new JDom2Reader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -83,8 +83,8 @@
public HierarchicalStreamReader createReader(File in) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(in);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(in);
return new JDom2Reader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -100,5 +100,17 @@
public HierarchicalStreamWriter createWriter(OutputStream out) {
return new PrettyPrintWriter(new OutputStreamWriter(out));
}
+
+ /**
+ * Create and initialize the SAX builder.
+ *
+ * @return the SAX builder instance.
+ * @since 1.4.9
+ */
+ protected SAXBuilder createBuilder() {
+ final SAXBuilder builder = new SAXBuilder();
+ builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ return builder;
+ }
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/JDomDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/JDomDriver.java
index 6bc3255..22a496b 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/JDomDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/JDomDriver.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -55,8 +55,8 @@
public HierarchicalStreamReader createReader(Reader reader) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(reader);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(reader);
return new JDomReader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -67,8 +67,8 @@
public HierarchicalStreamReader createReader(InputStream in) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(in);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(in);
return new JDomReader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -79,8 +79,8 @@
public HierarchicalStreamReader createReader(URL in) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(in);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(in);
return new JDomReader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -91,8 +91,8 @@
public HierarchicalStreamReader createReader(File in) {
try {
- SAXBuilder builder = new SAXBuilder();
- Document document = builder.build(in);
+ final SAXBuilder builder = createBuilder();
+ final Document document = builder.build(in);
return new JDomReader(document, getNameCoder());
} catch (IOException e) {
throw new StreamException(e);
@@ -109,5 +109,17 @@
return new PrettyPrintWriter(new OutputStreamWriter(out));
}
+ /**
+ * Create and initialize the SAX builder.
+ *
+ * @return the SAX builder instance.
+ * @since 1.4.9
+ */
+ protected SAXBuilder createBuilder() {
+ final SAXBuilder builder = new SAXBuilder();
+ builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ return builder;
+ }
+
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/QNameMap.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/QNameMap.java
index e047b13..06e7e96 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/QNameMap.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/QNameMap.java
@@ -22,7 +22,7 @@
* allowing class aliases and namespace aware mappings of QNames to class names.
*
* @author James Strachan
- * @version $Revision: 1345 $
+ * @version $Revision$
*/
public class QNameMap {
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/SjsxpDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/SjsxpDriver.java
index 26d8009..a8d4d77 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/SjsxpDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/SjsxpDriver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011, 2013 XStream Committers.
+ * Copyright (C) 2009, 2011, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -58,8 +58,10 @@
protected XMLInputFactory createInputFactory() {
Exception exception = null;
try {
- return (XMLInputFactory)Class.forName("com.sun.xml.internal.stream.XMLInputFactoryImpl").newInstance();
- } catch (InstantiationException e) {
+ final XMLInputFactory instance = (XMLInputFactory)Class.forName("com.sun.xml.internal.stream.XMLInputFactoryImpl").newInstance();
+ instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+ return instance;
+ } catch (final InstantiationException e) {
exception = e;
} catch (IllegalAccessException e) {
exception = e;
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/StandardStaxDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/StandardStaxDriver.java
index 1fe744d..272be6c 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/StandardStaxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/StandardStaxDriver.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2013 XStream Committers.
+ * Copyright (C) 2013, 2014, 2015 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 27. July 2013 by Joerg Schaible
*/
package com.thoughtworks.xstream.io.xml;
@@ -28,7 +28,7 @@
* implementations configured in lib/stax.properties or registered with the Service
* API.
*
- *
+ *
* @author Jörg Schaible
* @since 1.4.5
*/
@@ -75,7 +75,9 @@
try {
Class staxInputFactory = JVM.getStaxInputFactory();
if (staxInputFactory != null) {
- return (XMLInputFactory)staxInputFactory.newInstance();
+ final XMLInputFactory instance = (XMLInputFactory)staxInputFactory.newInstance();
+ instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+ return instance;
} else {
throw new StreamException("Java runtime has no standard XMLInputFactory implementation.", exception);
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxDriver.java
index b4c0086..d1ee523 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxDriver.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2011, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -40,7 +40,7 @@
*
* @author James Strachan
* @author Jörg Schaible
- * @version $Revision: 2116 $
+ * @version $Revision$
*/
public class StaxDriver extends AbstractXmlDriver {
@@ -238,7 +238,9 @@
* @since 1.4
*/
protected XMLInputFactory createInputFactory() {
- return XMLInputFactory.newInstance();
+ final XMLInputFactory instance = XMLInputFactory.newInstance();
+ instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+ return instance;
}
/**
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxReader.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxReader.java
index 08fe718..84e126f 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxReader.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxReader.java
@@ -24,7 +24,7 @@
* A reader using the StAX API.
*
* @author James Strachan
- * @version $Revision: 1861 $
+ * @version $Revision$
*/
public class StaxReader extends AbstractPullReader {
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxWriter.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxWriter.java
index 79410cc..6146717 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxWriter.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxWriter.java
@@ -23,7 +23,7 @@
* A stream writing that outputs to a StAX stream writer
*
* @author James Strachan
- * @version $Revision: 1906 $
+ * @version $Revision$
*/
public class StaxWriter extends AbstractXmlWriter {
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/WstxDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/WstxDriver.java
index fd9b316..d01f319 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/WstxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/WstxDriver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -62,7 +62,9 @@
}
protected XMLInputFactory createInputFactory() {
- return new WstxInputFactory();
+ final XMLInputFactory instance = new WstxInputFactory();
+ instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+ return instance;
}
protected XMLOutputFactory createOutputFactory() {
diff --git a/xstream/src/java/com/thoughtworks/xstream/io/xml/XomDriver.java b/xstream/src/java/com/thoughtworks/xstream/io/xml/XomDriver.java
index 5700ea6..d6c041d 100644
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/XomDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/XomDriver.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2011, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -35,9 +35,12 @@
private final Builder builder;
public XomDriver() {
- this(new Builder());
+ this(new XmlFriendlyNameCoder());
}
+ /**
+ * @deprecated As of 1.4.9, use {@link #XomDriver()} and overload {@link #createBuilder()} instead
+ */
public XomDriver(Builder builder) {
this(builder, new XmlFriendlyNameCoder());
}
@@ -46,40 +49,63 @@
* @since 1.4
*/
public XomDriver(NameCoder nameCoder) {
- this(new Builder(), nameCoder);
+ super(nameCoder);
+ this.builder = null;
}
/**
* @since 1.4
+ * @deprecated As of 1.4.9, use {@link #XomDriver(NameCoder)} and overload {@link #createBuilder()} instead
*/
public XomDriver(Builder builder, NameCoder nameCoder) {
- super(nameCoder);
+ super(nameCoder);
this.builder = builder;
}
/**
* @since 1.2
- * @deprecated As of 1.4, use {@link #XomDriver(Builder, NameCoder)} instead
+ * @deprecated As of 1.4, use {@link #XomDriver(NameCoder)} instead
*/
public XomDriver(XmlFriendlyReplacer replacer) {
- this(new Builder(), replacer);
+ this((NameCoder)replacer);
}
/**
* @since 1.2
- * @deprecated As of 1.4, use {@link #XomDriver(Builder, NameCoder)} instead
+ * @deprecated As of 1.4, use {@link #XomDriver(NameCoder)} and overload {@link #createBuilder()} instead
*/
public XomDriver(Builder builder, XmlFriendlyReplacer replacer) {
- this((NameCoder)replacer);
+ this(builder, (NameCoder)replacer);
}
+ /**
+ * @deprecated As of 1.4.9, overload {@link #createBuilder()} instead
+ */
protected Builder getBuilder() {
return this.builder;
}
+ /**
+ * Create the Builder instance.
+ *
+ * A XOM builder is a wrapper around a {@link org.xml.sax.XMLReader}
+ * instance which is not thread-safe by definition. Therefore each reader
+ * should use its own builder instance to avoid concurrency problems.
+ *
+ * Overload this method to configure the generated builder instances e.g.
+ * to activate validation.
+ *
+ * @return the new builder
+ * @since 1.4.9
+ */
+ protected Builder createBuilder() {
+ final Builder builder = getBuilder();
+ return builder != null ? builder : new Builder();
+ }
+
public HierarchicalStreamReader createReader(Reader text) {
try {
- Document document = builder.build(text);
+ final Document document = createBuilder().build(text);
return new XomReader(document, getNameCoder());
} catch (ValidityException e) {
throw new StreamException(e);
@@ -92,7 +118,7 @@
public HierarchicalStreamReader createReader(InputStream in) {
try {
- Document document = builder.build(in);
+ final Document document = createBuilder().build(in);
return new XomReader(document, getNameCoder());
} catch (ValidityException e) {
throw new StreamException(e);
@@ -105,7 +131,7 @@
public HierarchicalStreamReader createReader(URL in) {
try {
- Document document = builder.build(in.toExternalForm());
+ final Document document = createBuilder().build(in.toExternalForm());
return new XomReader(document, getNameCoder());
} catch (ValidityException e) {
throw new StreamException(e);
@@ -118,7 +144,7 @@
public HierarchicalStreamReader createReader(File in) {
try {
- Document document = builder.build(in);
+ final Document document = createBuilder().build(in);
return new XomReader(document, getNameCoder());
} catch (ValidityException e) {
throw new StreamException(e);
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/AnnotationMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/AnnotationMapper.java
index 7d0e78e..e8145e9 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/AnnotationMapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/AnnotationMapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009, 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2007, 2008, 2009, 2011, 2012, 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -505,12 +505,13 @@
if (array != null) {
int length = Array.getLength(array);
for (int i = 0; i < length; i++ ) {
- Object object = Array.get(array, i);
- if (!parameter.contains(object)) {
- parameter.add(object);
- }
- }
- }
+ parameter.add(Array.get(array, i));
+ }
+ }
+ }
+ for (final Class> type : annotation.nulls()) {
+ final TypedNull nullType = new TypedNull(type);
+ parameter.add(nullType);
}
final Class extends ConverterMatcher> converterType = annotation.value();
Map, Converter> converterMapping = converterCache.get(converterType);
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/ClassAliasingMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/ClassAliasingMapper.java
index c235db2..20cef9e 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/ClassAliasingMapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/ClassAliasingMapper.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -79,10 +79,16 @@
return super.realClass(elementName);
}
+ /**
+ * @deprecated As of 1.4.9
+ */
public boolean itemTypeAsAttribute(Class clazz) {
- return classToName.containsKey(clazz);
+ return classToName.containsKey(clazz.getName());
}
+ /**
+ * @deprecated As of 1.4.9
+ */
public boolean aliasIsAttribute(String name) {
return nameToType.containsKey(name);
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/DefaultMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/DefaultMapper.java
index 4d029b8..c4a1d6d 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/DefaultMapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/DefaultMapper.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2015 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. January 2005 by Joe Walnes
*/
package com.thoughtworks.xstream.mapper;
@@ -18,8 +18,10 @@
/**
- * Default mapper implementation with 'vanilla' functionality. To build up the functionality required, wrap this mapper
- * with other mapper implementations.
+ * Default mapper implementation with 'vanilla' functionality.
+ *
+ * To build up the functionality required, wrap this mapper with other mapper implementations.
+ *
*
* @author Joe Walnes
* @author Jörg Schaible
@@ -38,7 +40,7 @@
/**
* Construct a DefaultMapper.
- *
+ *
* @param classLoaderReference the reference to the classloader used by the XStream instance.
* @since 1.4.5
*/
@@ -48,7 +50,7 @@
/**
* Construct a DefaultMapper.
- *
+ *
* @param classLoader the ClassLoader used by the XStream instance.
* @deprecated As of 1.4.5 use {@link #DefaultMapper(ClassLoaderReference)}
*/
@@ -98,6 +100,10 @@
public boolean isImmutableValueType(Class type) {
return false;
+ }
+
+ public boolean isReferenceable(final Class type) {
+ return true;
}
public String getFieldNameForItemTypeAndName(Class definedIn, Class itemType, String itemFieldName) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/EnumMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/EnumMapper.java
index f46e4c2..d562126 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/EnumMapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/EnumMapper.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2015 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 20. March 2005 by Joe Walnes
*/
package com.thoughtworks.xstream.mapper;
@@ -22,11 +22,10 @@
/**
- * Mapper that handles the special case of polymorphic enums in Java 1.5. This renames MyEnum$1
- * to MyEnum making it less bloaty in the XML and avoiding the need for an alias per enum value
- * to be specified. Additionally every enum is treated automatically as immutable type and can
- * be written as attribute.
- *
+ * Mapper that handles the special case of polymorphic enums in Java 1.5. This renames MyEnum$1 to MyEnum making it less
+ * bloaty in the XML and avoiding the need for an alias per enum value to be specified. Additionally every enum is
+ * treated automatically as immutable and non-refrenceable type that can be written as attribute.
+ *
* @author Joe Walnes
* @author Jörg Schaible
*/
@@ -69,12 +68,21 @@
}
@Override
+ public boolean isReferenceable(final Class type) {
+ if (type != null && Enum.class.isAssignableFrom(type)) {
+ return false;
+ } else {
+ return super.isReferenceable(type);
+ }
+ }
+
+ @Override
public SingleValueConverter getConverterFromItemType(String fieldName, Class type,
- Class definedIn) {
- SingleValueConverter converter = getLocalConverter(fieldName, type, definedIn);
- return converter == null
- ? super.getConverterFromItemType(fieldName, type, definedIn)
- : converter;
+ Class definedIn) {
+ SingleValueConverter converter = getLocalConverter(fieldName, type, definedIn);
+ return converter == null
+ ? super.getConverterFromItemType(fieldName, type, definedIn)
+ : converter;
}
@Override
@@ -88,8 +96,8 @@
private SingleValueConverter getLocalConverter(String fieldName, Class type, Class definedIn) {
if (attributeMapper != null
- && Enum.class.isAssignableFrom(type)
- && attributeMapper.shouldLookForSingleValueConverter(fieldName, type, definedIn)) {
+ && Enum.class.isAssignableFrom(type)
+ && attributeMapper.shouldLookForSingleValueConverter(fieldName, type, definedIn)) {
synchronized (enumConverterMap) {
SingleValueConverter singleValueConverter = enumConverterMap.get(type);
if (singleValueConverter == null) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/ImmutableTypesMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/ImmutableTypesMapper.java
index f6db320..b218807 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/ImmutableTypesMapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/ImmutableTypesMapper.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2015 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. January 2005 by Joe Walnes
*/
package com.thoughtworks.xstream.mapper;
@@ -17,19 +17,44 @@
/**
* Mapper that specifies which types are basic immutable types. Types that are marked as immutable will be written
* multiple times in the serialization stream without using references.
+ *
+ * Note, that an already persisted stream might still contain references for immutable types. They can be dereferenced
+ * at deserialization time, unless the type is explicitly declared as unreferenceable. However, this is only possible at
+ * the expense of memory book-keeping all instances.
+ *
*
* @author Joe Walnes
*/
public class ImmutableTypesMapper extends MapperWrapper {
+ private final Set unreferenceableTypes = new HashSet();
private final Set immutableTypes = new HashSet();
public ImmutableTypesMapper(Mapper wrapped) {
super(wrapped);
}
+ /**
+ * @deprecated As of 1.4.9 use {@link #addImmutableType(Class, boolean)}
+ */
public void addImmutableType(Class type) {
+ addImmutableType(type, true);
+ }
+
+ /**
+ * Declare a type as immutable.
+ *
+ * @param type the immutable type
+ * @param isReferenceable flag for possible references
+ * @since 1.4.9
+ */
+ public void addImmutableType(final Class type, final boolean isReferenceable) {
immutableTypes.add(type);
+ if (!isReferenceable) {
+ unreferenceableTypes.add(type);
+ } else {
+ unreferenceableTypes.remove(type);
+ }
}
public boolean isImmutableValueType(Class type) {
@@ -40,4 +65,11 @@
}
}
+ public boolean isReferenceable(final Class type) {
+ if (unreferenceableTypes.contains(type)) {
+ return false;
+ } else {
+ return super.isReferenceable(type);
+ }
+ }
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/ImplicitCollectionMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/ImplicitCollectionMapper.java
index 36eca76..2eb442b 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/ImplicitCollectionMapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/ImplicitCollectionMapper.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2011, 2012, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2011, 2012, 2013, 2014, 2015 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. February 2005 by Joe Walnes
*/
package com.thoughtworks.xstream.mapper;
@@ -15,6 +15,7 @@
import com.thoughtworks.xstream.core.util.Primitives;
import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -30,12 +31,27 @@
// { definedIn (Class) -> (ImplicitCollectionMapperForClass) }
private final Map classNameToMapper = new HashMap();
- private ImplicitCollectionMapperForClass getMapper(Class definedIn) {
+ private ImplicitCollectionMapperForClass getMapper(final Class declaredFor, final String fieldName) {
+ Class definedIn = declaredFor;
while (definedIn != null) {
ImplicitCollectionMapperForClass mapper = (ImplicitCollectionMapperForClass)classNameToMapper
.get(definedIn);
if (mapper != null) {
return mapper;
+ } else {
+ if (fieldName != null) {
+ try {
+ // do not continue search for a hidden field
+ final Field field = definedIn.getDeclaredField(fieldName);
+ if (field != null && !Modifier.isStatic(field.getModifiers())) {
+ return null;
+ }
+ } catch (final SecurityException e) {
+ throw new InitializationException("Access denied for field with implicit collection", e);
+ } catch (final NoSuchFieldException e) {
+ // OK, we can continue the search in the class hierarchy
+ }
+ }
}
definedIn = definedIn.getSuperclass();
}
@@ -54,7 +70,7 @@
public String getFieldNameForItemTypeAndName(Class definedIn, Class itemType,
String itemFieldName) {
- ImplicitCollectionMapperForClass mapper = getMapper(definedIn);
+ ImplicitCollectionMapperForClass mapper = getMapper(definedIn, null);
if (mapper != null) {
return mapper.getFieldNameForItemTypeAndName(itemType, itemFieldName);
} else {
@@ -63,7 +79,7 @@
}
public Class getItemTypeForItemFieldName(Class definedIn, String itemFieldName) {
- ImplicitCollectionMapperForClass mapper = getMapper(definedIn);
+ ImplicitCollectionMapperForClass mapper = getMapper(definedIn, null);
if (mapper != null) {
return mapper.getItemTypeForItemFieldName(itemFieldName);
} else {
@@ -73,7 +89,7 @@
public ImplicitCollectionMapping getImplicitCollectionDefForFieldName(Class itemType,
String fieldName) {
- ImplicitCollectionMapperForClass mapper = getMapper(itemType);
+ ImplicitCollectionMapperForClass mapper = getMapper(itemType, fieldName);
if (mapper != null) {
return mapper.getImplicitCollectionDefForFieldName(fieldName);
} else {
@@ -91,16 +107,20 @@
public void add(Class definedIn, String fieldName, String itemFieldName, Class itemType, String keyFieldName) {
Field field = null;
- Class declaredIn = definedIn;
- while (declaredIn != Object.class && definedIn != null) {
- try {
- field = declaredIn.getDeclaredField(fieldName);
- break;
- } catch (SecurityException e) {
- throw new InitializationException(
- "Access denied for field with implicit collection", e);
- } catch (NoSuchFieldException e) {
- declaredIn = declaredIn.getSuperclass();
+ if (definedIn != null) {
+ Class declaredIn = definedIn;
+ while (declaredIn != Object.class) {
+ try {
+ field = declaredIn.getDeclaredField(fieldName);
+ if (!Modifier.isStatic(field.getModifiers())) {
+ break;
+ }
+ field = null;
+ } catch (final SecurityException e) {
+ throw new InitializationException("Access denied for field with implicit collection", e);
+ } catch (final NoSuchFieldException e) {
+ declaredIn = declaredIn.getSuperclass();
+ }
}
}
if (field == null) {
@@ -177,7 +197,7 @@
if (unnamed != null) {
return unnamed.getFieldName();
} else {
- ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass());
+ ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getFieldNameForItemTypeAndName(itemType, itemFieldName) : null;
}
}
@@ -187,7 +207,7 @@
if (def != null) {
return def.getItemType();
} else {
- ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass());
+ ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getItemTypeForItemFieldName(itemFieldName) : null;
}
}
@@ -201,7 +221,7 @@
if (mapping != null) {
return mapping;
} else {
- ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass());
+ ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getImplicitCollectionDefByItemFieldName(itemFieldName) : null;
}
}
@@ -212,7 +232,7 @@
if (mapping != null) {
return mapping;
} else {
- ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass());
+ ImplicitCollectionMapperForClass mapper = ImplicitCollectionMapper.this.getMapper(definedIn.getSuperclass(), null);
return mapper != null ? mapper.getImplicitCollectionDefForFieldName(fieldName) : null;
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/Mapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/Mapper.java
index 17bcaeb..3760ab2 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/Mapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/Mapper.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2015 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. January 2005 by Joe Walnes
*/
package com.thoughtworks.xstream.mapper;
@@ -41,16 +41,23 @@
String realMember(Class type, String serialized);
/**
- * Whether this type is a simple immutable value (int, boolean, String, URL, etc.
- * Immutable types will be repeatedly written in the serialized stream, instead of using object references.
+ * Whether this type is a simple immutable value (int, boolean, String, URL, etc). Immutable types will be
+ * repeatedly written in the serialized stream, instead of using object references.
*/
boolean isImmutableValueType(Class type);
+
+ /**
+ * Whether this type is referenceable in a stream.
+ *
+ * @since 1.4.9
+ */
+ boolean isReferenceable(Class type);
Class defaultImplementationOf(Class type);
/**
* Get the alias for an attribute's name.
- *
+ *
* @param attribute the attribute
* @return the alias
* @since 1.2
@@ -59,7 +66,7 @@
/**
* Get the attribute's name for an alias.
- *
+ *
* @param alias the alias
* @return the attribute's name
* @since 1.2
@@ -68,7 +75,7 @@
/**
* Get the alias for a system attribute's name.
- *
+ *
* @param attribute the system attribute
* @return the alias
* @since 1.3.1
@@ -78,8 +85,8 @@
/**
* Get the name of the field that acts as the default collection for an object, or return null if there is none.
*
- * @param definedIn owning type
- * @param itemType item type
+ * @param definedIn owning type
+ * @param itemType item type
* @param itemFieldName optional item element name
*/
String getFieldNameForItemTypeAndName(Class definedIn, Class itemType, String itemFieldName);
@@ -123,7 +130,7 @@
/**
* Returns a single value converter to be used in a specific field.
- *
+ *
* @param fieldName the field name
* @param type the field type
* @param definedIn the type which defines this field
@@ -157,7 +164,7 @@
/**
* Returns which converter to use for an specific attribute in a type.
- *
+ *
* @param definedIn the field's parent
* @param attribute the attribute name
* @deprecated As of 1.3.1, use {@link #getConverterFromAttribute(Class, String, Class)}
@@ -166,7 +173,7 @@
/**
* Returns which converter to use for an specific attribute in a type.
- *
+ *
* @param definedIn the field's parent
* @param attribute the attribute name
* @param type the type the converter should create
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/MapperWrapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/MapperWrapper.java
index 93ced3d..71649f8 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/MapperWrapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/MapperWrapper.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -40,6 +40,10 @@
public boolean isImmutableValueType(Class type) {
return wrapped.isImmutableValueType(type);
+ }
+
+ public boolean isReferenceable(Class type) {
+ return wrapped.isReferenceable(type);
}
public Class defaultImplementationOf(Class type) {
diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/OuterClassMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/OuterClassMapper.java
index f98c514..6b136bc 100644
--- a/xstream/src/java/com/thoughtworks/xstream/mapper/OuterClassMapper.java
+++ b/xstream/src/java/com/thoughtworks/xstream/mapper/OuterClassMapper.java
@@ -1,24 +1,34 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2015 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 31. January 2005 by Joe Walnes
*/
package com.thoughtworks.xstream.mapper;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.thoughtworks.xstream.core.Caching;
+
/**
* Mapper that uses a more meaningful alias for the field in an inner class (this$0) that refers to the outer class.
*
* @author Joe Walnes
*/
-public class OuterClassMapper extends MapperWrapper {
+public class OuterClassMapper extends MapperWrapper implements Caching {
+ private static final String[] EMPTY_NAMES = new String[0];
private final String alias;
+ private final Map innerFields;
public OuterClassMapper(Mapper wrapped) {
this(wrapped, "outer-class");
@@ -27,21 +37,61 @@
public OuterClassMapper(Mapper wrapped, String alias) {
super(wrapped);
this.alias = alias;
+ innerFields = Collections.synchronizedMap(new HashMap());
+ innerFields.put(Object.class.getName(), EMPTY_NAMES);
}
public String serializedMember(Class type, String memberName) {
- if (memberName.equals("this$0")) {
- return alias;
- } else {
- return super.serializedMember(type, memberName);
+ if (memberName.startsWith("this$")) {
+ final String[] innerFieldNames = getInnerFieldNames(type);
+ for (int i = 0; i < innerFieldNames.length; ++i) {
+ if (innerFieldNames[i].equals(memberName)) {
+ return i == 0 ? alias : alias + '-' + i;
+ }
+ }
}
+ return super.serializedMember(type, memberName);
}
public String realMember(Class type, String serialized) {
- if (serialized.equals(alias)) {
- return "this$0";
- } else {
- return super.realMember(type, serialized);
+ if (serialized.startsWith(alias)) {
+ int idx = -1;
+ final int len = alias.length();
+ if (len == serialized.length()) {
+ idx = 0;
+ } else if (serialized.length() > len + 1 && serialized.charAt(len) == '-') {
+ idx = Integer.valueOf(serialized.substring(len + 1)).intValue();
+ }
+ if (idx >= 0) {
+ final String[] innerFieldNames = getInnerFieldNames(type);
+ if (idx < innerFieldNames.length) {
+ return innerFieldNames[idx];
+ }
+ }
}
+ return super.realMember(type, serialized);
+ }
+
+ private String[] getInnerFieldNames(final Class type) {
+ String[] innerFieldNames = (String[])innerFields.get(type.getName());
+ if (innerFieldNames == null) {
+ innerFieldNames = getInnerFieldNames(type.getSuperclass());
+ Field[] declaredFields = type.getDeclaredFields();
+ for (int i = 0; i < declaredFields.length; i++) {
+ final Field field = declaredFields[i];
+ if (field.getName().startsWith("this$")) {
+ String[] temp = new String[innerFieldNames.length+1];
+ System.arraycopy(innerFieldNames, 0, temp, 0, innerFieldNames.length);
+ innerFieldNames = temp;
+ innerFieldNames[innerFieldNames.length - 1] = field.getName();
+ }
+ }
+ innerFields.put(type.getName(), innerFieldNames);
+ }
+ return innerFieldNames;
+ }
+
+ public void flushCache() {
+ innerFields.keySet().retainAll(Collections.singletonList(Object.class.getName()));
}
}
diff --git a/xstream/src/java/com/thoughtworks/xstream/persistence/FilePersistenceStrategy.java b/xstream/src/java/com/thoughtworks/xstream/persistence/FilePersistenceStrategy.java
index ea973e8..1fe685e 100644
--- a/xstream/src/java/com/thoughtworks/xstream/persistence/FilePersistenceStrategy.java
+++ b/xstream/src/java/com/thoughtworks/xstream/persistence/FilePersistenceStrategy.java
@@ -1,32 +1,31 @@
/*
- * Copyright (C) 2008 XStream Committers.
+ * Copyright (C) 2008, 2016 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 20. November 2008 by Joerg Schaible
*/
package com.thoughtworks.xstream.persistence;
+import java.io.File;
+
import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.SingleValueConverter;
-import com.thoughtworks.xstream.io.StreamException;
import com.thoughtworks.xstream.io.xml.DomDriver;
-
-import java.io.File;
/**
- * PersistenceStrategy to assign keys with single value to objects persisted in files. The
- * default naming strategy is based on the key's type and its {@link SingleValueConverter}. It
- * escapes all characters that are normally illegal in the most common file systems. Such a
- * character is escaped with percent escaping as it is done by URL encoding. The XStream used to
- * marshal the values is also requested for the key's SingleValueConverter. A
- * {@link StreamException} is thrown if no such converter is registered.
- *
+ * PersistenceStrategy to assign keys with single value to objects persisted in files. The default naming strategy is
+ * based on the key's type and its {@link SingleValueConverter}. It escapes all characters that are normally illegal in
+ * the most common file systems. Such a character is escaped with percent escaping as it is done by URL encoding. The
+ * XStream used to marshal the values is also requested for the key's SingleValueConverter. A
+ * {@link ConversionException} is thrown if no such converter is registered.
+ *
* @author Jörg Schaible
* @author Guilherme Silveira
* @since 1.3.1
@@ -36,9 +35,8 @@
private final String illegalChars;
/**
- * Create a new FilePersistenceStrategy. Use a standard XStream instance with a
- * {@link DomDriver}.
- *
+ * Create a new FilePersistenceStrategy. Use a standard XStream instance with a {@link DomDriver}.
+ *
* @param baseDirectory the directory for the serialized values
* @since 1.3.1
*/
@@ -48,7 +46,7 @@
/**
* Create a new FilePersistenceStrategy with a provided XStream instance.
- *
+ *
* @param baseDirectory the directory for the serialized values
* @param xstream the XStream instance to use for (de)serialization
* @since 1.3.1
@@ -58,19 +56,17 @@
}
/**
- * Create a new FilePersistenceStrategy with a provided XStream instance and the characters
- * to encode.
- *
+ * Create a new FilePersistenceStrategy with a provided XStream instance and the characters to encode.
+ *
* @param baseDirectory the directory for the serialized values
* @param xstream the XStream instance to use for (de)serialization
* @param encoding encoding used to write the files
- * @param illegalChars illegal characters for file names (should always include '%' as long
- * as you do not overwrite the (un)escape methods)
+ * @param illegalChars illegal characters for file names (should always include '%' as long as you do not overwrite
+ * the (un)escape methods)
* @since 1.3.1
*/
public FilePersistenceStrategy(
- final File baseDirectory, final XStream xstream, final String encoding,
- final String illegalChars) {
+ final File baseDirectory, final XStream xstream, final String encoding, final String illegalChars) {
super(baseDirectory, xstream, encoding);
this.illegalChars = illegalChars;
}
@@ -81,7 +77,7 @@
/**
* Given a filename, the unescape method returns the key which originated it.
- *
+ *
* @param name the filename
* @return the original key
*/
@@ -90,19 +86,22 @@
if ("null@null".equals(key)) {
return null;
}
- int idx = key.indexOf('@');
+ final int idx = key.indexOf('@');
if (idx < 0) {
- throw new StreamException("Not a valid key: " + key);
+ final ConversionException exception = new ConversionException("No valid key");
+ exception.add("key", key);
+ throw exception;
}
- Class type = getMapper().realClass(key.substring(0, idx));
- Converter converter = getConverterLookup().lookupConverterForType(type);
+ final Class type = getMapper().realClass(key.substring(0, idx));
+ final Converter converter = getConverterLookup().lookupConverterForType(type);
if (converter instanceof SingleValueConverter) {
final SingleValueConverter svConverter = (SingleValueConverter)converter;
return svConverter.fromString(key.substring(idx + 1));
} else {
- throw new StreamException("No SingleValueConverter for type "
- + type.getName()
- + " available");
+ final ConversionException exception = new ConversionException(
+ "No SingleValueConverter available for key type");
+ exception.add("key-type", type.getName());
+ throw exception;
}
}
@@ -110,7 +109,7 @@
final StringBuffer buffer = new StringBuffer();
for (int idx = name.indexOf('%'); idx >= 0; idx = name.indexOf('%')) {
buffer.append(name.substring(0, idx));
- int c = Integer.parseInt(name.substring(idx + 1, idx + 3), 16);
+ final int c = Integer.parseInt(name.substring(idx + 1, idx + 3), 16);
buffer.append((char)c);
name = name.substring(idx + 3);
}
@@ -120,7 +119,7 @@
/**
* Given a key, the escape method returns the filename which shall be used.
- *
+ *
* @param key the key
* @return the desired and escaped filename
*/
@@ -128,18 +127,16 @@
if (key == null) {
return "null@null.xml";
}
- Class type = key.getClass();
- Converter converter = getConverterLookup().lookupConverterForType(type);
+ final Class type = key.getClass();
+ final Converter converter = getConverterLookup().lookupConverterForType(type);
if (converter instanceof SingleValueConverter) {
final SingleValueConverter svConverter = (SingleValueConverter)converter;
- return getMapper().serializedClass(type)
- + '@'
- + escape(svConverter.toString(key))
- + ".xml";
+ return getMapper().serializedClass(type) + '@' + escape(svConverter.toString(key)) + ".xml";
} else {
- throw new StreamException("No SingleValueConverter for type "
- + type.getName()
- + " available");
+ final ConversionException exception = new ConversionException(
+ "No SingleValueConverter available for key type");
+ exception.add("key-type", type.getName());
+ throw exception;
}
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/AbstractAcceptanceTest.java b/xstream/src/test/com/thoughtworks/acceptance/AbstractAcceptanceTest.java
index 7fcf9f6..ee11141 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/AbstractAcceptanceTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/AbstractAcceptanceTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -71,9 +71,8 @@
Class type = Class.forName(driver);
return (HierarchicalStreamDriver) type.newInstance();
}
- }
- catch (Exception e) {
- throw new RuntimeException("Could not load driver: " + driver);
+ } catch (final Exception e) {
+ throw new RuntimeException("Could not load driver: " + driver, e);
}
return new XppDriver();
}
@@ -121,9 +120,10 @@
return resultRoot;
- } catch (TransformerException e) {
- throw new AssertionFailedError("Cannot normalize XML: " + e.getMessage());
- // .initCause(e); ... still JDK 1.3
+ } catch (final TransformerException e) {
+ final AssertionFailedError error = new AssertionFailedError("Cannot normalize XML: " + e.getMessage());
+ error.initCause(e);
+ throw error;
}
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/AbstractReferenceTest.java b/xstream/src/test/com/thoughtworks/acceptance/AbstractReferenceTest.java
index 514187c..07664a4 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/AbstractReferenceTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/AbstractReferenceTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2010, 2011, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2010, 2011, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -66,6 +66,8 @@
Thing t0 = (Thing)result.get(0);
Thing t1 = (Thing)result.get(1);
Thing t2 = (Thing)result.get(2);
+
+ assertSame(t0, t1);
t0.field = "bye";
@@ -472,4 +474,59 @@
String xml = xstream.toXML(emails);
assertEquals(emails, xstream.fromXML(xml));
}
+
+ public void testImmutableInstancesAreNotReferenced() {
+ xstream.addImmutableType(Thing.class, false);
+
+ Thing sameThing = new Thing("hello");
+ Thing anotherThing = new Thing("hello");
+
+ List list = new ArrayList();
+ list.add(sameThing);
+ list.add(sameThing);
+ list.add(anotherThing);
+
+ String xml = xstream.toXML(list);
+ List result = (List)xstream.fromXML(xml);
+
+ Thing t0 = (Thing)result.get(0);
+ Thing t1 = (Thing)result.get(1);
+ Thing t2 = (Thing)result.get(2);
+
+ assertEquals(t0, t1);
+ assertNotSame(t0, t1);
+ }
+
+ public void testImmutableInstancesCanBeDereferenced() {
+
+ Thing sameThing = new Thing("hello");
+ Thing anotherThing = new Thing("hello");
+
+ List list = new ArrayList();
+ list.add(sameThing);
+ list.add(sameThing);
+ list.add(anotherThing);
+
+ String xml = xstream.toXML(list);
+
+ xstream.addImmutableType(Thing.class, false);
+
+ try {
+ xstream.fromXML(xml);
+ fail("Thrown " + ConversionException.class.getName() + " expected");
+ } catch (final ConversionException e) {
+ assertEquals(Thing.class.getName(), e.get("referenced-type"));
+ }
+
+ xstream.addImmutableType(Thing.class, true);
+
+ List result = (List)xstream.fromXML(xml);
+
+ Thing t0 = (Thing)result.get(0);
+ Thing t1 = (Thing)result.get(1);
+ Thing t2 = (Thing)result.get(2);
+
+ assertEquals(t0, t1);
+ assertSame(t0, t1);
+ }
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/Extended17TypesTest.java b/xstream/src/test/com/thoughtworks/acceptance/Extended17TypesTest.java
new file mode 100644
index 0000000..edc7b99
--- /dev/null
+++ b/xstream/src/test/com/thoughtworks/acceptance/Extended17TypesTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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 7. February 2016 by Aaron Johnson
+ */
+package com.thoughtworks.acceptance;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.thoughtworks.xstream.XStream;
+
+
+/**
+ * @author Aaron Johnson
+ * @author Jörg Schaible
+ */
+public class Extended17TypesTest extends AbstractAcceptanceTest {
+
+ @Override
+ protected void setupSecurity(final XStream xstream) {
+ super.setupSecurity(xstream);
+ xstream.allowTypeHierarchy(Path.class);
+ }
+
+ public void testPathOfDefaultFileSystem() {
+ assertBothWays(Paths.get("../a/relative/path"), "../a/relative/path");
+ assertBothWays(Paths.get("/an/absolute/path"), "/an/absolute/path");
+
+ final String absolutePathName = Paths.get("target").toAbsolutePath().toString();
+ final URI uri = URI.create("file://" + absolutePathName);
+ assertBothWays(Paths.get(uri), "" + absolutePathName + "");
+ }
+
+ public void testPathOfNonDefaultFileSystem() throws IOException {
+ final Map env = new HashMap();
+ env.put("create", "true");
+ final URI uri = URI.create("jar:file://"
+ + Paths.get("target/lib/proxytoys-0.2.1.jar").toAbsolutePath().toString());
+
+ FileSystem zipfs = null;
+ try {
+ zipfs = FileSystems.newFileSystem(uri, env);
+ final String entry = "/com/thoughtworks/proxy/kit/SimpleReference.class";
+ final Path path = zipfs.getPath(entry);
+ assertBothWays(path, "" + uri.toString() + "!" + entry + "");
+ } finally {
+ if (zipfs != null) {
+ zipfs.close();
+ }
+ }
+ }
+}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/FinalFieldsTest.java b/xstream/src/test/com/thoughtworks/acceptance/FinalFieldsTest.java
index ea8d806..d3ebcbf 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/FinalFieldsTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/FinalFieldsTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2013, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2013, 2014, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -45,7 +45,7 @@
}
} catch (ObjectAccessException expectedException) {
assertEquals("Invalid final field " + ThingWithFinalField.class.getName() + ".number",
- expectedException.getMessage());
+ expectedException.get("message"));
}
}
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/ImplicitArrayTest.java b/xstream/src/test/com/thoughtworks/acceptance/ImplicitArrayTest.java
index b98c519..0573897 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/ImplicitArrayTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/ImplicitArrayTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2011, 2012, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -27,6 +27,8 @@
xstream.alias("farm", Farm.class);
xstream.alias("animal", Animal.class);
xstream.alias("MEGA-farm", MegaFarm.class);
+ xstream.alias("area", Area.class);
+ xstream.alias("country", Country.class);
xstream.ignoreUnknownElements();
}
@@ -483,6 +485,179 @@
assertBothWays(farm, expected);
}
+ public static class Area extends Farm {
+ Animal[] animals;
+ }
+
+ public void testWithHiddenArray() {
+ Area area = new Area();
+ ((Farm)area).animals = new Animal[2];
+ ((Farm)area).animals[0] = new Animal("Cow");
+ ((Farm)area).animals[1] = new Animal("Sheep");
+ area.animals = new Animal[2];
+ area.animals[0] = new Animal("Falcon");
+ area.animals[1] = new Animal("Sparrow");
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitArray(Farm.class, "animals");
+ xstream.addImplicitArray(Area.class, "animals");
+ assertBothWays(area, expected);
+ }
+
+ public void testWithHiddenArrayAndDifferentAlias() {
+ Area area = new Area();
+ ((Farm)area).animals = new Animal[2];
+ ((Farm)area).animals[0] = new Animal("Cow");
+ ((Farm)area).animals[1] = new Animal("Sheep");
+ area.animals = new Animal[2];
+ area.animals[0] = new Animal("Falcon");
+ area.animals[1] = new Animal("Sparrow");
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitArray(Farm.class, "animals", "domesticated");
+ xstream.addImplicitArray(Area.class, "animals", "wild");
+ assertBothWays(area, expected);
+ }
+
+ public void testDoesNotInheritFromHiddenArrayOfSuperclass() {
+ Area area = new Area();
+ ((Farm)area).animals = new Animal[2];
+ ((Farm)area).animals[0] = new Animal("Cow");
+ ((Farm)area).animals[1] = new Animal("Sheep");
+ area.animals = new Animal[2];
+ area.animals[0] = new Animal("Falcon");
+ area.animals[1] = new Animal("Sparrow");
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitArray(Farm.class, "animals");
+ assertBothWays(area, expected);
+ }
+
+ public void testDoesNotPropagateToHiddenArrayOfSuperclass() {
+ Area area = new Area();
+ ((Farm)area).animals = new Animal[2];
+ ((Farm)area).animals[0] = new Animal("Cow");
+ ((Farm)area).animals[1] = new Animal("Sheep");
+ area.animals = new Animal[2];
+ area.animals[0] = new Animal("Falcon");
+ area.animals[1] = new Animal("Sparrow");
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitArray(Area.class, "animals");
+ assertBothWays(area, expected);
+ }
+
+ public static class County extends Area {
+ }
+
+ public static class Country extends County {
+ Animal[] animals;
+ }
+
+ public void testWithDoubleHiddenArray() {
+ Country country = new Country();
+ ((Farm)country).animals = new Animal[2];
+ ((Farm)country).animals[0] = new Animal("Cow");
+ ((Farm)country).animals[1] = new Animal("Sheep");
+ ((Area)country).animals = new Animal[2];
+ ((Area)country).animals[0] = new Animal("Falcon");
+ ((Area)country).animals[1] = new Animal("Sparrow");
+ country.animals = new Animal[2];
+ country.animals[0] = new Animal("Wale");
+ country.animals[1] = new Animal("Dolphin");
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ " \n" +
+ " Wale\n" +
+ " \n" +
+ " \n" +
+ " Dolphin\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitArray(Farm.class, "animals");
+ xstream.addImplicitArray(Area.class, "animals");
+ xstream.addImplicitArray(Country.class, "animals");
+ assertBothWays(country, expected);
+ }
+
static class PrimitiveArray {
int[] ints;
};
diff --git a/xstream/src/test/com/thoughtworks/acceptance/ImplicitCollectionTest.java b/xstream/src/test/com/thoughtworks/acceptance/ImplicitCollectionTest.java
index c489c13..502c486 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/ImplicitCollectionTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/ImplicitCollectionTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -57,6 +57,8 @@
xstream.alias("room", Room.class);
xstream.alias("house", House.class);
xstream.alias("person", Person.class);
+ xstream.alias("area", Area.class);
+ xstream.alias("country", Country.class);
xstream.ignoreUnknownElements();
}
@@ -549,4 +551,181 @@
xstream.addImplicitCollection(Farm.class, "animals", "beast", Animal.class);
assertBothWays(farm, expected);
}
+
+ public static class Area extends Farm {
+
+ List animals = new ArrayList();
+
+ public Area(int size) {
+ super(size);
+ }
+
+ }
+
+ public void testWithHiddenList() {
+ Area area = new Area(1000);
+ area.add(new Animal("Cow"));
+ area.add(new Animal("Sheep"));
+ area.animals.add(new Animal("Falcon"));
+ area.animals.add(new Animal("Sparrow"));
+
+ String expected = "" +
+ "\n" +
+ " 1000\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitCollection(Farm.class, "animals");
+ xstream.addImplicitCollection(Area.class, "animals");
+ assertBothWays(area, expected);
+ }
+
+ public void testWithHiddenListAndDifferentAlias() {
+ Area area = new Area(1000);
+ area.add(new Animal("Cow"));
+ area.add(new Animal("Sheep"));
+ area.animals.add(new Animal("Falcon"));
+ area.animals.add(new Animal("Sparrow"));
+
+ String expected = "" +
+ "\n" +
+ " 1000\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitCollection(Farm.class, "animals", "domesticated", Animal.class);
+ xstream.addImplicitCollection(Area.class, "animals", "wild", Animal.class);
+ assertBothWays(area, expected);
+ }
+
+ public void testDoesNotInheritFromHiddenListOfSuperclass() {
+ Area area = new Area(1000);
+ area.add(new Animal("Cow"));
+ area.add(new Animal("Sheep"));
+ area.animals.add(new Animal("Falcon"));
+ area.animals.add(new Animal("Sparrow"));
+
+ String expected = "" +
+ "\n" +
+ " 1000\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitCollection(Farm.class, "animals");
+ assertBothWays(area, expected);
+ }
+
+ public void testDoesNotPropagateToHiddenListOfSuperclass() {
+ Area area = new Area(1000);
+ area.add(new Animal("Cow"));
+ area.add(new Animal("Sheep"));
+ area.animals.add(new Animal("Falcon"));
+ area.animals.add(new Animal("Sparrow"));
+
+ String expected = "" +
+ "\n" +
+ " 1000\n" +
+ " \n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitCollection(Area.class, "animals");
+ assertBothWays(area, expected);
+ }
+
+ public static class County extends Area {
+
+ public County() {
+ super(10);
+ }
+ }
+
+ public static class Country extends County {
+ List animals = new ArrayList();
+ }
+
+ public void testWithDoubleHiddenList() {
+ Country country = new Country();
+ country.add(new Animal("Cow"));
+ country.add(new Animal("Sheep"));
+ ((Area)country).animals.add(new Animal("Falcon"));
+ ((Area)country).animals.add(new Animal("Sparrow"));
+ country.animals.add(new Animal("Wale"));
+ country.animals.add(new Animal("Dolphin"));
+
+ String expected = "" +
+ "\n" +
+ " 10\n" +
+ " \n" +
+ " Cow\n" +
+ " \n" +
+ " \n" +
+ " Sheep\n" +
+ " \n" +
+ " \n" +
+ " Falcon\n" +
+ " \n" +
+ " \n" +
+ " Sparrow\n" +
+ " \n" +
+ " \n" +
+ " Wale\n" +
+ " \n" +
+ " \n" +
+ " Dolphin\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitCollection(Farm.class, "animals");
+ xstream.addImplicitCollection(Area.class, "animals");
+ xstream.addImplicitCollection(Country.class, "animals");
+ assertBothWays(country, expected);
+ }
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/ImplicitMapTest.java b/xstream/src/test/com/thoughtworks/acceptance/ImplicitMapTest.java
index 7a3d13d..3184c31 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/ImplicitMapTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/ImplicitMapTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2011, 2012, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,61 +14,37 @@
import com.thoughtworks.acceptance.objects.Product;
import com.thoughtworks.acceptance.objects.SampleMaps;
import com.thoughtworks.acceptance.objects.Software;
-import com.thoughtworks.acceptance.objects.StandardObject;
import com.thoughtworks.xstream.converters.collections.MapConverter;
-import com.thoughtworks.xstream.core.util.OrderRetainingMap;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class ImplicitMapTest extends AbstractAcceptanceTest {
-
- public static class Farm extends StandardObject {
- int size;
- List animals = new ArrayList();
-
- public Farm(int size) {
- this.size = size;
- }
-
- public void add(Animal animal) {
- animals.add(animal);
- }
- }
-
- public static class Animal extends StandardObject implements Comparable {
- String name;
-
- public Animal(String name) {
- this.name = name;
- }
-
- public int compareTo(Object o) {
- return name.compareTo(((Animal)o).name);
- }
- }
protected void setUp() throws Exception {
super.setUp();
xstream.registerConverter(new MapConverter(xstream.getMapper()) {
public boolean canConvert(Class type) {
- return type == OrderRetainingMap.class;
+ return type == LinkedHashMap.class;
}
});
- xstream.addDefaultImplementation(OrderRetainingMap.class, Map.class);
+ xstream.addDefaultImplementation(LinkedHashMap.class, Map.class);
xstream.alias("sample", SampleMaps.class);
xstream.alias("software", Software.class);
xstream.alias("hardware", Hardware.class);
xstream.alias("product", Product.class);
+ xstream.alias("sample2", SampleMaps2.class);
+ xstream.alias("sample3", SampleMaps3.class);
xstream.ignoreUnknownElements();
}
public void testWithout() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put("Windows", new Software("Microsoft", "Windows"));
sample.good.put("Linux", new Software("Red Hat", "Linux"));
@@ -98,7 +74,7 @@
public void testWithMap() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put("Windows", new Software("Microsoft", "Windows"));
sample.good.put("Linux", new Software("Red Hat", "Linux"));
@@ -121,10 +97,10 @@
public static class MegaSampleMaps extends SampleMaps {
String separator = "---";
- Map other = new OrderRetainingMap();
+ Map other = new LinkedHashMap();
{
- good = new OrderRetainingMap();
- bad = new OrderRetainingMap();
+ good = new LinkedHashMap();
+ bad = new LinkedHashMap();
}
}
@@ -371,7 +347,7 @@
public void testWithExplicitItemNameMatchingTheNameOfTheFieldWithTheMap() {
SampleMaps sample = new SampleMaps();
- sample.bad = new OrderRetainingMap();
+ sample.bad = new LinkedHashMap();
sample.bad.put("Windows", new Software("Microsoft", "Windows"));
sample.bad.put("Linux", new Software("Red Hat", "Linux"));
@@ -394,7 +370,7 @@
public void testWithImplicitNameMatchingTheNameOfTheFieldWithTheMap() {
SampleMaps sample = new SampleMaps();
- sample.bad = new OrderRetainingMap();
+ sample.bad = new LinkedHashMap();
sample.bad.put("Windows", new Software("Microsoft", "Windows"));
sample.bad.put("Linux", new Software("Red Hat", "Linux"));
@@ -418,7 +394,7 @@
public void testWithAliasedItemNameMatchingTheAliasedNameOfTheFieldWithTheMap() {
SampleMaps sample = new SampleMaps();
- sample.bad = new OrderRetainingMap();
+ sample.bad = new LinkedHashMap();
sample.bad.put("Windows", new Software("Microsoft", "Windows"));
sample.bad.put("Linux", new Software("Red Hat", "Linux"));
@@ -442,7 +418,7 @@
public void testWithNullElement() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put(null, null);
sample.good.put("Linux", new Software("Red Hat", "Linux"));
@@ -462,7 +438,7 @@
public void testWithAliasAndNullElement() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put(null, null);
sample.good.put("Linux", new Software("Red Hat", "Linux"));
@@ -479,10 +455,215 @@
xstream.addImplicitMap(SampleMaps.class, "good", "code", Software.class, "name");
assertBothWays(sample, expected);
}
+
+ public static class SampleMaps2 extends SampleMaps {
+ public Map good = new LinkedHashMap();
+ }
+
+ public void testWithHiddenMap() {
+ SampleMaps2 sample = new SampleMaps2();
+ ((SampleMaps)sample).good = new LinkedHashMap();
+ ((SampleMaps)sample).good.put("Windows", new Software("Microsoft", "Windows"));
+ ((SampleMaps)sample).good.put("Linux", new Software("Red Hat", "Linux"));
+ sample.good.put("Android", new Software("Google", "Android"));
+ sample.good.put("iOS", new Software("Apple", "iOS"));
+ sample.bad = null;
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Microsoft\n" +
+ " Windows\n" +
+ " \n" +
+ " \n" +
+ " Red Hat\n" +
+ " Linux\n" +
+ " \n" +
+ " \n" +
+ " Google\n" +
+ " Android\n" +
+ " \n" +
+ " \n" +
+ " Apple\n" +
+ " iOS\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitMap(SampleMaps.class, "good", Software.class, "name");
+ xstream.addImplicitMap(SampleMaps2.class, "good", Software.class, "name");
+ assertBothWays(sample, expected);
+ }
+
+ public void testWithHiddenMapAndDifferentAlias() {
+ SampleMaps2 sample = new SampleMaps2();
+ ((SampleMaps)sample).good = new LinkedHashMap();
+ ((SampleMaps)sample).good.put("Windows", new Software("Microsoft", "Windows"));
+ ((SampleMaps)sample).good.put("Linux", new Software("Red Hat", "Linux"));
+ sample.good.put("Android", new Software("Google", "Android"));
+ sample.good.put("iOS", new Software("Apple", "iOS"));
+ sample.bad = null;
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Microsoft\n" +
+ " Windows\n" +
+ "
\n" +
+ " \n" +
+ " Red Hat\n" +
+ " Linux\n" +
+ "
\n" +
+ " \n" +
+ " Google\n" +
+ " Android\n" +
+ " \n" +
+ " \n" +
+ " Apple\n" +
+ " iOS\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitMap(SampleMaps.class, "good", "code", Software.class, "name");
+ xstream.addImplicitMap(SampleMaps2.class, "good", "mobile", Software.class, "name");
+ }
+
+ public void testDoesNotInheritFromHiddenMapOfSuperclass() {
+ SampleMaps2 sample = new SampleMaps2();
+ ((SampleMaps)sample).good = new LinkedHashMap();
+ ((SampleMaps)sample).good.put("Windows", new Software("Microsoft", "Windows"));
+ ((SampleMaps)sample).good.put("Linux", new Software("Red Hat", "Linux"));
+ sample.good.put("Android", new Software("Google", "Android"));
+ sample.good.put("iOS", new Software("Apple", "iOS"));
+ sample.bad = null;
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Microsoft\n" +
+ " Windows\n" +
+ " \n" +
+ " \n" +
+ " Red Hat\n" +
+ " Linux\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Android\n" +
+ " \n" +
+ " Google\n" +
+ " Android\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " iOS\n" +
+ " \n" +
+ " Apple\n" +
+ " iOS\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitMap(SampleMaps.class, "good", Software.class, "name");
+ assertBothWays(sample, expected);
+ }
+
+ public void testDoesNotPropagateToHiddenMapOfSuperclass() {
+ SampleMaps2 sample = new SampleMaps2();
+ ((SampleMaps)sample).good = new LinkedHashMap();
+ ((SampleMaps)sample).good.put("Windows", new Software("Microsoft", "Windows"));
+ ((SampleMaps)sample).good.put("Linux", new Software("Red Hat", "Linux"));
+ sample.good.put("Android", new Software("Google", "Android"));
+ sample.good.put("iOS", new Software("Apple", "iOS"));
+ sample.bad = null;
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " \n" +
+ " Windows\n" +
+ " \n" +
+ " Microsoft\n" +
+ " Windows\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Linux\n" +
+ " \n" +
+ " Red Hat\n" +
+ " Linux\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Google\n" +
+ " Android\n" +
+ " \n" +
+ " \n" +
+ " Apple\n" +
+ " iOS\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitMap(SampleMaps2.class, "good", Software.class, "name");
+ assertBothWays(sample, expected);
+ }
+
+ public static class IntermediateMaps extends SampleMaps2 {
+ }
+
+ public static class SampleMaps3 extends IntermediateMaps {
+ Map good = new LinkedHashMap();
+ }
+
+ public void testWithDoubleHiddenList() {
+ SampleMaps3 sample = new SampleMaps3();
+ ((SampleMaps)sample).good = new LinkedHashMap();
+ ((SampleMaps)sample).good.put("Windows", new Software("Microsoft", "Windows"));
+ ((SampleMaps)sample).good.put("Linux", new Software("Red Hat", "Linux"));
+ ((SampleMaps2)sample).good.put("Android", new Software("Google", "Android"));
+ ((SampleMaps2)sample).good.put("iOS", new Software("Apple", "iOS"));
+ sample.good.put("Oracle", new Software("Oracle", "Oracle"));
+ sample.good.put("Hana", new Software("SAP", "Hana"));
+ sample.bad = null;
+
+ String expected = "" +
+ "\n" +
+ " \n" +
+ " Microsoft\n" +
+ " Windows\n" +
+ " \n" +
+ " \n" +
+ " Red Hat\n" +
+ " Linux\n" +
+ " \n" +
+ " \n" +
+ " Google\n" +
+ " Android\n" +
+ " \n" +
+ " \n" +
+ " Apple\n" +
+ " iOS\n" +
+ " \n" +
+ " \n" +
+ " Oracle\n" +
+ " Oracle\n" +
+ " \n" +
+ " \n" +
+ " SAP\n" +
+ " Hana\n" +
+ " \n" +
+ "";
+
+ xstream.addImplicitMap(SampleMaps.class, "good", Software.class, "name");
+ xstream.addImplicitMap(SampleMaps2.class, "good", Software.class, "name");
+ xstream.addImplicitMap(SampleMaps3.class, "good", Software.class, "name");
+ assertBothWays(sample, expected);
+ }
public void testCollectsDifferentTypesWithFieldOfSameName() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put("iPhone", new Product("iPhone", "i", 399.99));
sample.good.put("Linux", new Software("Red Hat", "Linux"));
sample.good.put("Intel", new Hardware("i386", "Intel"));
@@ -511,9 +692,9 @@
public void testSeparatesItemsBasedOnItemName() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put("Chrome", new Software("Google", "Chrome"));
- sample.bad = new OrderRetainingMap();
+ sample.bad = new LinkedHashMap();
sample.bad.put("Linux", new Software("Red Hat", "Linux"));
sample.bad.put("Windows", new Software("Microsoft", "Windows"));
@@ -540,7 +721,7 @@
public void testWithoutKeyField() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put("Windows", new Software("Microsoft", "Windows"));
sample.good.put("Linux", new Software("Red Hat", "Linux"));
@@ -569,7 +750,7 @@
public void testCanUsePrimitiveAsKey() {
SampleMaps sample = new SampleMaps();
- sample.good = new OrderRetainingMap();
+ sample.good = new LinkedHashMap();
sample.good.put(new Double(399.99), new Product("iPhone", "i", 399.99));
String expected = "" +
diff --git a/xstream/src/test/com/thoughtworks/acceptance/ImplicitTest.java b/xstream/src/test/com/thoughtworks/acceptance/ImplicitTest.java
index fa04248..94b3439 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/ImplicitTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/ImplicitTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 XStream Committers.
+ * Copyright (C) 2013, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,6 +11,7 @@
package com.thoughtworks.acceptance;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -141,6 +142,10 @@
c.val = new Integer(6);
implicits.cMap.put(c.val, c);
assertBothWays(implicits, expected);
+ implicits.separator1 = implicits.separator2 = null;
+ assertBothWays(implicits, stripSeparator(expected));
+ implicits.separator1 = implicits.separator2 = null;
+ assertBothWays(implicits, stripSeparator(expected));
}
public void testAllImplicitTypesAtOnceWithExplicitElementNames()
@@ -190,5 +195,118 @@
c.val = new Integer(6);
implicits.cMap.put(c.val, c);
assertBothWays(implicits, expected);
+ implicits.separator1 = implicits.separator2 = null;
+ assertBothWays(implicits, stripSeparator(expected));
+ }
+
+ private String stripSeparator(String s) {
+ return s.replaceAll(" *\n"
+ + " \n"
+ + " 1\n"
+ + " \n"
+ + " \n"
+ + " 2\n"
+ + " \n"
+ + " --1--\n"
+ + " \n"
+ + " 3\n"
+ + " \n"
+ + " \n"
+ + " 4\n"
+ + " \n"
+ + " --2--\n"
+ + " \n"
+ + " 5\n"
+ + " \n"
+ + " \n"
+ + " 6\n"
+ + " \n"
+ + " --X--\n"
+ + " a\n"
+ + " b\n"
+ + " c\n"
+ + " --H--\n"
+ + " \n"
+ + " 7\n"
+ + " \n"
+ + " \n"
+ + " 8\n"
+ + " \n"
+ + " \n"
+ + " 9\n"
+ + " \n"
+ + " \n"
+ + " 10\n"
+ + " \n"
+ + " \n"
+ + " 11\n"
+ + " \n"
+ + " \n"
+ + " 12\n"
+ + " \n"
+ + "";
+
+ AllHidingImplicitTypes implicits = new AllHidingImplicitTypes();
+ ((AllImplicitTypes)implicits).aArray[0] = new AllImplicitTypes.A();
+ ((AllImplicitTypes)implicits).aArray[0].val = 1;
+ ((AllImplicitTypes)implicits).aArray[1] = new AllImplicitTypes.A();
+ ((AllImplicitTypes)implicits).aArray[1].val = 2;
+ implicits.aArray[0] = new AllImplicitTypes.A();
+ implicits.aArray[0].val = 7;
+ implicits.aArray[1] = new AllImplicitTypes.A();
+ implicits.aArray[1].val = 8;
+ ((AllImplicitTypes)implicits).bList.add(new AllImplicitTypes.B());
+ ((AllImplicitTypes.B)((AllImplicitTypes)implicits).bList.get(0)).val = 3;
+ ((AllImplicitTypes)implicits).bList.add(new AllImplicitTypes.B());
+ ((AllImplicitTypes.B)((AllImplicitTypes)implicits).bList.get(1)).val = 4;
+ implicits.bList.add(new AllImplicitTypes.B());
+ ((AllImplicitTypes.B)implicits.bList.get(0)).val = 9;
+ implicits.bList.add(new AllImplicitTypes.B());
+ ((AllImplicitTypes.B)implicits.bList.get(1)).val = 10;
+ AllImplicitTypes.C c = new AllImplicitTypes.C();
+ c.val = new Integer(5);
+ ((AllImplicitTypes)implicits).cMap.put(c.val, c);
+ c = new AllImplicitTypes.C();
+ c.val = new Integer(6);
+ ((AllImplicitTypes)implicits).cMap.put(c.val, c);
+ c = new AllImplicitTypes.C();
+ c.val = new Integer(11);
+ implicits.cMap.put(c.val, c);
+ c = new AllImplicitTypes.C();
+ c.val = new Integer(12);
+ implicits.cMap.put(c.val, c);
+ assertBothWays(implicits, expected);
+ implicits.separator1 = implicits.separator2 = ((AllHidingTypes)implicits).separator = implicits.separator = null;
+ assertBothWays(implicits, stripSeparator(expected));
}
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/InnerClassesTest.java b/xstream/src/test/com/thoughtworks/acceptance/InnerClassesTest.java
index 1952400..f1114d8 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/InnerClassesTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/InnerClassesTest.java
@@ -1,29 +1,31 @@
/*
* Copyright (C) 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2014 XStream Committers.
+ * Copyright (C) 2006, 2007, 2014, 2015 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 31. January 2005 by Joe Walnes
*/
package com.thoughtworks.acceptance;
+
+import com.thoughtworks.xstream.core.JVM;
public class InnerClassesTest extends AbstractAcceptanceTest {
public void testSerializedInnerClassMaintainsReferenceToOuterClass() {
xstream.allowTypes(new Class[]{Outer.class, Outer.Inner.class});
- Outer outer = new Outer("THE-OUTER-NAME", "THE-INNER-NAME");
- Outer.Inner inner = outer.getInner();
+ final Outer outer = new Outer("THE-OUTER-NAME", "THE-INNER-NAME");
+ final Outer.Inner inner = outer.getInner();
assertEquals("Hello from THE-INNER-NAME (inside THE-OUTER-NAME)", inner.getMessage());
- String xml = xstream.toXML(inner);
+ final String xml = xstream.toXML(inner);
- String expectedXml = ""
+ final String expectedXml = ""
+ "\n"
+ " THE-INNER-NAME\n"
+ " \n"
@@ -33,18 +35,100 @@
+ "";
assertEquals(expectedXml, xml);
- Outer.Inner newInner = (Outer.Inner) xstream.fromXML(xml);
+ final Outer.Inner newInner = (Outer.Inner)xstream.fromXML(xml);
assertEquals("Hello from THE-INNER-NAME (inside THE-OUTER-NAME)", newInner.getMessage());
+ }
+
+ public static class OuterType {
+ private final String outerName = "Outer Name";
+ public InnerType inner = new InnerType();
+ private final InnerType.Dynamic1 dyn1 = inner.new Dynamic1();
+ private final InnerType.Dynamic1.Dynamic2 dyn2 = dyn1.new Dynamic2();
+ private final InnerType.Dynamic3 dyn3 = inner.new Dynamic3(dyn1);
+
+ public class InnerType {
+ private final String innerName = "Inner Name";
+
+ public class Dynamic1 {
+ private final String name1 = "Name 1";
+
+ public class Dynamic2 {
+ private final String name2 = "Name 2";
+ }
+ }
+
+ public class Dynamic3 extends Dynamic1.Dynamic2 {
+ private final String name3 = "Name 3";
+ final Dynamic1.Dynamic2 dyn4;
+
+ public Dynamic3(final Dynamic1 outer) {
+ outer.super();
+ class Dynamic4 extends Dynamic1.Dynamic2 {
+ private final String name4 = "Name 4";
+ private final Dynamic5 dyn5 = new Dynamic5();
+ class Dynamic5 {
+ private final String name5 = "Name 5";
+ }
+ Dynamic4(Dynamic1 outer) {
+ outer.super();
+ }
+ }
+ dyn4 = new Dynamic4(outer);
+ }
+ }
+ }
+ }
+
+ public void testNestedDynamicTypes() {
+ final OuterType outer = new OuterType();
+
+ xstream.alias("inner", OuterType.InnerType.class);
+ xstream.alias("Dynamic4", outer.dyn3.dyn4.getClass());
+
+ String expectedXml = ""
+ + "\n"
+ + " Inner Name\n"
+ + " \n"
+ + " Outer Name\n"
+ + " \n"
+ + " \n"
+ + " Name 1\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " Name 2\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " Name 2\n"
+ + " \n"
+ + " Name 3\n"
+ + " \n"
+ + " Name 2\n"
+ + " \n"
+ + " Name 4\n"
+ + " \n"
+ + " Name 5\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + "";
+
+ assertBothWays(outer.inner, expectedXml);
}
}
class Outer {
- private Inner inner;
- private String outerName;
+ private final Inner inner;
+ private final String outerName;
- public Outer(String outerName, String innerName) {
+ public Outer(final String outerName, final String innerName) {
inner = new Inner(innerName);
this.outerName = outerName;
}
@@ -54,9 +138,9 @@
}
public class Inner {
- private String innerName;
+ private final String innerName;
- public Inner(String innerName) {
+ public Inner(final String innerName) {
this.innerName = innerName;
}
@@ -65,5 +149,3 @@
}
}
}
-
-
diff --git a/xstream/src/test/com/thoughtworks/acceptance/NamedLocalElementsTest.java b/xstream/src/test/com/thoughtworks/acceptance/NamedLocalElementsTest.java
index 94b92c6..7716115 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/NamedLocalElementsTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/NamedLocalElementsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 XStream Committers.
+ * Copyright (C) 2013, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,9 +11,13 @@
package com.thoughtworks.acceptance;
import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.TimeZone;
import com.thoughtworks.acceptance.objects.Category;
import com.thoughtworks.acceptance.objects.SampleMaps;
@@ -384,20 +388,24 @@
public void testMapElementsUsingAttributeAndText() {
xstream.registerLocalConverter(
SampleMaps.class, "good", new NamedMapConverter(
- xstream.getMapper(), "product", "name", String.class, null, String.class,
+ xstream.getMapper(), "product", "name", String.class, null, Date.class,
true, false, xstream.getConverterLookup()));
-
- SampleMaps maps = new SampleMaps();
- maps.bad = null;
- maps.good = new LinkedHashMap();
- maps.good.put("SiteMesh", "com.opensymphony");
- maps.good.put("XStream", "com.thoughtworks");
-
- String expected = (""
- + "\n"
- + " \n"
- + " com.opensymphony\n"
- + " com.thoughtworks\n"
+
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.GERMANY);
+ cal.clear();
+ cal.set(2016, Calendar.FEBRUARY, 8, 20, 11, 10);
+ SampleMaps maps = new SampleMaps();
+ maps.bad = null;
+ maps.good = new LinkedHashMap();
+ maps.good.put("SiteMesh", cal.getTime());
+ cal.add(Calendar.DAY_OF_MONTH, 1);
+ maps.good.put("XStream", cal.getTime());
+
+ String expected = (""
+ + "\n"
+ + " \n"
+ + " 2016-02-08 20:11:10.0 UTC\n"
+ + " 2016-02-09 20:11:10.0 UTC\n"
+ " \n"
+ "").replace('\'', '"');
diff --git a/xstream/src/test/com/thoughtworks/acceptance/SecurityManagerTest.java b/xstream/src/test/com/thoughtworks/acceptance/SecurityManagerTest.java
index b0beced..6a66799 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/SecurityManagerTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/SecurityManagerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2009, 2010, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2010, 2013, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -184,6 +184,7 @@
sm.addPermission(source, new PropertyPermission("jdk.xml.maxGeneralEntitySizeLimit", "read"));
sm.addPermission(source, new PropertyPermission("jdk.xml.maxParameterEntitySizeLimit", "read"));
sm.addPermission(source, new PropertyPermission("jdk.xml.maxOccurLimit", "read"));
+ sm.addPermission(source, new PropertyPermission("jdk.xml.maxXMLNameLimit", "read"));
sm.addPermission(source, new PropertyPermission("jdk.xml.totalEntitySizeLimit", "read"));
sm.addPermission(source, new PropertyPermission("maxOccurLimit", "read"));
sm.addPermission(source, new PropertyPermission("sun.boot.class.path", "read"));
diff --git a/xstream/src/test/com/thoughtworks/acceptance/XStreamer.xsl b/xstream/src/test/com/thoughtworks/acceptance/XStreamer.xsl
index b2200b4..467d8ad 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/XStreamer.xsl
+++ b/xstream/src/test/com/thoughtworks/acceptance/XStreamer.xsl
@@ -1,6 +1,6 @@
-
+
diff --git a/xstream/src/test/com/thoughtworks/acceptance/annotations/FieldConverterTest.java b/xstream/src/test/com/thoughtworks/acceptance/annotations/FieldConverterTest.java
index 06d8c3b..1e99b7d 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/annotations/FieldConverterTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/annotations/FieldConverterTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -12,13 +12,16 @@
package com.thoughtworks.acceptance.annotations;
import com.thoughtworks.acceptance.AbstractAcceptanceTest;
+import com.thoughtworks.xstream.InitializationException;
import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
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.converters.enums.EnumToStringConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@@ -230,4 +233,24 @@
assertEquals(before + 1, after);
}
+ @XStreamConverter(EnumToStringConverter.class)
+ public static class InvalidForConverter {
+ }
+
+ public void testCausingExceptionIsNotSuppressed() {
+ try {
+ toXML(new InvalidForConverter());
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ Throwable th = e.getCause();
+ for(;;) {
+ th = th.getCause();
+ assertNotNull("No causing InitializationException.", th);
+ if (th instanceof InitializationException) {
+ assertTrue("No hint for enum types only", th.getMessage().indexOf(" enum ") >= 0);
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/annotations/ParametrizedConverterTest.java b/xstream/src/test/com/thoughtworks/acceptance/annotations/ParametrizedConverterTest.java
index 954a778..8388bab 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/annotations/ParametrizedConverterTest.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/annotations/ParametrizedConverterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2012, 2013, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,8 +11,11 @@
package com.thoughtworks.acceptance.annotations;
import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import com.thoughtworks.acceptance.AbstractAcceptanceTest;
@@ -24,6 +27,7 @@
import com.thoughtworks.xstream.annotations.XStreamInclude;
import com.thoughtworks.xstream.converters.basic.BooleanConverter;
import com.thoughtworks.xstream.converters.collections.MapConverter;
+import com.thoughtworks.xstream.converters.extended.NamedCollectionConverter;
import com.thoughtworks.xstream.converters.extended.NamedMapConverter;
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import com.thoughtworks.xstream.converters.extended.ToStringConverter;
@@ -53,9 +57,13 @@
xstream.alias("decimal", Decimal.class);
xstream.alias("type", Type.class);
xstream.processAnnotations(MyMap.class);
+ xstream.processAnnotations(MyType.class);
xstream.processAnnotations(DerivedType.class);
+ xstream.processAnnotations(DerivedType2.class);
xstream.processAnnotations(SimpleBean.class);
xstream.processAnnotations(ContainsMap.class);
+ xstream.processAnnotations(ContainsMap2.class);
+ xstream.processAnnotations(ContainsCollection.class);
}
public void testAnnotationForConvertersWithParameters() {
@@ -141,6 +149,20 @@
}
}
+ public void testConverterRequiringNull() {
+ final Type value = new DerivedType(new Decimal("1.5"), new Boolean(true), DerivedType.E.FOO);
+ String expected = "1.5".replace('\'', '"');
+ assertBothWays(value, expected);
+ }
+
+ @XStreamAlias("mytype")
+ @XStreamConverter(value=ToAttributedValueConverter.class, types={Type.class}, nulls={String.class})
+ public static class MyType extends Type {
+ public MyType(Decimal decimal, Boolean bool) {
+ super(decimal, bool);
+ }
+ }
+
public void testConverterWithSecondTypeParameter() {
final Type value = new DerivedType(new Decimal("1.5"), new Boolean(true), DerivedType.E.FOO);
String expected = "1.5".replace('\'', '"');
@@ -155,6 +177,25 @@
private E e;
public DerivedType(Decimal decimal, Boolean bool, E e) {
+ super(decimal, bool);
+ this.e = e;
+ }
+ }
+
+ public void testConverterWithAllAttributes() {
+ final Type value = new DerivedType2(new Decimal("1.5"), new Boolean(true), DerivedType2.E.FOO);
+ String expected = "".replace('\'', '"');
+ assertBothWays(value, expected);
+ }
+
+ @XStreamAlias("dtype2")
+ @XStreamConverter(value=ToAttributedValueConverter.class)
+ public static class DerivedType2 extends Type {
+ public enum E { FOO, BAR };
+ @XStreamAlias("enum")
+ private E e;
+
+ public DerivedType2(Decimal decimal, Boolean bool, E e) {
super(decimal, bool);
this.e = e;
}
@@ -214,8 +255,62 @@
this.map = map;
}
}
+
+ public void testAnnotatedNamedMapConverterWithMultipleSameArguments() {
+ xstream.addDefaultImplementation(LinkedHashMap.class, Map.class);
+
+ final Map map = new LinkedHashMap();
+ map.put("FOO", "foo");
+ map.put("BAR", "bar");
+ final ContainsMap2 value = new ContainsMap2(map);
+ String expected = (""
+ + "\n"
+ + " \n"
+ + "").replace('\'', '"');
+ assertBothWays(value, expected);
+ }
+
+ @XStreamAlias("container-map")
+ public static class ContainsMap2 extends StandardObject {
+ @XStreamConverter(value = NamedMapConverter.class, strings = {"", "key", "value"}, types = {
+ LinkedHashMap.class, String.class, String.class}, booleans = {false, false}, useImplicitType = false)
+ private Map map;
+
+ public ContainsMap2(Map map) {
+ this.map = map;
+ }
+ }
@XStreamAlias("my-enums")
public static class MyEnumMap extends LinkedHashMap {
}
+
+ public void testAnnotatedNamedCollectionConverter() {
+ List names = new ArrayList(Arrays.asList("joe", "joerg", "mauro"));
+ final ContainsCollection container = new ContainsCollection(names);
+ String expected = (""
+ + "\n"
+ + " \n"
+ + " joe\n"
+ + " joerg\n"
+ + " mauro\n"
+ + " \n"
+ + "").replace('\'', '"');
+ assertBothWays(container, expected);
+ }
+
+ @XStreamAlias("CollCont")
+ public static class ContainsCollection extends StandardObject {
+ @XStreamConverter(value=NamedCollectionConverter.class, strings={"name"}, types={String.class}, useImplicitType = false)
+ private List names;
+
+ public ContainsCollection(List names) {
+ this.names = names;
+ }
+ }
}
diff --git a/xstream/src/test/com/thoughtworks/acceptance/someobjects/Handler.java b/xstream/src/test/com/thoughtworks/acceptance/someobjects/Handler.java
index a7654d6..030f594 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/someobjects/Handler.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/someobjects/Handler.java
@@ -16,7 +16,7 @@
*
* @author Jason van Zyl
*
- * @version $Id: Handler.java 2034 2013-03-12 22:15:00Z joehni $
+ * @version $Id$
*/
public class Handler
{
diff --git a/xstream/src/test/com/thoughtworks/acceptance/someobjects/HandlerManager.java b/xstream/src/test/com/thoughtworks/acceptance/someobjects/HandlerManager.java
index 3896a74..aae0187 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/someobjects/HandlerManager.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/someobjects/HandlerManager.java
@@ -18,7 +18,7 @@
*
* @author Jason van Zyl
*
- * @version $Id: HandlerManager.java 1345 2007-12-11 01:50:12Z joehni $
+ * @version $Id$
*/
public class HandlerManager
{
diff --git a/xstream/src/test/com/thoughtworks/acceptance/someobjects/Protocol.java b/xstream/src/test/com/thoughtworks/acceptance/someobjects/Protocol.java
index 1ece4f8..a6e0dd6 100644
--- a/xstream/src/test/com/thoughtworks/acceptance/someobjects/Protocol.java
+++ b/xstream/src/test/com/thoughtworks/acceptance/someobjects/Protocol.java
@@ -16,7 +16,7 @@
*
* @author Jason van Zyl
*
- * @version $Id: Protocol.java 2034 2013-03-12 22:15:00Z joehni $
+ * @version $Id$
*/
public class Protocol
{
diff --git a/xstream/src/test/com/thoughtworks/xstream/converters/ConversionExceptionTest.java b/xstream/src/test/com/thoughtworks/xstream/converters/ConversionExceptionTest.java
index 2536b8a..256acf9 100644
--- a/xstream/src/test/com/thoughtworks/xstream/converters/ConversionExceptionTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/converters/ConversionExceptionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -43,6 +43,7 @@
StringTokenizer tokenizer = new StringTokenizer(ex.getMessage(), "\n\r");
tokenizer.nextToken();
tokenizer.nextToken();
+ assertEquals("message : Message", tokenizer.nextToken());
assertEquals("1st : first", tokenizer.nextToken());
assertEquals("2nd : second", tokenizer.nextToken());
assertEquals("3rd : third", tokenizer.nextToken());
diff --git a/xstream/src/test/com/thoughtworks/xstream/converters/extended/ActivationDataFlavorConverterTest.java b/xstream/src/test/com/thoughtworks/xstream/converters/extended/ActivationDataFlavorConverterTest.java
new file mode 100644
index 0000000..043c4c7
--- /dev/null
+++ b/xstream/src/test/com/thoughtworks/xstream/converters/extended/ActivationDataFlavorConverterTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 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.06.2015 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.extended;
+
+import java.awt.datatransfer.DataFlavor;
+
+import javax.activation.ActivationDataFlavor;
+
+import com.thoughtworks.acceptance.AbstractAcceptanceTest;
+import com.thoughtworks.xstream.XStream;
+
+
+public class ActivationDataFlavorConverterTest extends AbstractAcceptanceTest {
+
+ protected void setupSecurity(XStream xstream) {
+ super.setupSecurity(xstream);
+ xstream.allowTypeHierarchy(DataFlavor.class);
+ }
+
+ public void testMimeTypeOnly() {
+ final String expected = ""
+ + "\n"
+ + " application/x-junit\n"
+ + " java.io.InputStream\n"
+ + "";
+ assertBothWays(new ActivationDataFlavor("application/x-junit", null), expected);
+ }
+
+ public void testMimeTypeAndRepresentation() {
+ final String expected = ""
+ + "\n"
+ + " application/x-junit\n"
+ + " JUnit\n"
+ + " java.io.InputStream\n"
+ + "";
+ assertBothWays(new ActivationDataFlavor("application/x-junit", "JUnit"), expected);
+ }
+
+ public void testWithAllArguments() {
+ final String expected = ""
+ + "\n"
+ + " application/x-junit\n"
+ + " JUnit\n"
+ + " com.thoughtworks.xstream.converters.extended.ActivationDataFlavorConverterTest\n"
+ + "";
+ assertBothWays(new ActivationDataFlavor(ActivationDataFlavorConverterTest.class, "application/x-junit", "JUnit"), expected);
+ }
+}
diff --git a/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java b/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java
index c7703ab..354f23b 100644
--- a/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java
@@ -47,7 +47,7 @@
/**
* Tests {@link ToAttributedValueConverter}.
*
- * @author jos / last modified by $Author: joehni $
+ * @author jos / last modified by $Author$
*/
public class ToAttributedValueConverterTest extends TestCase {
private HierarchicalStreamDriver driver;
diff --git a/xstream/src/test/com/thoughtworks/xstream/converters/javabean/JavaBeanConverterTest.java b/xstream/src/test/com/thoughtworks/xstream/converters/javabean/JavaBeanConverterTest.java
index 6f69c15..3dd7932 100644
--- a/xstream/src/test/com/thoughtworks/xstream/converters/javabean/JavaBeanConverterTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/converters/javabean/JavaBeanConverterTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -201,6 +201,42 @@
assertEquals(expected, result);
}
+ public void testSerializesNullValue() {
+ World world = new World();
+ world.setAString(null);
+
+ XStream xstream = new XStream();
+ xstream.registerConverter(new JavaBeanConverter(xstream.getMapper(), new BeanProvider(
+ new StringComparator())), XStream.PRIORITY_LOW);
+ xstream.alias("world", World.class);
+
+ String expected = ""
+ + "\n"
+ + " true\n"
+ + " false\n"
+ + " 4\n"
+ + " 5\n"
+ + " a\n"
+ + " w\n"
+ + " 8.0\n"
+ + " 9.0\n"
+ + " 10\n"
+ + " 11\n"
+ + " 1\n"
+ + " 2\n"
+ + " 6\n"
+ + " 7\n"
+ + " \n"
+ + "";
+
+ String result = xstream.toXML(world);
+
+ assertEquals(expected, result);
+
+ World world2 = (World) xstream.fromXML(result);
+ assertEquals(null, world2.getAString());
+ }
+
/**
* Only normal and trans are serializable properties, the field modifiers do not matter
*/
diff --git a/xstream/src/test/com/thoughtworks/xstream/converters/reflection/FieldDictionaryTest.java b/xstream/src/test/com/thoughtworks/xstream/converters/reflection/FieldDictionaryTest.java
index 3243389..a857d39 100644
--- a/xstream/src/test/com/thoughtworks/xstream/converters/reflection/FieldDictionaryTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/converters/reflection/FieldDictionaryTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -15,7 +15,14 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
+
+import com.thoughtworks.xstream.core.JVM;
public class FieldDictionaryTest extends TestCase {
@@ -78,4 +85,115 @@
}
return field.getName();
}
+
+ private static class AssertNoDuplicateHashMap extends HashMap {
+ public Object put(final Object key, final Object value) {
+ assertFalse("Attempt to insert duplicate key: " + key, containsKey(key));
+ return super.put(key, value);
+ }
+ }
+
+ static class A { String a; }
+ static class B extends A { String b; }
+ static class C extends B { String c; }
+ static class D extends C { String d; }
+ static class E extends D { String e; }
+ static class F extends E { String f; }
+ static class G extends F { String g; }
+ static class H extends G { String h; }
+ static class I extends H { String i; }
+ static class J extends I { String j; }
+ static class BB extends B { String b; }
+ static class CC extends C { String c; }
+ static class DD extends D { String d; }
+ static class EE extends E { String e; }
+ static class FF extends F { String f; }
+ static class GG extends G { String g; }
+ static class HH extends H { String h; }
+ static class II extends I { String i; }
+ static class JJ extends J { String j; }
+ static class JJJ extends JJ { String j; }
+
+ public void testSynchronizedAccessShouldEnsureEachClassAddedOnceToCache() throws Exception {
+ AssertNoDuplicateHashMap assertNoDuplicateHashMap = new AssertNoDuplicateHashMap();
+
+ Field field = FieldDictionary.class.getDeclaredField("dictionaryEntries");
+ field.setAccessible(true);
+ field.set(fieldDictionary, assertNoDuplicateHashMap);
+
+ final List exceptions = Collections.synchronizedList(new ArrayList());
+
+ final List types =
+ Arrays.asList(new Class[] {
+ A.class, B.class, C.class, E.class, F.class, G.class, H.class, I.class, J.class,
+ BB.class, CC.class, DD.class, EE.class, FF.class, GG.class, HH.class, II.class, JJ.class,
+ JJJ.class, FieldDictionaryTest.class
+ });
+ final Thread[] threads = createThreads(types, exceptions);
+
+ for (int i = 0; i < threads.length; ++i) {
+ synchronized (threads[i]) {
+ threads[i].start();
+ threads[i].wait();
+ }
+ }
+
+ for (int i = 0; i < threads.length; ++i) {
+ synchronized (threads[i]) {
+ threads[i].notifyAll();
+ }
+ }
+
+ Thread.sleep(1500);
+
+ for (int i = 0; i < threads.length; ++i) {
+ threads[i].interrupt();
+ }
+ for (int i = 0; i < threads.length; ++i) {
+ synchronized (threads[i]) {
+ threads[i].join();
+ }
+ }
+
+ assertEquals("Assertions failed or exceptions thrown", Collections.EMPTY_LIST, exceptions);
+ }
+
+ private Thread[] createThreads(final List types, final List exceptions) {
+ Collections.shuffle(types);
+ final Thread[] threads = new Thread[types.size()];
+ for (int i = 0; i < types.size(); i++) {
+ final Class type = (Class)types.get(i);
+ threads[i] = new Thread() {
+ public void run() {
+ try {
+ synchronized (this) {
+ notifyAll();
+ wait();
+ }
+ final Iterator fieldIterator = fieldDictionary.fieldsFor(type);
+ int fieldCount = 0;
+ while (fieldIterator.hasNext()) {
+ Field field = (Field)fieldIterator.next();
+ if (JVM.is15() || !Modifier.isStatic(field.getModifiers())) {
+ fieldCount++;
+ }
+ }
+
+ if (type == FieldDictionaryTest.class) {
+ assertEquals("fieldCount not equal for type " + type.getName(), 2, fieldCount);
+ } else {
+ int count = 0;
+ for(Class cls = type; cls != null; count++, cls = cls.getSuperclass());
+ assertEquals("fieldCount not equal for type " + type.getName(), count-1, fieldCount);
+ }
+ } catch (final Exception e) {
+ exceptions.add(e);
+ } catch (final Error e) {
+ exceptions.add(e);
+ }
+ }
+ };
+ }
+ return threads;
+ }
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorterTest.java b/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorterTest.java
index a69d226..914ef3d 100644
--- a/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorterTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SortableFieldKeySorterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 XStream Committers.
+ * Copyright (C) 2007, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -13,8 +13,8 @@
import java.lang.reflect.Field;
import java.util.Map;
+import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.core.util.OrderRetainingMap;
-import com.thoughtworks.xstream.io.StreamException;
import junit.framework.TestCase;
@@ -49,8 +49,8 @@
try {
sorter.sort(Base.class, buildMap(Base.class));
fail();
- } catch (StreamException ex) {
- // ok
+ } catch (ConversionException ex) {
+ assertEquals(Base.class.getName(), ex.get("sort-type"));
}
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/core/ReferenceByXPathMarshallingStrategyTest.java b/xstream/src/test/com/thoughtworks/xstream/core/ReferenceByXPathMarshallingStrategyTest.java
index 8e42bf1..3d19dad 100644
--- a/xstream/src/test/com/thoughtworks/xstream/core/ReferenceByXPathMarshallingStrategyTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/core/ReferenceByXPathMarshallingStrategyTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,9 +14,19 @@
import com.thoughtworks.acceptance.AbstractAcceptanceTest;
import com.thoughtworks.acceptance.objects.StandardObject;
import com.thoughtworks.xstream.XStream;
-
+import com.thoughtworks.xstream.converters.ConverterLookup;
+import com.thoughtworks.xstream.core.util.ObjectIdDictionary;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.io.path.Path;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
public class ReferenceByXPathMarshallingStrategyTest extends AbstractAcceptanceTest {
@@ -88,4 +98,135 @@
assertBothWays(list, expected);
}
+
+ public class CountingXPathStrategy extends ReferenceByXPathMarshallingStrategy{
+
+ public CountingXPathStrategy() {
+ super(ReferenceByXPathMarshallingStrategy.ABSOLUTE);
+ }
+
+ public ReferenceByXPathMarshaller requestedMarshaller;
+ public ReferenceByXPathUnmarshaller requestedUnmarshaller;
+
+ protected TreeUnmarshaller createUnmarshallingContext(Object root,
+ HierarchicalStreamReader reader,
+ ConverterLookup converterLookup,
+ Mapper mapper) {
+
+ assertNull("strategy can only make one unmarshaller", requestedUnmarshaller);
+ requestedUnmarshaller = (ReferenceByXPathUnmarshaller) super.createUnmarshallingContext(root, reader, converterLookup, mapper);
+ return requestedUnmarshaller;
+ }
+
+ protected TreeMarshaller createMarshallingContext(HierarchicalStreamWriter writer,
+ ConverterLookup converterLookup,
+ Mapper mapper) {
+
+ assertNull("strategy can only make one marshaller", requestedMarshaller);
+ requestedMarshaller = (ReferenceByXPathMarshaller) super.createMarshallingContext(writer, converterLookup, mapper);
+ return requestedMarshaller;
+ }
+ }
+
+ public void testDoNotKeepXPathMapForImmutablesOnMarshall() throws MalformedURLException {
+ //configure XStream
+ CountingXPathStrategy marshallingStrategy = new CountingXPathStrategy();
+ xstream.setMarshallingStrategy(marshallingStrategy);
+
+ //setup document
+ List list = new ArrayList();
+ URL url = new URL("http://jira.codehaus.org/browse");
+ list.add(url);
+ list.add(url);
+
+ //act
+ String serialized = xstream.toXML(list);
+
+ //assert
+ ObjectIdDictionary trackedPathsOnMarshal = getReferences(marshallingStrategy.requestedMarshaller);
+
+ assertTrue(trackedPathsOnMarshal.containsId(list));
+ assertEquals(1, trackedPathsOnMarshal.size());
+ }
+
+ public void testDoNotKeepXPathMapForImmutablesOnUnmarshall() {
+ //configure XStream
+ CountingXPathStrategy marshallingStrategy = new CountingXPathStrategy();
+ xstream.setMarshallingStrategy(marshallingStrategy);
+
+ //setup document
+ String document = ""
+ + ""
+ + " http://jira.codehaus.org/browse"
+ + " http://jira.codehaus.org/browse"
+ + "
";
+
+ //act
+ Object result = xstream.fromXML(document);
+
+ //assert
+ Map trackedPathsOnUnmarshal = getReferences(marshallingStrategy.requestedUnmarshaller);
+
+ assertTrue(trackedPathsOnUnmarshal.containsKey(new Path("/list")));
+ assertEquals(1, trackedPathsOnUnmarshal.size());
+ }
+
+ public static class DomainType extends StandardObject{
+ public String value;
+
+ public DomainType(String value){
+ this.value = value;
+ }
+ }
+
+ public void testDoesKeepXPathMapForBackwardsCompatibleImmutablesOnUnmarshall() {
+ //configure XStream
+ CountingXPathStrategy marshallingStrategy = new CountingXPathStrategy();
+ xstream.setMarshallingStrategy(marshallingStrategy);
+ xstream.addImmutableType(Thing.class, true);
+
+ //setup document
+ String document = ""
+ + ""
+ + " "
+ + " JUnit"
+ + " "
+ + " "
+ + " JUnit"
+ + " "
+ + "
";
+
+ //act
+ Object result = xstream.fromXML(document);
+
+ //assert
+ Map trackedPathsOnUnmarshal = getReferences(marshallingStrategy.requestedUnmarshaller);
+
+ assertTrue(trackedPathsOnUnmarshal.containsKey(new Path("/list")));
+ assertTrue(trackedPathsOnUnmarshal.containsKey(new Path("/list/thing")));
+ assertTrue(trackedPathsOnUnmarshal.containsKey(new Path("/list/thing[2]")));
+ assertEquals(3, trackedPathsOnUnmarshal.size());
+ }
+
+ private Map getReferences(ReferenceByXPathUnmarshaller requestedUnmarshaller) {
+ try {
+ Field field = AbstractReferenceUnmarshaller.class.getDeclaredField("values");
+ field.setAccessible(true);
+ return (Map) field.get(requestedUnmarshaller);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private ObjectIdDictionary getReferences(ReferenceByXPathMarshaller requestedMarshaller) {
+ try {
+ Field field = AbstractReferenceMarshaller.class.getDeclaredField("references");
+ field.setAccessible(true);
+ return (ObjectIdDictionary) field.get(requestedMarshaller);
+ }
+ catch(Exception e){
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/core/util/DependencyInjectionFactoryTest.java b/xstream/src/test/com/thoughtworks/xstream/core/util/DependencyInjectionFactoryTest.java
index de7c425..6afa791 100644
--- a/xstream/src/test/com/thoughtworks/xstream/core/util/DependencyInjectionFactoryTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/core/util/DependencyInjectionFactoryTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2009, 2010, 2011, 2012 XStream Committers.
+ * Copyright (C) 2007, 2009, 2010, 2011, 2012, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,6 +10,7 @@
*/
package com.thoughtworks.xstream.core.util;
+import com.thoughtworks.xstream.converters.ErrorWriter;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import junit.framework.TestCase;
@@ -24,8 +25,8 @@
ObjectAccessException.class, new Object[]{
"The message", this, new RuntimeException("JUnit")}, used);
assertTrue(exception instanceof ObjectAccessException);
- assertEquals("The message : JUnit", exception.getMessage());
- assertEquals("JUnit", ((ObjectAccessException)exception).getCause().getMessage());
+ assertEquals("The message", ((ErrorWriter)exception).get("message"));
+ assertEquals("JUnit", ((ErrorWriter)exception).get("cause-message"));
assertTrue(used.get(0));
assertFalse(used.get(1));
assertTrue(used.get(2));
@@ -45,7 +46,8 @@
ObjectAccessException.class, new Object[]{
new TypedNull(String.class), this, new RuntimeException("JUnit")}, used);
assertTrue(exception instanceof ObjectAccessException);
- assertEquals("null : JUnit", exception.getMessage());
+ assertNull(((ErrorWriter)exception).get("message"));
+ assertEquals("JUnit", ((ErrorWriter)exception).get("cause-message"));
assertTrue(used.get(0));
assertFalse(used.get(1));
assertTrue(used.get(2));
@@ -69,7 +71,8 @@
ObjectAccessException.class, new Object[]{
new RuntimeException("JUnit"), this, "The message"}, used);
assertTrue(exception instanceof ObjectAccessException);
- assertEquals("The message : JUnit", exception.getMessage());
+ assertEquals("The message", ((ErrorWriter)exception).get("message"));
+ assertEquals("JUnit", ((ErrorWriter)exception).get("cause-message"));
assertTrue(used.get(0));
assertFalse(used.get(1));
assertTrue(used.get(2));
@@ -82,7 +85,8 @@
new RuntimeException("JUnit"), new IllegalArgumentException("foo"), this,
"The message"}, used);
assertTrue(exception instanceof ObjectAccessException);
- assertEquals("The message : foo", exception.getMessage());
+ assertEquals("The message", ((ErrorWriter)exception).get("message"));
+ assertEquals("foo", ((ErrorWriter)exception).get("cause-message"));
assertFalse(used.get(0));
assertTrue(used.get(1));
assertFalse(used.get(2));
@@ -96,7 +100,8 @@
new RuntimeException("JUnit"), "The message", "bar",
new IllegalArgumentException("foo"), this}, used);
assertTrue(exception instanceof ObjectAccessException);
- assertEquals("The message : foo", exception.getMessage());
+ assertEquals("The message", ((ErrorWriter)exception).get("message"));
+ assertEquals("foo", ((ErrorWriter)exception).get("cause-message"));
assertFalse(used.get(0));
assertTrue(used.get(1));
assertFalse(used.get(2));
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/binary/BinaryStreamTest.java b/xstream/src/test/com/thoughtworks/xstream/io/binary/BinaryStreamTest.java
index ba347af..d34962b 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/binary/BinaryStreamTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/binary/BinaryStreamTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2011, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,6 +11,7 @@
*/
package com.thoughtworks.xstream.io.binary;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier;
@@ -76,4 +77,16 @@
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("resolve entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/copy/HierarchicalStreamCopierTest.java b/xstream/src/test/com/thoughtworks/xstream/io/copy/HierarchicalStreamCopierTest.java
index e9a88ae..9f65b80 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/copy/HierarchicalStreamCopierTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/copy/HierarchicalStreamCopierTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2011, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,6 +11,7 @@
*/
package com.thoughtworks.xstream.io.copy;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.AbstractXMLReaderTest;
@@ -58,4 +59,16 @@
assertEquals(expected, buffer.toString());
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("resolve entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/AbstractXMLReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/AbstractXMLReaderTest.java
index 7f818ef..194e930 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/AbstractXMLReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/AbstractXMLReaderTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2012, 2013, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -242,6 +242,31 @@
assertEquals(content, xmlReader.getValue());
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ HierarchicalStreamReader xmlReader = createReader(""
+ + "\n"
+ +"\n"
+ +"\n"
+// +"\n"
+// +"\n"
+ +"]>&content;");
+ assertEquals("", xmlReader.getValue());
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ HierarchicalStreamReader xmlReader = createReader(""
+ + "\n"
+ +"\n"
+ +"\n"
+// +"\n"
+// +"\n"
+ +"%content;\n"
+ +"]>test");
+ assertEquals("test", xmlReader.getValue());
+ }
+
// TODO: See XSTR-473
public void todoTestCanReadNullValueInString() throws Exception {
HierarchicalStreamReader xmlReader = createReader("");
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/BEAStaxReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/BEAStaxReaderTest.java
index cc2a10a..8a92e40 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/BEAStaxReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/BEAStaxReaderTest.java
@@ -1,27 +1,33 @@
/*
- * Copyright (C) 2011 XStream Committers.
+ * Copyright (C) 2011, 2015 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 30. September 2011 by Joerg Schaible
*/
package com.thoughtworks.xstream.io.xml;
+import java.io.StringReader;
+
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import java.io.StringReader;
public class BEAStaxReaderTest extends AbstractXMLReaderTest {
-
- private HierarchicalStreamDriver driver = new BEAStaxDriver();
+
+ private final HierarchicalStreamDriver driver = new BEAStaxDriver();
// factory method
- protected HierarchicalStreamReader createReader(String xml) throws Exception {
+ protected HierarchicalStreamReader createReader(final String xml) throws Exception {
return driver.createReader(new StringReader(xml));
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ // Implementation ignores XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES set to false.
+ // super.testIsXXEVulnerableWithExternalParameterEntity();
}
// inherits tests from superclass
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/Dom4JReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/Dom4JReaderTest.java
index a6a7ad7..5c69ee5 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/Dom4JReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/Dom4JReaderTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,7 +11,11 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+import java.io.StringReader;
import org.dom4j.Document;
import org.dom4j.DocumentException;
@@ -22,7 +26,7 @@
// factory method
protected HierarchicalStreamReader createReader(String xml) throws Exception {
- return new Dom4JReader(DocumentHelper.parseText(xml));
+ return new Dom4JDriver().createReader(new StringReader(xml));
}
public void testCanReadFromElementOfLargerDocument() throws DocumentException {
@@ -42,4 +46,32 @@
assertEquals("tiny", xmlReader.getNodeName());
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("DOCTYPE") < 0) {
+ if (JVM.is17() || (JVM.is16() && message.indexOf("Nested exception: null") < 0)) {
+ throw e;
+ }
+ }
+ }
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("DOCTYPE") < 0) {
+ if (JVM.is17() || (JVM.is16() && message.indexOf("Nested exception: null") < 0)) {
+ throw e;
+ }
+ }
+ }
+ }
+
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/DomReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/DomReaderTest.java
index ab94ebe..4ca3b89 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/DomReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/DomReaderTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,6 +11,8 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import org.w3c.dom.Document;
@@ -20,6 +22,7 @@
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
+import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
@@ -27,7 +30,7 @@
// factory method
protected HierarchicalStreamReader createReader(String xml) throws Exception {
- return new DomReader(buildDocument(xml));
+ return new DomDriver().createReader(new StringReader(xml));
}
private Document buildDocument(String xml) throws Exception {
@@ -82,4 +85,44 @@
assertEquals(0, xmlReader.getAttributeCount());
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ if (JVM.is16()) {
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ }
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("DOCTYPE") < 0) {
+ throw e;
+ }
+ } catch (final NullPointerException e) {
+ // NPE only with Sun Java 1.6 runtime
+ if (JVM.is17() || !JVM.is16()) {
+ throw e;
+ }
+ }
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("DOCTYPE") < 0) {
+ // XXE vulnerable with Sun Java 1.6 runtime
+ if (JVM.is16()) {
+ throw e;
+ } else {
+ System.err.println("DomReader is vulnerable with Java 5 and 1.4!");
+ }
+ }
+ } catch (final NullPointerException e) {
+ // NPE only with Sun Java 1.6 runtime
+ if (JVM.is17() || !JVM.is16()) {
+ throw e;
+ }
+ }
+ }
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/JDom2ReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/JDom2ReaderTest.java
index 8d763a4..c17630b 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/JDom2ReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/JDom2ReaderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 XStream Committers.
+ * Copyright (C) 2013, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,9 +10,12 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import org.jdom2.Document;
+import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.io.StringReader;
@@ -21,8 +24,59 @@
// factory method
protected HierarchicalStreamReader createReader(String xml) throws Exception {
+ return new JDom2Driver().createReader(new StringReader(xml));
+ }
+
+ public void testCanReadFromElementOfLargerDocument() throws Exception {
+ String xml ="" +
+ "" +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ "";
Document document = new SAXBuilder().build(new StringReader(xml));
- return new JDom2Reader(document);
+ Element element = document.getRootElement().getChild("small");
+
+ HierarchicalStreamReader xmlReader = new JDom2Reader(element);
+ assertEquals("small", xmlReader.getNodeName());
+ xmlReader.moveDown();
+ assertEquals("tiny", xmlReader.getNodeName());
+ }
+
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (!message.contains("DOCTYPE")) {
+ throw e;
+ }
+ } catch (final NullPointerException e) {
+ // NPE only with Sun Java 1.6 runtime
+ if (JVM.is17()) {
+ throw e;
+ }
+ }
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (!message.contains("DOCTYPE")) {
+ throw e;
+ }
+ } catch (final NullPointerException e) {
+ // NPE only with Sun Java 1.6 runtime
+ if (JVM.is17()) {
+ throw e;
+ }
+ }
}
// inherits tests from superclass
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/JDomReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/JDomReaderTest.java
index 506cb86..646669d 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/JDomReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/JDomReaderTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,9 +11,12 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import org.jdom.Document;
+import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import java.io.StringReader;
@@ -22,8 +25,59 @@
// factory method
protected HierarchicalStreamReader createReader(String xml) throws Exception {
+ return new JDomDriver().createReader(new StringReader(xml));
+ }
+
+ public void testCanReadFromElementOfLargerDocument() throws Exception {
+ String xml ="" +
+ "" +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ "";
Document document = new SAXBuilder().build(new StringReader(xml));
- return new JDomReader(document);
+ Element element = document.getRootElement().getChild("small");
+
+ HierarchicalStreamReader xmlReader = new JDomReader(element);
+ assertEquals("small", xmlReader.getNodeName());
+ xmlReader.moveDown();
+ assertEquals("tiny", xmlReader.getNodeName());
+ }
+
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("DOCTYPE") < 0) {
+ throw e;
+ }
+ } catch (final NullPointerException e) {
+ // NPE only with Sun Java 1.6 runtime
+ if (JVM.is17()) {
+ throw e;
+ }
+ }
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("DOCTYPE") < 0) {
+ throw e;
+ }
+ } catch (final NullPointerException e) {
+ // NPE only with Sun Java 1.6 runtime
+ if (JVM.is17()) {
+ throw e;
+ }
+ }
}
// inherits tests from superclass
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/KXml2ReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/KXml2ReaderTest.java
index 8d7f8ae..0a65383 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/KXml2ReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/KXml2ReaderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 XStream Committers.
+ * Copyright (C) 2011, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,6 +10,7 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
@@ -28,5 +29,17 @@
return driver.createReader(new StringReader(xml));
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("unresolved") < 0) {
+ throw e;
+ }
+ }
+ }
+
// inherits tests from superclass
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/SjsxpReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/SjsxpReaderTest.java
index 46e0322..5361b85 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/SjsxpReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/SjsxpReaderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 XStream Committers.
+ * Copyright (C) 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,6 +10,8 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
@@ -47,5 +49,12 @@
return driver.createReader(new StringReader(xml));
}
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ // Fails for Java 1.6 runtime
+ if (JVM.is17()) {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ }
+ }
+
// inherits tests from superclass
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/StandardStaxReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/StandardStaxReaderTest.java
new file mode 100644
index 0000000..274881f
--- /dev/null
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/StandardStaxReaderTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 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. September 2015 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.io.xml;
+
+import com.thoughtworks.xstream.core.JVM;
+import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import java.io.StringReader;
+
+public class StandardStaxReaderTest extends AbstractXMLReaderTest {
+
+ public static Test suite() {
+ if (JVM.is16()) {
+ return new TestSuite(StandardStaxReaderTest.class);
+ } else {
+ return new TestCase(StandardStaxReaderTest.class.getName() + ": not available") {
+
+ public int countTestCases() {
+ return 1;
+ }
+
+ public void run(TestResult result) {
+ }
+ };
+ }
+ }
+
+ private HierarchicalStreamDriver driver = new StandardStaxDriver();
+
+ // factory method
+ protected HierarchicalStreamReader createReader(String xml) throws Exception {
+ return driver.createReader(new StringReader(xml));
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ // fails for Sun JDK 1.6 runtime
+ if (JVM.is17() || !JVM.getStaxInputFactory().getName().equals("com.sun.xml.internal.stream.XMLInputFactoryImpl")) {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ }
+ }
+
+ // inherits tests from superclass
+}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/StaxReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/StaxReaderTest.java
index 3fa489d..1bc7ab4 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/StaxReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/StaxReaderTest.java
@@ -1,24 +1,61 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015, 2016 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. September 2004 by James Strachan
*/
package com.thoughtworks.xstream.io.xml;
+import java.io.StringReader;
+
+import com.thoughtworks.xstream.XStreamException;
+import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import java.io.StringReader;
public class StaxReaderTest extends AbstractXMLReaderTest {
- protected HierarchicalStreamReader createReader(String xml) throws Exception {
- StaxDriver driver = new StaxDriver();
+ protected HierarchicalStreamReader createReader(final String xml) throws Exception {
+ final StaxDriver driver = new StaxDriver();
return driver.createReader(new StringReader(xml));
+ }
+
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("external entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (JVM.is14() && message == null) {
+ if (JVM.is16()) {
+ throw e;
+ }
+ System.err.println("BEAStaxReader was selected as default StAX driver for StaxReaderTest!");
+ } else if (message.indexOf("external entity") < 0) {
+ if (JVM.is16() && message.indexOf("com.wutka.dtd.DTDParseException") >= 0) {
+ System.err.println("BEAStaxReader was selected as default StAX driver for StaxReaderTest!");
+ } else if (message.replaceAll("[:space:]", "").endsWith("null")) {
+ System.err.println("BEAStaxReader was selected as default StAX driver for StaxReaderTest!");
+ } else {
+ throw e;
+ }
+ }
+ }
}
// inherits tests from superclass
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/WstxReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/WstxReaderTest.java
index e486d51..eb42cd9 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/WstxReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/WstxReaderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 XStream Committers.
+ * Copyright (C) 2011, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,6 +10,7 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
@@ -24,5 +25,29 @@
return driver.createReader(new StringReader(xml));
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("external entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalParameterEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("external entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
// inherits tests from superclass
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/XomReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/XomReaderTest.java
index 491222f..dcf7e74 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/XomReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/XomReaderTest.java
@@ -1,29 +1,59 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 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. September 2004 by Joe Walnes
*/
package com.thoughtworks.xstream.io.xml;
+import java.io.StringReader;
+
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import nu.xom.Builder;
import nu.xom.Document;
+import nu.xom.Element;
-import java.io.StringReader;
public class XomReaderTest extends AbstractXMLReaderTest {
// factory method
- protected HierarchicalStreamReader createReader(String xml) throws Exception {
- Document document = new Builder().build(new StringReader(xml));
- return new XomReader(document);
+ protected HierarchicalStreamReader createReader(final String xml) throws Exception {
+ return new XomDriver().createReader(new StringReader(xml));
+ }
+
+ public void testCanReadFromElementOfLargerDocument() throws Exception {
+ final String xml = ""
+ + ""
+ + " "
+ + " "
+ + " "
+ + " "
+ + " "
+ + "";
+ final Document document = new Builder().build(new StringReader(xml));
+ final Element element = document.getRootElement().getFirstChildElement("small");
+
+ final HierarchicalStreamReader xmlReader = new XomReader(element);
+ assertEquals("small", xmlReader.getNodeName());
+ xmlReader.moveDown();
+ assertEquals("tiny", xmlReader.getNodeName());
+ }
+
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ // No possibility to suppress support for external entities in XOM?
+ // super.testIsXXEVulnerableWithExternalGeneralEntity();
+ }
+
+ public void testIsXXEVulnerableWithExternalParameterEntity() throws Exception {
+ // No possibility to suppress support for external entities in XOM?
+ // super.testIsXXEVulnerableWithExternalParameterEntity();
}
// inherits tests from superclass
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/Xpp3ReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/Xpp3ReaderTest.java
index 1443663..d899a51 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/Xpp3ReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/Xpp3ReaderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 XStream Committers.
+ * Copyright (C) 2011, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -10,6 +10,7 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
@@ -24,5 +25,17 @@
return driver.createReader(new StringReader(xml));
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("resolve entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
// inherits tests from superclass
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/XppDomReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/XppDomReaderTest.java
index 7ae8d92..ac2fcdc 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/XppDomReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/XppDomReaderTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2011, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,6 +11,7 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.xml.xppdom.XppDom;
import com.thoughtworks.xstream.io.xml.xppdom.XppFactory;
@@ -75,4 +76,16 @@
assertEquals(0, xmlReader.getAttributeCount());
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("resolve entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
}
diff --git a/xstream/src/test/com/thoughtworks/xstream/io/xml/XppReaderTest.java b/xstream/src/test/com/thoughtworks/xstream/io/xml/XppReaderTest.java
index 80eeb1f..7852882 100644
--- a/xstream/src/test/com/thoughtworks/xstream/io/xml/XppReaderTest.java
+++ b/xstream/src/test/com/thoughtworks/xstream/io/xml/XppReaderTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015, 2016 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,6 +11,7 @@
*/
package com.thoughtworks.xstream.io.xml;
+import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import java.io.StringReader;
@@ -20,5 +21,17 @@
return new XppReader(new StringReader(xml));
}
+ public void testIsXXEVulnerableWithExternalGeneralEntity() throws Exception {
+ try {
+ super.testIsXXEVulnerableWithExternalGeneralEntity();
+ fail("Thrown " + XStreamException.class.getName() + " expected");
+ } catch (final XStreamException e) {
+ final String message = e.getCause().getMessage();
+ if (message.indexOf("resolve entity") < 0) {
+ throw e;
+ }
+ }
+ }
+
// inherits tests from superclass
}
diff --git a/xstream-benchmark/pom.xml b/xstream-benchmark/pom.xml
index d6fb34a..bb8ddfe 100644
--- a/xstream-benchmark/pom.xml
+++ b/xstream-benchmark/pom.xml
@@ -14,7 +14,7 @@
com.thoughtworks.xstream
xstream-parent
- 1.4.8
+ 1.4.9
xstream-benchmark
jar
@@ -91,10 +91,6 @@
org.apache.maven.plugins
- maven-source-plugin
-
-
- org.apache.maven.plugins
maven-surefire-plugin
true
@@ -133,4 +129,8 @@
junit
+
+
+ !com.thoughtworks.xstream.tools.benchmark.model,com.thoughtworks.xstream.tools.benchmark.*;-noimport:=true
+
diff --git a/xstream-benchmark/profiles/osgi b/xstream-benchmark/profiles/osgi
new file mode 100644
index 0000000..e69de29
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Harness.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Harness.java
index dd1bd74..6458cd4 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Harness.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Harness.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2013, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -53,6 +53,7 @@
*
*
* @author Joe Walnes
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class Harness {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Metric.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Metric.java
index 8d68b91..6a0db02 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Metric.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Metric.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @author Joe Walnes
* @author Jörg Schaible
* @see Harness
+ * @deprecated As of 1.4.9 use JMH instead
*/
public interface Metric {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Product.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Product.java
index 308ec39..eb86aca 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Product.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Product.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -20,6 +20,7 @@
*
* @author Joe Walnes
* @see Harness
+ * @deprecated As of 1.4.9 use JMH instead
*/
public interface Product {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Reporter.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Reporter.java
index 67775e3..b3aa546 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Reporter.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Reporter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -31,6 +31,7 @@
*
* @author Joe Walnes
* @see Harness
+ * @deprecated As of 1.4.9 use JMH instead
*/
public interface Reporter {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Target.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Target.java
index 1010f51..1996582 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Target.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/Target.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -20,6 +20,7 @@
*
* @author Joe Walnes
* @see Harness
+ * @deprecated As of 1.4.9 use JMH instead
*/
public interface Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/CharacterCountMetric.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/CharacterCountMetric.java
index 297d654..bd9f540 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/CharacterCountMetric.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/CharacterCountMetric.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2007, 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
*
* @author Jörg Schaible
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class CharacterCountMetric implements Metric {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/DeserializationSpeedMetric.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/DeserializationSpeedMetric.java
index 9817575..a48235e 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/DeserializationSpeedMetric.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/DeserializationSpeedMetric.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -25,6 +25,7 @@
* @author Jörg Schaible
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Metric
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class DeserializationSpeedMetric implements Metric {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SerializationSpeedMetric.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SerializationSpeedMetric.java
index 699e611..7949638 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SerializationSpeedMetric.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SerializationSpeedMetric.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -23,6 +23,7 @@
* @author Joe Walnes
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Metric
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class SerializationSpeedMetric implements Metric {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SizeMetric.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SizeMetric.java
index a31c9e9..0662e10 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SizeMetric.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/metrics/SizeMetric.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -23,6 +23,7 @@
* @author Joe Walnes
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Metric
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class SizeMetric implements Metric {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Fields.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Fields.java
index 770ebfe..02cc530 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Fields.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Fields.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2007, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,6 +14,7 @@
* Class with 100 fields.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class A100Fields {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Parents.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Parents.java
index a6439ac..5896365 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Parents.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A100Parents.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2007, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,6 +14,7 @@
* Class with 100 parents.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class A100Parents {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50InnerClasses.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50InnerClasses.java
index 749e3ae..963f019 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50InnerClasses.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50InnerClasses.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2007, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,6 +14,7 @@
* Class with inner classes 50 levels deep.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class A50InnerClasses {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50StaticInnerClasses.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50StaticInnerClasses.java
index ae296ce..bc621f2 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50StaticInnerClasses.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/A50StaticInnerClasses.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2009, 2011 XStream Committers.
+ * Copyright (C) 2007, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -14,6 +14,7 @@
* Class with static inner classes 50 levels deep.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class A50StaticInnerClasses {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/Five.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/Five.java
index 8daa634..4059ea0 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/Five.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/Five.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -15,6 +15,7 @@
* Class containing 5 basic types.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class Five extends One {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/FiveBean.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/FiveBean.java
index 21216ab..021156d 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/FiveBean.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/FiveBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -15,6 +15,7 @@
* JavaBean class containing 5 basic types.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class FiveBean extends OneBean {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/One.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/One.java
index 8b40d05..2dfa3a7 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/One.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/One.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -15,6 +15,7 @@
* Class containing one basic type.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class One {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/OneBean.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/OneBean.java
index c9ae520..77dbc98 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/OneBean.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/OneBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -15,6 +15,7 @@
* JavaBean class containing one basic type.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class OneBean {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableFive.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableFive.java
index f1d4c2f..53e3415 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableFive.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableFive.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -18,6 +18,7 @@
* Serializable class containing 5 basic types.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class SerializableFive extends SerializableOne {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableOne.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableOne.java
index 104c301..7ef8acb 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableOne.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/model/SerializableOne.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -19,6 +19,7 @@
* Serializable class containing one basic types.
*
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class SerializableOne implements Serializable {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/JavaObjectSerialization.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/JavaObjectSerialization.java
index 6263761..1988e7c 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/JavaObjectSerialization.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/JavaObjectSerialization.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -26,6 +26,7 @@
* @see Product
* @see ObjectOutputStream
* @see ObjectInputStream
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class JavaObjectSerialization implements Product {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBEAStax.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBEAStax.java
index 373372e..16f674c 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBEAStax.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBEAStax.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see BEAStaxDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamBEAStax extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBinary.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBinary.java
index e66f848..2753c2c 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBinary.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBinary.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -28,6 +28,7 @@
* @see XStream
* @see BinaryStreamReader
* @see BinaryStreamWriter
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamBinary implements Product {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamCompact.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamCompact.java
index 7a99d0a..a1109a5 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamCompact.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamCompact.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -28,6 +28,7 @@
* @see Product
* @see XStream
* @see CompactWriter
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamCompact implements Product {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom.java
index d953e46..7c3388e 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see DomDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamDom extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom4J.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom4J.java
index d1b360c..8dbbbc2 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom4J.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom4J.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -25,6 +25,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see Dom4JDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamDom4J extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDriver.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDriver.java
index 43b500d..995c8dc 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDriver.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDriver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -30,6 +30,7 @@
* @author Joe Walnes
* @author Jörg Schaible
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamDriver implements Product {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamJDom.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamJDom.java
index b374d05..c1f771c 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamJDom.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamJDom.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see JDomDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamJDom extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2.java
index 5b688cb..5b7959b 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see KXml2Driver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamKXml2 extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2DOM.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2DOM.java
index 2b102f8..4a71e7e 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2DOM.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2DOM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see KXml2DomDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamKXml2DOM extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamSjsxp.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamSjsxp.java
index 05676f1..17d76cf 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamSjsxp.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamSjsxp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see SjsxpDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamSjsxp extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamStax.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamStax.java
index 8077f67..cf4ea15 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamStax.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamStax.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see StaxDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamStax extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamWoodstox.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamWoodstox.java
index a46df2d..6d743f3 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamWoodstox.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamWoodstox.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see WstxDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamWoodstox extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXom.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXom.java
index 6309ad1..d121c63 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXom.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXom.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see XomDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamXom extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp.java
index 4ae26e2..fadd959 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2009 XStream Committers.
+ * Copyright (C) 2006, 2007, 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -22,6 +22,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see XppDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamXpp extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3.java
index 567968b..d9fbc08 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see Xpp3Driver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamXpp3 extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3DOM.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3DOM.java
index 646f1fd..5cae364 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3DOM.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3DOM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 XStream Committers.
+ * Copyright (C) 2009, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Product
* @see com.thoughtworks.xstream.XStream
* @see Xpp3DomDriver
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class XStreamXpp3DOM extends XStreamDriver {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/HtmlReporter.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/HtmlReporter.java
index 437c4fa..9209bef 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/HtmlReporter.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/HtmlReporter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -25,6 +25,9 @@
import java.util.Iterator;
import java.util.Date;
+/**
+ * @deprecated As of 1.4.9 use JMH instead
+ */
public class HtmlReporter implements Reporter {
private final PrettyPrintWriter out;
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/MultiReporter.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/MultiReporter.java
index 270157f..a4ebc02 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/MultiReporter.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/MultiReporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 XStream Committers.
+ * Copyright (C) 2007, 2008, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -20,6 +20,7 @@
*
* @author Jörg Schaible
* @since 1.3
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class MultiReporter implements Reporter {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/TextReporter.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/TextReporter.java
index cdb696a..6c6e446 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/TextReporter.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/reporters/TextReporter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -25,6 +25,7 @@
* @author Joe Walnes
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Reporter
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class TextReporter implements Reporter {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/BasicTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/BasicTarget.java
index d7f4c90..a119f57 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/BasicTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/BasicTarget.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -22,6 +22,7 @@
*
* @author Jörg Schaible
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class BasicTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ExtendedTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ExtendedTarget.java
index 2c15837..62195da 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ExtendedTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ExtendedTarget.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -26,6 +26,7 @@
*
* @author Jörg Schaible
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class ExtendedTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JTreeTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JTreeTarget.java
index 00ed6cf..ee965f7 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JTreeTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JTreeTarget.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -22,6 +22,7 @@
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Target
* @see JTree
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class JTreeTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JavaBeanTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JavaBeanTarget.java
index dd7240c..fe868a6 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JavaBeanTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/JavaBeanTarget.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -22,6 +22,7 @@
*
* @author Jörg Schaible
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class JavaBeanTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ListTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ListTarget.java
index 89a5e43..1e37107 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ListTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ListTarget.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -22,6 +22,7 @@
* @author Joe Walnes
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Target
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class ListTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/Person.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/Person.java
index c347453..f1e92f9 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/Person.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/Person.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -16,6 +16,7 @@
/**
* @see UserDefinedClassTarget
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class Person implements Serializable {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ReflectionTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ReflectionTarget.java
index 1970f87..f8d31be 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ReflectionTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/ReflectionTarget.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -22,6 +22,7 @@
*
* @author Jörg Schaible
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class ReflectionTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/SerializableTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/SerializableTarget.java
index 537ba81..bff83dc 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/SerializableTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/SerializableTarget.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -22,6 +22,7 @@
*
* @author Jörg Schaible
* @since 1.4
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class SerializableTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/StringTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/StringTarget.java
index 0f11266..8b08b3a 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/StringTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/StringTarget.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -19,6 +19,7 @@
* @author Joe Walnes
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Target
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class StringTarget implements Target {
diff --git a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/UserDefinedClassTarget.java b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/UserDefinedClassTarget.java
index f82604b..5bcf1ff 100644
--- a/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/UserDefinedClassTarget.java
+++ b/xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/targets/UserDefinedClassTarget.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2015 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
* @author Joe Walnes
* @see com.thoughtworks.xstream.tools.benchmark.Harness
* @see Target
+ * @deprecated As of 1.4.9 use JMH instead
*/
public class UserDefinedClassTarget implements Target {
diff --git a/xstream-distribution/pom.xml b/xstream-distribution/pom.xml
index cd64e6b..c5274fb 100644
--- a/xstream-distribution/pom.xml
+++ b/xstream-distribution/pom.xml
@@ -1,7 +1,7 @@
+
+ Benchmarks
+
+
+
+
+ Introduction
+
+ Benchmark results are always dependent on a very individual setup. Normally it is not useful to generalize such results
+ for every use case, but it can give you a hint. However, if you're really in the need of maximum performance, you should
+ probably create an own benchmark with your objects or even use a profiler to detect the real hot spots in your application.
+
+ XStream uses the Java Microbenchmark Harness (JMH)
+ of the JDK Tools as benchmark framework starting with version 1.4.9. As result it contains a ZIP file
+ (xstream-jmh-<version>-app.zip) as new artifact containing anything required to run the benchmarks. Unpack
+ the file and use the scripts in the bin directory to execute the benchmarks. Use option -h to look at the
+ options provided by JMH. You may exchange the libraries in the lib directory with other versions of
+ XStream or the individual parsers or you may even add new JMH benchmarks to the default ones of XStream.
+
+ All benchmark values below measure the average throughput in nanosecond per operation. JMH provides additional
+ measurement options, see online help. The maximum deviation for each benchmark is recorded in the reference files
+ of the distributed ZIP file. The benchmark is executed on Linux 4.1.12 Gentoo 64-bit system with an Intel Core i7
+ CPU 920 of 2.67 GHz. Note again, that these values are no replacement for real profiler results and they may
+ vary from run to run (see reference files) due to this machine's background processes on a single CPU. However, it
+ can give you some idea of what you can expect using different parser technologies.
+
+ Parser Benchmark
+
+ The values represent the average throughput of 15 runs with a single thread. The benchmarks emphasis the parser
+ efficiency for different structures.
+
+
+
+ Parser |
+ Text |
+ Array |
+ Nested |
+
+
+ W3C DOM (Oracle JDK 1.8.0_66) |
+ 10037380.795 |
+ 54234293.351 |
+ 1917332.056 |
+
+
+ JDOM (1.1.3) |
+ 6368317.636 |
+ 7910979.223 |
+ 3862796.027 |
+
+
+ JDOM 2 (2.0.5) |
+ 5767640.105 |
+ 10570210.653 |
+ 2980906.727 |
+
+
+ DOM4J (1.6.1) |
+ 7816280.084 |
+ 92998322.952 |
+ 2108075.646 |
+
+
+ XOM (1.1) |
+ 7950778.533 |
+ 38704485.310 |
+ 2471019.743 |
+
+
+ StAX (BEA 1.2.0) |
+ 3108517.699 |
+ 1310406.961 |
+ 669111.164 |
+
+
+ StAX (Woodstox 3.2.7) |
+ 1884858.525 |
+ 1240767.393 |
+ 650470.623 |
+
+
+ StAX (Oracle JDK 1.8.0_66) |
+ 7366387.272 |
+ 1334398.501 |
+ 688229.709 |
+
+
+ XPP (Xpp3 min 1.1.4c) |
+ 2109341.076 |
+ 1309607.210 |
+ 3301732.767 |
+
+
+ XPP (kXML2 min 2.3.0) |
+ 3391204.266 |
+ 1514514.680 |
+ 8105934.241 |
+
+
+ Binary (XStream 1.4.9) |
+ 1144243.750 |
+ 1062031.901 |
+ 496839.565 |
+
+
+ Jettison (1.2) |
+ 3002547.220 |
+ 1159238.555 |
+ 682182.733 |
+
+
+
+
+ - Text
+ - A single element with a text of 100.000 characters.
+ - Array
+ - A single element with 1.000 child elements.
+ - Nested
+ - Nested elements in 500 levels.
+
+
+ Converter Type Benchmark
+
+ The values represent the average throughput of 16 runs with four threads using the Xpp3 parser for a structure
+ with 1.000 elements. The benchmarks demonstrate the different converter types that can be used for a standard Java
+ class.
+
+
+
+ Converter Type |
+ Throughput |
+
+
+ Custom |
+ 11276718.384 |
+
+
+ Java Bean |
+ 28878706.293 |
+
+
+ Reflection |
+ 40085786.696 |
+
+
+
+
+ - Custom
+ - A converter especially written for the Java type to convert.
+ - Java Bean
+ - Usage of the generic JavaBeanConverter, since the Java type respects the Java Bean contract.
+ - Reflection
+ - Usage of the generic converter based on reflection.
+
+
+ String Converter Benchmark
+
+ The values represent the average throughput of 16 runs with four threads using the Xpp3 parser for a structure
+ with 10.000 string elements of various sizes and duplicates. The benchmarks demonstrate different implementations
+ and configurations of the StringConverter.
+
+
+
+ StringConverter Strategy |
+ Throughput |
+
+
+ No Cache |
+ 19626160.696 |
+
+
+ Intern |
+ 23060982.052 |
+
+
+ ConcurrentMap (length limit) |
+ 21796001.29 |
+
+
+ ConcurrentMap (unlimited) |
+ 21378299.003 |
+
+
+ Sync'd WeakCache (length limit) |
+ 21838410.801 |
+
+
+ Sync'd WeakCache (unlimited) |
+ 22011251.691 |
+
+
+
+
+ - No Cache
+ - An implementation that does not cache deserialized String values with the consequence that repeated values
+ will always allocate separate memory.
+ - Intern
+ - An implementation that uses String.intern() to cache the individual values. The memory pool used for the
+ values is dependent on the JDK version. Up to Java 7 this was the permanent generation space i.e. the memory has
+ to be shared with all loaded classes. It is up to the garbage collection when these string values are freed
+ again.
+ - ConcurrentMap (length limit)
+ - An implementation that uses a ConcurrentHashMap as cache for strings of limited length (38 characters). The
+ lifetime of the cache is equivalent with the lifetime of the XStream instance.
+ - ConcurrentMap (unlimited)
+ - An implementation that uses a ConcurrentHashMap as cache for all strings. The lifetime of the cache is
+ equivalent with the lifetime of the XStream instance.
+ - Sync'd WeakCache (length limit)
+ - An implementation that uses a WeakCache for strings of limited length (38 characters). This cache uses weak
+ references for its keys and values. An entry is therefore only kept as long as the deserialized object structure
+ is referencing it. This is XStream's default strategy.
+ - Syn'd WeakCache (unlimited)
+ - An implementation that uses a WeakCache for all strings. This cache uses weak references for its keys and
+ values. An entry is therefore ony kept as long as the deserialized object structure is referencing it.
+
+
+ Name Coder Benchmark
+
+ The values represent the average throughput of 25 runs with four threads using the Xpp3 parser for a structure
+ with 250 nested elements using names invalid for XML elements. The benchmarks demonstrate different implementation
+ strategies for a NameCoder to create valid tag names in XML.
+
+
+
+ NameCoder Implementation |
+ Throughput |
+
+
+ No Coding |
+ 7299475.975 |
+
+
+ Dollar Coding |
+ 7767196.902 |
+
+
+ Escaped Underscore Coding |
+ 9894393.289 |
+
+
+ Cached Escaped Underscore Coding |
+ 7867671.962 |
+
+
+ Xml Friendly Coding |
+ 8635501.208 |
+
+
+
+
+ - No Coding
+ - An implementation that does not encode the names of XML elements. It relies on the fact that the object graph
+ does not contain elements with invalid XML names, because the name of the class types and members are either
+ conforming or have been aliased.
+ - Dollar Coding
+ - An implementation that uses String.replace to replace any dollar sign with '·' (middle dot), a valid
+ character normally not used for Java identifiers. In typical Java code there are no other invalid characters used
+ for Java identifiers, however, Java allows identifiers to contain a wide range of UTF-8 characters and the JVM
+ has even less restrictions.
+ - Escaped Underscore Coding
+ - An implementation that uses a StringBuilder to create the XML name by replacing any dollar sign with '_-' and
+ escapes every plain underscore with two ones. The implementation will therefore only use characters in the
+ standard ASCII range. It is not possible to use a simple minus sign as replacement because it is not a valid
+ first character for XML names. However, the comments about Java identifiers and JVM identifiers from the Dollar
+ Coding still apply.
+ - Cached Escaped Underscore Coding
+ - An implementation that implements a cache for the NameCoder that escapes the underscores.
+ - Xml Friendly Coding
+ - The default implementation of XStream using a StringBuilder and a cache, encoding any character that is
+ invalid for XML names. It implements also the underscore escaping for compatibility reasons with XML created by
+ earlier versions of XStream.
+
+
+