Codebase list libxstream-java / e1a339d
New upstream version 1.4.10 Emmanuel Bourg 6 years ago
121 changed file(s) with 7028 addition(s) and 2313 deletion(s). Raw diff Collapse all Expand all
00 language: java
1 sudo: false
12 jdk:
23 - oraclejdk8
34 - oraclejdk7
45 - openjdk6
56 install: true
6 script: "mvn -V -B -e clean package"
7 script:
8 if ( `javac -version 2>&1 | grep '1\.8\.0' > /dev/null` ); then
9 mkdir -p xstream/profiles/coveralls;
10 mkdir -p xstream-hibernate/profiles/coveralls;
11 mvn -V -B -e clean package cobertura:cobertura coveralls:report;
12 else
13 mvn -V -B -e clean package;
14 fi
715 cache:
816 directories:
917 - $HOME/.m2
0 For Java 6 or higher build with Maven 3.2.5 or higher
0 For Java 7, 8, or 9 build with Maven 3.3.9 or higher
1 For Java 6 or higher build with Maven 3.2.5
12 For Java 5 build with Maven 3.0.5
23 For Java 1.4 build with Maven 2.0.11
3
4 Before building:
54
65 To build:
76
0 [![Build Status](https://travis-ci.org/x-stream/xstream.svg?branch=v-1.4.x)](https://travis-ci.org/x-stream/xstream)
1 ----
0 master: [![Build Status](https://travis-ci.org/x-stream/xstream.svg?branch=master)](https://travis-ci.org/x-stream/xstream) [![Coverage Status](https://coveralls.io/repos/github/x-stream/xstream/badge.svg?branch=master)](https://coveralls.io/github/x-stream/xstream?branch=master)
1 v-1.4.x: [![Build Status](https://travis-ci.org/x-stream/xstream.svg?branch=v-1.4.x)](https://travis-ci.org/x-stream/xstream) [![Coverage Status](https://coveralls.io/repos/github/x-stream/xstream/badge.svg?branch=v-1.4.x)](https://coveralls.io/github/x-stream/xstream?branch=v-1.4.x)
2
3 - - - -
24 # XStream
35 _Java to XML Serialization, and back again_
46
00 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
11 <!--
22 Copyright (C) 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
1313 <groupId>com.thoughtworks.xstream</groupId>
1414 <artifactId>xstream-parent</artifactId>
1515 <packaging>pom</packaging>
16 <version>1.4.9</version>
16 <version>1.4.10</version>
1717 <name>XStream Parent</name>
1818 <url>http://x-stream.github.io</url>
1919 <description>
3838 <profile>
3939 <id>jdk19</id>
4040 <activation>
41 <jdk>1.9</jdk>
41 <jdk>9</jdk>
4242 </activation>
4343 <properties>
4444 <version.java.source>1.6</version.java.source>
5252 </activation>
5353 <properties>
5454 <javadoc.xdoclint>-Xdoclint:-missing</javadoc.xdoclint>
55 <version.plugin.felix.bundle>2.5.4</version.plugin.felix.bundle>
56 </properties>
57 </profile>
58 <profile>
59 <id>jdk16</id>
60 <activation>
61 <jdk>1.6</jdk>
62 </activation>
63 <properties>
64 <version.org.openjdk.jmh>1.16</version.org.openjdk.jmh>
5565 </properties>
5666 </profile>
5767 <profile>
204214 </plugins>
205215 </build>
206216 </profile>
217 <profile>
218 <id>coveralls</id>
219 <activation>
220 <file>
221 <exists>profiles/coveralls</exists>
222 </file>
223 </activation>
224 <build>
225 <plugins>
226 <plugin>
227 <groupId>org.codehaus.mojo</groupId>
228 <artifactId>cobertura-maven-plugin</artifactId>
229 <configuration>
230 <formats>
231 <format>xml</format>
232 </formats>
233 <aggregate>true</aggregate>
234 </configuration>
235 </plugin>
236 <plugin>
237 <groupId>org.eluder.coveralls</groupId>
238 <artifactId>coveralls-maven-plugin</artifactId>
239 </plugin>
240 </plugins>
241 </build>
242 </profile>
207243 </profiles>
208244
209245 <modules>
268304 <dependency>
269305 <groupId>com.thoughtworks.xstream</groupId>
270306 <artifactId>xstream</artifactId>
271 <version>1.4.9</version>
307 <version>1.4.10</version>
272308 </dependency>
273309 <dependency>
274310 <groupId>com.thoughtworks.xstream</groupId>
275311 <artifactId>xstream</artifactId>
276 <version>1.4.9</version>
312 <version>1.4.10</version>
277313 <classifier>tests</classifier>
278314 <type>test-jar</type>
279315 <scope>test</scope>
281317 <dependency>
282318 <groupId>com.thoughtworks.xstream</groupId>
283319 <artifactId>xstream</artifactId>
284 <version>1.4.9</version>
320 <version>1.4.10</version>
285321 <classifier>javadoc</classifier>
286322 <scope>provided</scope>
287323 </dependency>
288324 <dependency>
289325 <groupId>com.thoughtworks.xstream</groupId>
290326 <artifactId>xstream-hibernate</artifactId>
291 <version>1.4.9</version>
327 <version>1.4.10</version>
292328 </dependency>
293329 <dependency>
294330 <groupId>com.thoughtworks.xstream</groupId>
295331 <artifactId>xstream-hibernate</artifactId>
296 <version>1.4.9</version>
332 <version>1.4.10</version>
297333 <classifier>javadoc</classifier>
298334 <scope>provided</scope>
299335 </dependency>
300336 <dependency>
301337 <groupId>com.thoughtworks.xstream</groupId>
302338 <artifactId>xstream-jmh</artifactId>
303 <version>1.4.9</version>
339 <version>1.4.10</version>
304340 </dependency>
305341 <dependency>
306342 <groupId>com.thoughtworks.xstream</groupId>
307343 <artifactId>xstream-jmh</artifactId>
308 <version>1.4.9</version>
344 <version>1.4.10</version>
309345 <classifier>javadoc</classifier>
310346 <scope>provided</scope>
311347 </dependency>
312348 <dependency>
313349 <groupId>com.thoughtworks.xstream</groupId>
314350 <artifactId>xstream-benchmark</artifactId>
315 <version>1.4.9</version>
351 <version>1.4.10</version>
316352 </dependency>
317353 <dependency>
318354 <groupId>com.thoughtworks.xstream</groupId>
319355 <artifactId>xstream-benchmark</artifactId>
320 <version>1.4.9</version>
356 <version>1.4.10</version>
321357 <classifier>javadoc</classifier>
322358 <scope>provided</scope>
323359 </dependency>
749785 <artifactId>maven-surefire-plugin</artifactId>
750786 <version>${version.plugin.maven.surefire}</version>
751787 <configuration>
788 <argLine>${surefire.argline}</argLine>
752789 <forkMode>once</forkMode>
753790 <printSummary>true</printSummary>
754791 <useFile>false</useFile>
817854 </manifest>
818855 </archive>
819856 </configuration>
857 </plugin>
858 <plugin>
859 <groupId>org.eluder.coveralls</groupId>
860 <artifactId>coveralls-maven-plugin</artifactId>
861 <version>${version.plugin.eluder.coveralls}</version>
820862 </plugin>
821863 </plugins>
822864 </pluginManagement>
903945 <version.plugin.maven.source>2.1.2</version.plugin.maven.source>
904946 <version.plugin.maven.surefire>2.4.3</version.plugin.maven.surefire>
905947 <version.plugin.mojo.build-helper>1.5</version.plugin.mojo.build-helper>
906 <version.plugin.mojo.cobertura>2.0</version.plugin.mojo.cobertura>
948 <version.plugin.mojo.cobertura>2.7</version.plugin.mojo.cobertura>
907949 <version.plugin.mojo.jxr>2.0-beta-1</version.plugin.mojo.jxr>
950 <version.plugin.eluder.coveralls>4.2.0</version.plugin.eluder.coveralls>
908951
909952 <version.org.apache.maven.wagon.webdev>1.0-beta-2</version.org.apache.maven.wagon.webdev>
910953
928971 <version.org.jdom>1.1.3</version.org.jdom>
929972 <version.org.jdom2>2.0.5</version.org.jdom2>
930973 <version.org.json>20080701</version.org.json>
931 <version.org.openjdk.jmh>1.11.1</version.org.openjdk.jmh>
974 <version.org.openjdk.jmh>1.19</version.org.openjdk.jmh>
932975 <version.org.slf4j>1.6.1</version.org.slf4j>
933976 <version.oro>2.0.8</version.oro>
934977 <version.stax>1.2.0</version.stax>
942985 <link.javadoc.javase>http://docs.oracle.com/javase/8/docs/api/</link.javadoc.javase>
943986
944987 <javadoc.xdoclint />
988 <surefire.argline />
945989 </properties>
946990 </project>
00 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
11 <!--
22 Copyright (C) 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
1313 <parent>
1414 <groupId>com.thoughtworks.xstream</groupId>
1515 <artifactId>xstream-parent</artifactId>
16 <version>1.4.9</version>
16 <version>1.4.10</version>
1717 </parent>
1818 <artifactId>xstream</artifactId>
1919 <packaging>jar</packaging>
205205
206206 <profiles>
207207 <profile>
208 <id>jdk18ge</id>
208 <id>jdk19-ge</id>
209 <activation>
210 <jdk>[9,)</jdk>
211 </activation>
212 <properties>
213 <surefire.argline>--add-modules java.activation --permit-illegal-access</surefire.argline>
214 </properties>
215 </profile>
216 <profile>
217 <id>jdk18-ge</id>
209218 <activation>
210219 <jdk>[1.8,)</jdk>
211220 </activation>
220229 </compilerArgs>
221230 <excludes>
222231 <exclude>**/Lambda**</exclude>
232 <exclude>**/time/**</exclude>
233 <exclude>**/ISO8601JavaTimeConverter.java</exclude>
223234 </excludes>
224235 <testExcludes>
225236 <exclude>**/Lambda**</exclude>
237 <exclude>**/*18TypesTest.java</exclude>
226238 </testExcludes>
227239 </configuration>
228240 <executions>
233245 <target>1.8</target>
234246 <excludes>
235247 <exclude>foo</exclude>
248 <exclude>foo</exclude>
249 <exclude>foo</exclude>
236250 </excludes>
237251 <testExcludes>
252 <exclude>foo</exclude>
238253 <exclude>foo</exclude>
239254 </testExcludes>
240255 </configuration>
245260 </execution>
246261 </executions>
247262 </plugin>
263 </plugins>
264 </build>
265 </profile>
266 <profile>
267 <id>jdk18</id>
268 <activation>
269 <jdk>1.8</jdk>
270 </activation>
271 <build>
272 <plugins>
248273 <plugin>
249274 <groupId>org.apache.maven.plugins</groupId>
250275 <artifactId>maven-javadoc-plugin</artifactId>
251276 <configuration>
277 <source>1.8</source>
252278 <excludePackageNames>com.thoughtworks.xstream.core.util</excludePackageNames>
253279 </configuration>
254280 </plugin>
264290 <excludePackageNames>com.thoughtworks.xstream.core.util</excludePackageNames>
265291 <additionalparam>${javadoc.xdoclint}</additionalparam>
266292 <detectJavaApiLink>false</detectJavaApiLink>
267 <source>${version.java.source}</source>
293 <source>1.8</source>
268294 <links>
269295 <link>${link.javadoc.javase}</link>
270296 </links>
289315 </compilerArgs>
290316 <excludes>
291317 <exclude>**/Lambda**</exclude>
318 <exclude>**/time/**</exclude>
319 <exclude>**/ISO8601JavaTimeConverter.java</exclude>
292320 </excludes>
293321 <testExcludes>
294322 <exclude>**/Lambda**</exclude>
323 <exclude>**/*18TypesTest.java</exclude>
295324 </testExcludes>
296325 </configuration>
297326 </plugin>
315344 <excludes>
316345 <exclude>**/Lambda**</exclude>
317346 <exclude>**/extended/PathConverter*</exclude>
347 <exclude>**/time/**</exclude>
348 <exclude>**/ISO8601JavaTimeConverter.java</exclude>
318349 </excludes>
319350 <testExcludes>
320351 <exclude>**/Lambda**</exclude>
352 <exclude>**/extended/*17Test*</exclude>
321353 <exclude>**/acceptance/Extended17TypesTest*</exclude>
322 <exclude>**/extended/*17Test*</exclude>
354 <exclude>**/acceptance/*18TypesTest.java</exclude>
323355 </testExcludes>
324356 </configuration>
325357 </plugin>
383415 <exclude>**/AnnotationMapper*</exclude>
384416 <exclude>**/EnumMapper*</exclude>
385417 <exclude>**/enums/*</exclude>
418 <exclude>**/time/**</exclude>
419 <exclude>**/ISO8601JavaTimeConverter.java</exclude>
386420 <exclude>**/basic/StringBuilder*</exclude>
387421 <exclude>**/basic/UUID*</exclude>
388422 <exclude>**/core/util/Types*</exclude>
401435 <exclude>**/acceptance/Basic15TypesTest*</exclude>
402436 <exclude>**/acceptance/Concurrent15TypesTest*</exclude>
403437 <exclude>**/acceptance/Extended17TypesTest*</exclude>
438 <exclude>**/acceptance/*18TypesTest.java</exclude>
404439 </testExcludes>
405440 </configuration>
406441 </plugin>
00 /*
11 * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
2525 import java.io.Writer;
2626 import java.lang.reflect.Constructor;
2727 import java.lang.reflect.Field;
28 import java.lang.reflect.InvocationTargetException;
29 import java.lang.reflect.Member;
2830 import java.lang.reflect.Method;
2931 import java.math.BigDecimal;
3032 import java.math.BigInteger;
3133 import java.net.URI;
3234 import java.net.URL;
35 import java.nio.charset.Charset;
36 import java.text.DecimalFormatSymbols;
3337 import java.util.ArrayList;
3438 import java.util.BitSet;
3539 import java.util.Calendar;
40 import java.util.Collection;
3641 import java.util.Collections;
42 import java.util.Currency;
3743 import java.util.Date;
3844 import java.util.GregorianCalendar;
3945 import java.util.HashMap;
4046 import java.util.HashSet;
4147 import java.util.Hashtable;
48 import java.util.Iterator;
4249 import java.util.LinkedList;
4350 import java.util.List;
4451 import java.util.Locale;
4653 import java.util.Properties;
4754 import java.util.Set;
4855 import java.util.SortedSet;
56 import java.util.TimeZone;
4957 import java.util.TreeMap;
5058 import java.util.TreeSet;
5159 import java.util.Vector;
5664 import com.thoughtworks.xstream.converters.ConverterLookup;
5765 import com.thoughtworks.xstream.converters.ConverterRegistry;
5866 import com.thoughtworks.xstream.converters.DataHolder;
67 import com.thoughtworks.xstream.converters.MarshallingContext;
5968 import com.thoughtworks.xstream.converters.SingleValueConverter;
6069 import com.thoughtworks.xstream.converters.SingleValueConverterWrapper;
70 import com.thoughtworks.xstream.converters.UnmarshallingContext;
6171 import com.thoughtworks.xstream.converters.basic.BigDecimalConverter;
6272 import com.thoughtworks.xstream.converters.basic.BigIntegerConverter;
6373 import com.thoughtworks.xstream.converters.basic.BooleanConverter;
128138 import com.thoughtworks.xstream.mapper.DefaultImplementationsMapper;
129139 import com.thoughtworks.xstream.mapper.DefaultMapper;
130140 import com.thoughtworks.xstream.mapper.DynamicProxyMapper;
141 import com.thoughtworks.xstream.mapper.ElementIgnoringMapper;
131142 import com.thoughtworks.xstream.mapper.FieldAliasingMapper;
132143 import com.thoughtworks.xstream.mapper.ImmutableTypesMapper;
133144 import com.thoughtworks.xstream.mapper.ImplicitCollectionMapper;
140151 import com.thoughtworks.xstream.mapper.SystemAttributeAliasingMapper;
141152 import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper;
142153 import com.thoughtworks.xstream.security.AnyTypePermission;
154 import com.thoughtworks.xstream.security.ArrayTypePermission;
143155 import com.thoughtworks.xstream.security.ExplicitTypePermission;
156 import com.thoughtworks.xstream.security.InterfaceTypePermission;
144157 import com.thoughtworks.xstream.security.NoPermission;
145158 import com.thoughtworks.xstream.security.NoTypePermission;
159 import com.thoughtworks.xstream.security.NullPermission;
160 import com.thoughtworks.xstream.security.PrimitiveTypePermission;
146161 import com.thoughtworks.xstream.security.RegExpTypePermission;
147162 import com.thoughtworks.xstream.security.TypeHierarchyPermission;
148163 import com.thoughtworks.xstream.security.TypePermission;
311326 private PackageAliasingMapper packageAliasingMapper;
312327 private ClassAliasingMapper classAliasingMapper;
313328 private FieldAliasingMapper fieldAliasingMapper;
329 private ElementIgnoringMapper elementIgnoringMapper;
314330 private AttributeAliasingMapper attributeAliasingMapper;
315331 private SystemAttributeAliasingMapper systemAttributeAliasingMapper;
316332 private AttributeMapper attributeMapper;
320336 private LocalConversionMapper localConversionMapper;
321337 private SecurityMapper securityMapper;
322338 private AnnotationConfiguration annotationConfiguration;
339
340 private transient boolean insecureWarning;
323341
324342 public static final int NO_REFERENCES = 1001;
325343 public static final int ID_REFERENCES = 1002;
583601 mapper = new DynamicProxyMapper(mapper);
584602 mapper = new PackageAliasingMapper(mapper);
585603 mapper = new ClassAliasingMapper(mapper);
604 mapper = new ElementIgnoringMapper(mapper);
586605 mapper = new FieldAliasingMapper(mapper);
587606 mapper = new AttributeAliasingMapper(mapper);
588607 mapper = new SystemAttributeAliasingMapper(mapper);
589 mapper = new ImplicitCollectionMapper(mapper);
608 mapper = new ImplicitCollectionMapper(mapper, reflectionProvider);
590609 mapper = new OuterClassMapper(mapper);
591610 mapper = new ArrayMapper(mapper);
592611 mapper = new DefaultImplementationsMapper(mapper);
599618 mapper = new LocalConversionMapper(mapper);
600619 mapper = new ImmutableTypesMapper(mapper);
601620 if (JVM.is18()) {
602 mapper =
603 buildMapperDynamically("com.thoughtworks.xstream.mapper.LambdaMapper", new Class[]{Mapper.class},
604 new Object[]{mapper});
621 mapper = buildMapperDynamically("com.thoughtworks.xstream.mapper.LambdaMapper", new Class[]{Mapper.class},
622 new Object[]{mapper});
605623 }
606624 mapper = new SecurityMapper(mapper);
607625 if (JVM.is15()) {
647665 .lookupMapperOfType(PackageAliasingMapper.class);
648666 classAliasingMapper = (ClassAliasingMapper)this.mapper
649667 .lookupMapperOfType(ClassAliasingMapper.class);
668 elementIgnoringMapper = (ElementIgnoringMapper)this.mapper
669 .lookupMapperOfType(ElementIgnoringMapper.class);
650670 fieldAliasingMapper = (FieldAliasingMapper)this.mapper
651671 .lookupMapperOfType(FieldAliasingMapper.class);
652672 attributeMapper = (AttributeMapper)this.mapper
675695 }
676696
677697 addPermission(AnyTypePermission.ANY);
698 insecureWarning = true;
699 }
700
701 /**
702 * Setup the security framework of a XStream instance.
703 * <p>
704 * This method is a pure helper method for XStream 1.4.x. It initializes an XStream instance with a white list of
705 * well-known and simply types of the Java runtime as it is done in XStream 1.5.x by default. This method will do
706 * therefore nothing in XStream 1.5.
707 * </p>
708 *
709 * @param xstream
710 * @since 1.4.10
711 */
712 public static void setupDefaultSecurity(final XStream xstream) {
713 if (xstream.insecureWarning) {
714 xstream.addPermission(NoTypePermission.NONE);
715 xstream.addPermission(NullPermission.NULL);
716 xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
717 xstream.addPermission(ArrayTypePermission.ARRAYS);
718 xstream.addPermission(InterfaceTypePermission.INTERFACES);
719 xstream.allowTypeHierarchy(Calendar.class);
720 xstream.allowTypeHierarchy(Collection.class);
721 xstream.allowTypeHierarchy(Map.class);
722 xstream.allowTypeHierarchy(Map.Entry.class);
723 xstream.allowTypeHierarchy(Member.class);
724 xstream.allowTypeHierarchy(Number.class);
725 xstream.allowTypeHierarchy(Throwable.class);
726 xstream.allowTypeHierarchy(TimeZone.class);
727
728 Class type = JVM.loadClassForName("java.lang.Enum");
729 if (type != null) {
730 xstream.allowTypeHierarchy(type);
731 }
732 type = JVM.loadClassForName("java.nio.file.Path");
733 if (type != null) {
734 xstream.allowTypeHierarchy(type);
735 }
736
737 final Set types = new HashSet();
738 types.add(BitSet.class);
739 types.add(Charset.class);
740 types.add(Class.class);
741 types.add(Currency.class);
742 types.add(Date.class);
743 types.add(DecimalFormatSymbols.class);
744 types.add(File.class);
745 types.add(Locale.class);
746 types.add(Object.class);
747 types.add(Pattern.class);
748 types.add(StackTraceElement.class);
749 types.add(String.class);
750 types.add(StringBuffer.class);
751 types.add(JVM.loadClassForName("java.lang.StringBuilder"));
752 types.add(URL.class);
753 types.add(URI.class);
754 types.add(JVM.loadClassForName("java.util.UUID"));
755 if (JVM.isSQLAvailable()) {
756 types.add(JVM.loadClassForName("java.sql.Timestamp"));
757 types.add(JVM.loadClassForName("java.sql.Time"));
758 types.add(JVM.loadClassForName("java.sql.Date"));
759 }
760 if (JVM.is18()) {
761 xstream.allowTypeHierarchy(JVM.loadClassForName("java.time.Clock"));
762 types.add(JVM.loadClassForName("java.time.Duration"));
763 types.add(JVM.loadClassForName("java.time.Instant"));
764 types.add(JVM.loadClassForName("java.time.LocalDate"));
765 types.add(JVM.loadClassForName("java.time.LocalDateTime"));
766 types.add(JVM.loadClassForName("java.time.LocalTime"));
767 types.add(JVM.loadClassForName("java.time.MonthDay"));
768 types.add(JVM.loadClassForName("java.time.OffsetDateTime"));
769 types.add(JVM.loadClassForName("java.time.OffsetTime"));
770 types.add(JVM.loadClassForName("java.time.Period"));
771 types.add(JVM.loadClassForName("java.time.Ser"));
772 types.add(JVM.loadClassForName("java.time.Year"));
773 types.add(JVM.loadClassForName("java.time.YearMonth"));
774 types.add(JVM.loadClassForName("java.time.ZonedDateTime"));
775 xstream.allowTypeHierarchy(JVM.loadClassForName("java.time.ZoneId"));
776 types.add(JVM.loadClassForName("java.time.chrono.HijrahDate"));
777 types.add(JVM.loadClassForName("java.time.chrono.JapaneseDate"));
778 types.add(JVM.loadClassForName("java.time.chrono.JapaneseEra"));
779 types.add(JVM.loadClassForName("java.time.chrono.MinguoDate"));
780 types.add(JVM.loadClassForName("java.time.chrono.ThaiBuddhistDate"));
781 types.add(JVM.loadClassForName("java.time.chrono.Ser"));
782 xstream.allowTypeHierarchy(JVM.loadClassForName("java.time.chrono.Chronology"));
783 types.add(JVM.loadClassForName("java.time.temporal.ValueRange"));
784 types.add(JVM.loadClassForName("java.time.temporal.WeekFields"));
785 }
786 types.remove(null);
787
788 final Iterator iter = types.iterator();
789 final Class[] classes = new Class[types.size()];
790 for (int i = 0; i < classes.length; ++i) {
791 classes[i] = (Class)iter.next();
792 }
793 xstream.allowTypes(classes);
794 } else {
795 throw new IllegalArgumentException("Security framework of XStream instance already initialized");
796 }
678797 }
679798
680799 protected void setupAliases() {
734853 alias("awt-color", JVM.loadClassForName("java.awt.Color", false));
735854 alias("awt-font", JVM.loadClassForName("java.awt.Font", false));
736855 alias("awt-text-attribute", JVM.loadClassForName("java.awt.font.TextAttribute"));
737
738 // only available in Java 5 when javax.activation:activation is available on CP
739 Class type = JVM.loadClassForName("javax.activation.ActivationDataFlavor");
740 if (type != null) {
741 alias("activation-data-flavor", type);
742 }
856 }
857
858 Class type = JVM.loadClassForName("javax.activation.ActivationDataFlavor");
859 if (type != null) {
860 alias("activation-data-flavor", type);
743861 }
744862
745863 if (JVM.isSQLAvailable()) {
762880 }
763881
764882 if (JVM.is15()) {
765 aliasDynamically("duration", "javax.xml.datatype.Duration");
883 aliasDynamically("xml-duration", "javax.xml.datatype.Duration");
766884 alias("concurrent-hash-map", JVM.loadClassForName("java.util.concurrent.ConcurrentHashMap"));
767885 alias("enum-set", JVM.loadClassForName("java.util.EnumSet"));
768886 alias("enum-map", JVM.loadClassForName("java.util.EnumMap"));
773891 if (JVM.is17()) {
774892 aliasType("path", JVM.loadClassForName("java.nio.file.Path"));
775893 }
776
894
895 if (JVM.is18()) {
896 alias("fixed-clock", JVM.loadClassForName("java.time.Clock$FixedClock"));
897 alias("offset-clock", JVM.loadClassForName("java.time.Clock$OffsetClock"));
898 alias("system-clock", JVM.loadClassForName("java.time.Clock$SystemClock"));
899 alias("tick-clock", JVM.loadClassForName("java.time.Clock$TickClock"));
900 alias("day-of-week", JVM.loadClassForName("java.time.DayOfWeek"));
901 alias("duration", JVM.loadClassForName("java.time.Duration"));
902 alias("instant", JVM.loadClassForName("java.time.Instant"));
903 alias("local-date", JVM.loadClassForName("java.time.LocalDate"));
904 alias("local-date-time", JVM.loadClassForName("java.time.LocalDateTime"));
905 alias("local-time", JVM.loadClassForName("java.time.LocalTime"));
906 alias("month", JVM.loadClassForName("java.time.Month"));
907 alias("month-day", JVM.loadClassForName("java.time.MonthDay"));
908 alias("offset-date-time", JVM.loadClassForName("java.time.OffsetDateTime"));
909 alias("offset-time", JVM.loadClassForName("java.time.OffsetTime"));
910 alias("period", JVM.loadClassForName("java.time.Period"));
911 alias("year", JVM.loadClassForName("java.time.Year"));
912 alias("year-month", JVM.loadClassForName("java.time.YearMonth"));
913 alias("zoned-date-time", JVM.loadClassForName("java.time.ZonedDateTime"));
914 aliasType("zone-id", JVM.loadClassForName("java.time.ZoneId"));
915 aliasType("chronology", JVM.loadClassForName("java.time.chrono.Chronology"));
916 alias("hijrah-date", JVM.loadClassForName("java.time.chrono.HijrahDate"));
917 alias("hijrah-era", JVM.loadClassForName("java.time.chrono.HijrahEra"));
918 alias("japanese-date", JVM.loadClassForName("java.time.chrono.JapaneseDate"));
919 alias("japanese-era", JVM.loadClassForName("java.time.chrono.JapaneseEra"));
920 alias("minguo-date", JVM.loadClassForName("java.time.chrono.MinguoDate"));
921 alias("minguo-era", JVM.loadClassForName("java.time.chrono.MinguoEra"));
922 alias("thai-buddhist-date", JVM.loadClassForName("java.time.chrono.ThaiBuddhistDate"));
923 alias("thai-buddhist-era", JVM.loadClassForName("java.time.chrono.ThaiBuddhistEra"));
924 alias("chrono-field", JVM.loadClassForName("java.time.temporal.ChronoField"));
925 alias("chrono-unit", JVM.loadClassForName("java.time.temporal.ChronoUnit"));
926 alias("iso-field", JVM.loadClassForName("java.time.temporal.IsoFields$Field"));
927 alias("iso-unit", JVM.loadClassForName("java.time.temporal.IsoFields$Unit"));
928 alias("julian-field", JVM.loadClassForName("java.time.temporal.JulianFields$Field"));
929 alias("temporal-value-range", JVM.loadClassForName("java.time.temporal.ValueRange"));
930 alias("week-fields", JVM.loadClassForName("java.time.temporal.WeekFields"));
931 }
932
777933 if (JVM.loadClassForName("java.lang.invoke.SerializedLambda") != null) {
778934 aliasDynamically("serialized-lambda", "java.lang.invoke.SerializedLambda");
779935 }
804960 registerConverter(
805961 new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW);
806962 registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW);
963 registerConverter(new InternalBlackList(), PRIORITY_LOW);
807964
808965 registerConverter(new NullConverter(), PRIORITY_VERY_HIGH);
809966 registerConverter(new IntConverter(), PRIORITY_NORMAL);
841998 registerConverter(new SqlTimeConverter(), PRIORITY_NORMAL);
842999 registerConverter(new SqlDateConverter(), PRIORITY_NORMAL);
8431000 }
844 registerConverter(
845 new DynamicProxyConverter(mapper, classLoaderReference), PRIORITY_NORMAL);
1001 registerConverter(new DynamicProxyConverter(mapper, classLoaderReference), PRIORITY_NORMAL);
8461002 registerConverter(new JavaClassConverter(classLoaderReference), PRIORITY_NORMAL);
8471003 registerConverter(new JavaMethodConverter(classLoaderReference), PRIORITY_NORMAL);
8481004 registerConverter(new JavaFieldConverter(classLoaderReference), PRIORITY_NORMAL);
1005
8491006 if (JVM.isAWTAvailable()) {
8501007 registerConverter(new FontConverter(mapper), PRIORITY_NORMAL);
8511008 registerConverter(new ColorConverter(), PRIORITY_NORMAL);
9131070 PRIORITY_NORMAL, null, null);
9141071 }
9151072 if (JVM.is18()) {
1073 registerConverterDynamically("com.thoughtworks.xstream.converters.time.ChronologyConverter",
1074 PRIORITY_NORMAL, null, null);
1075 registerConverterDynamically("com.thoughtworks.xstream.converters.time.DurationConverter", PRIORITY_NORMAL,
1076 null, null);
1077 registerConverterDynamically("com.thoughtworks.xstream.converters.time.HijrahDateConverter",
1078 PRIORITY_NORMAL, null, null);
1079 registerConverterDynamically("com.thoughtworks.xstream.converters.time.JapaneseDateConverter",
1080 PRIORITY_NORMAL, null, null);
1081 registerConverterDynamically("com.thoughtworks.xstream.converters.time.JapaneseEraConverter",
1082 PRIORITY_NORMAL, null, null);
1083 registerConverterDynamically("com.thoughtworks.xstream.converters.time.InstantConverter", PRIORITY_NORMAL,
1084 null, null);
1085 registerConverterDynamically("com.thoughtworks.xstream.converters.time.LocalDateConverter", PRIORITY_NORMAL,
1086 null, null);
1087 registerConverterDynamically("com.thoughtworks.xstream.converters.time.LocalDateTimeConverter",
1088 PRIORITY_NORMAL, null, null);
1089 registerConverterDynamically("com.thoughtworks.xstream.converters.time.LocalTimeConverter", PRIORITY_NORMAL,
1090 null, null);
1091 registerConverterDynamically("com.thoughtworks.xstream.converters.time.MinguoDateConverter",
1092 PRIORITY_NORMAL, null, null);
1093 registerConverterDynamically("com.thoughtworks.xstream.converters.time.MonthDayConverter", PRIORITY_NORMAL,
1094 null, null);
1095 registerConverterDynamically("com.thoughtworks.xstream.converters.time.OffsetDateTimeConverter",
1096 PRIORITY_NORMAL, null, null);
1097 registerConverterDynamically("com.thoughtworks.xstream.converters.time.OffsetTimeConverter",
1098 PRIORITY_NORMAL, null, null);
1099 registerConverterDynamically("com.thoughtworks.xstream.converters.time.PeriodConverter", PRIORITY_NORMAL,
1100 null, null);
1101 registerConverterDynamically("com.thoughtworks.xstream.converters.time.SystemClockConverter",
1102 PRIORITY_NORMAL, new Class[]{Mapper.class}, new Object[]{mapper});
1103 registerConverterDynamically("com.thoughtworks.xstream.converters.time.ThaiBuddhistDateConverter",
1104 PRIORITY_NORMAL, null, null);
1105 registerConverterDynamically("com.thoughtworks.xstream.converters.time.ValueRangeConverter",
1106 PRIORITY_NORMAL, new Class[]{Mapper.class}, new Object[]{mapper});
1107 registerConverterDynamically("com.thoughtworks.xstream.converters.time.WeekFieldsConverter",
1108 PRIORITY_NORMAL, new Class[]{Mapper.class}, new Object[]{mapper});
1109 registerConverterDynamically("com.thoughtworks.xstream.converters.time.YearConverter", PRIORITY_NORMAL,
1110 null, null);
1111 registerConverterDynamically("com.thoughtworks.xstream.converters.time.YearMonthConverter", PRIORITY_NORMAL,
1112 null, null);
1113 registerConverterDynamically("com.thoughtworks.xstream.converters.time.ZonedDateTimeConverter",
1114 PRIORITY_NORMAL, null, null);
1115 registerConverterDynamically("com.thoughtworks.xstream.converters.time.ZoneIdConverter", PRIORITY_NORMAL,
1116 null, null);
9161117 registerConverterDynamically("com.thoughtworks.xstream.converters.reflection.LambdaConverter",
9171118 PRIORITY_NORMAL, new Class[]{Mapper.class, ReflectionProvider.class, ClassLoaderReference.class},
9181119 new Object[]{mapper, reflectionProvider, classLoaderReference});
9741175 addImmutableType(File.class, false);
9751176 addImmutableType(Class.class, false);
9761177
1178 if (JVM.is17()) {
1179 Class type = JVM.loadClassForName("java.nio.file.Paths");
1180 if (type != null) {
1181 Method methodGet;
1182 try {
1183 methodGet = type.getDeclaredMethod("get", new Class[] {String.class, String[].class});
1184 if (methodGet != null) {
1185 Object path = methodGet.invoke(null, new Object[]{".", new String[0]});
1186 if (path != null) {
1187 addImmutableType(path.getClass(), false);
1188 }
1189 }
1190 } catch (NoSuchMethodException e) {
1191 } catch (SecurityException e) {
1192 } catch (IllegalAccessException e) {
1193 } catch (InvocationTargetException e) {
1194 }
1195 }
1196 }
1197
9771198 if (JVM.isAWTAvailable()) {
9781199 addImmutableTypeDynamically("java.awt.font.TextAttribute", false);
9791200 }
9921213 addImmutableType(Collections.EMPTY_LIST.getClass(), true);
9931214 addImmutableType(Collections.EMPTY_SET.getClass(), true);
9941215 addImmutableType(Collections.EMPTY_MAP.getClass(), true);
1216
1217 if (JVM.is18()) {
1218 addImmutableTypeDynamically("java.time.Duration", false);
1219 addImmutableTypeDynamically("java.time.Instant", false);
1220 addImmutableTypeDynamically("java.time.LocalDate", false);
1221 addImmutableTypeDynamically("java.time.LocalDateTime", false);
1222 addImmutableTypeDynamically("java.time.LocalTime", false);
1223 addImmutableTypeDynamically("java.time.MonthDay", false);
1224 addImmutableTypeDynamically("java.time.OffsetDateTime", false);
1225 addImmutableTypeDynamically("java.time.OffsetTime", false);
1226 addImmutableTypeDynamically("java.time.Period", false);
1227 addImmutableTypeDynamically("java.time.Year", false);
1228 addImmutableTypeDynamically("java.time.YearMonth", false);
1229 addImmutableTypeDynamically("java.time.ZonedDateTime", false);
1230 addImmutableTypeDynamically("java.time.ZoneId", false);
1231 addImmutableTypeDynamically("java.time.ZoneOffset", false);
1232 addImmutableTypeDynamically("java.time.ZoneRegion", false);
1233 addImmutableTypeDynamically("java.time.chrono.HijrahChronology", false);
1234 addImmutableTypeDynamically("java.time.chrono.HijrahDate", false);
1235 addImmutableTypeDynamically("java.time.chrono.IsoChronology", false);
1236 addImmutableTypeDynamically("java.time.chrono.JapaneseChronology", false);
1237 addImmutableTypeDynamically("java.time.chrono.JapaneseDate", false);
1238 addImmutableTypeDynamically("java.time.chrono.JapaneseEra", false);
1239 addImmutableTypeDynamically("java.time.chrono.MinguoChronology", false);
1240 addImmutableTypeDynamically("java.time.chrono.MinguoDate", false);
1241 addImmutableTypeDynamically("java.time.chrono.ThaiBuddhistChronology", false);
1242 addImmutableTypeDynamically("java.time.chrono.ThaiBuddhistDate", false);
1243 addImmutableTypeDynamically("java.time.temporal.IsoFields$Field", false);
1244 addImmutableTypeDynamically("java.time.temporal.IsoFields$Unit", false);
1245 addImmutableTypeDynamically("java.time.temporal.JulianFields$Field", false);
1246 }
9951247 }
9961248
9971249 private void addImmutableTypeDynamically(String className, boolean isReferenceable) {
12261478 */
12271479 public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) {
12281480 try {
1481 if (insecureWarning) {
1482 insecureWarning = false;
1483 System.err.println("Security framework of XStream not initialized, XStream is probably vulnerable.");
1484 }
12291485 return marshallingStrategy.unmarshal(
12301486 root, reader, dataHolder, converterLookup, mapper);
12311487
17131969 }
17141970
17151971 /**
1716 * Create a DataHolder that can be used to pass data to the converters. The DataHolder is
1717 * provided with a call to {@link #marshal(Object, HierarchicalStreamWriter, DataHolder)} or
1718 * {@link #unmarshal(HierarchicalStreamReader, Object, DataHolder)}.
1972 * Create a DataHolder that can be used to pass data to the converters. The DataHolder is provided with a call to
1973 * {@link #marshal(Object, HierarchicalStreamWriter, DataHolder)},
1974 * {@link #unmarshal(HierarchicalStreamReader, Object, DataHolder)},
1975 * {@link #createObjectInputStream(HierarchicalStreamReader, DataHolder)} or
1976 * {@link #createObjectOutputStream(HierarchicalStreamWriter, String, DataHolder)}.
17191977 *
17201978 * @return a new {@link DataHolder}
17211979 */
18332091 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
18342092 * @since 1.0.3
18352093 */
1836 public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer,
1837 String rootNodeName) throws IOException {
2094 public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer, final String rootNodeName)
2095 throws IOException {
2096 return createObjectOutputStream(writer, rootNodeName, null);
2097 }
2098
2099 /**
2100 * Creates an ObjectOutputStream that serializes a stream of objects to the writer using XStream.
2101 *
2102 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, String)
2103 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
2104 * @since 1.4.10
2105 */
2106 public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer, final String rootNodeName,
2107 final DataHolder dataHolder) throws IOException {
18382108 final StatefulWriter statefulWriter = new StatefulWriter(writer);
18392109 statefulWriter.startNode(rootNodeName, null);
18402110 return new CustomObjectOutputStream(new CustomObjectOutputStream.StreamCallback() {
1841 public void writeToStream(Object object) {
1842 marshal(object, statefulWriter);
2111 public void writeToStream(final Object object) {
2112 marshal(object, statefulWriter, dataHolder);
18432113 }
18442114
18452115 public void writeFieldsToStream(Map fields) throws NotActiveException {
18902160 }
18912161
18922162 /**
1893 * Creates an ObjectInputStream that deserializes a stream of objects from a reader using
1894 * XStream. <h3>Example</h3>
1895 *
2163 * Creates an ObjectInputStream that deserializes a stream of objects from a reader using XStream.
2164 * <p>
2165 * It is necessary to call ObjectInputStream.close() when done, otherwise the stream might keep system resources.
2166 * </p>
2167 * <h3>Example</h3>
2168 *
18962169 * <pre>
18972170 * ObjectInputStream in = xstream.createObjectOutputStream(aReader);
18982171 * int a = out.readInt();
19042177 * String)
19052178 * @since 1.0.3
19062179 */
1907 public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader)
1908 throws IOException {
2180 public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader) throws IOException {
2181 return createObjectInputStream(reader, null);
2182 }
2183
2184 /**
2185 * Creates an ObjectInputStream that deserializes a stream of objects from a reader using XStream.
2186 *
2187 * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, String)
2188 * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader)
2189 * @since 1.4.10
2190 */
2191 public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader, final DataHolder dataHolder)
2192 throws IOException {
19092193 return new CustomObjectInputStream(new CustomObjectInputStream.StreamCallback() {
19102194 public Object readFromStream() throws EOFException {
19112195 if (!reader.hasMoreChildren()) {
19122196 throw new EOFException();
19132197 }
19142198 reader.moveDown();
1915 Object result = unmarshal(reader);
2199 final Object result = unmarshal(reader, dataHolder);
19162200 reader.moveUp();
19172201 return result;
19182202 }
19752259 * declaring type and not necessarily the type that is converted.
19762260 *
19772261 * @since 1.1.3
1978 * @throws InitializationException if no {@link FieldAliasingMapper} is available
2262 * @throws InitializationException if no {@link ElementIgnoringMapper} is available
19792263 */
19802264 public void omitField(Class definedIn, String fieldName) {
1981 if (fieldAliasingMapper == null) {
2265 if (elementIgnoringMapper == null) {
19822266 throw new com.thoughtworks.xstream.InitializationException("No "
1983 + FieldAliasingMapper.class.getName()
2267 + ElementIgnoringMapper.class.getName()
19842268 + " available");
19852269 }
1986 fieldAliasingMapper.omitField(definedIn, fieldName);
2270 elementIgnoringMapper.omitField(definedIn, fieldName);
19872271 }
19882272
19892273 /**
20122296 * @since 1.4.5
20132297 */
20142298 public void ignoreUnknownElements(final Pattern pattern) {
2015 if (fieldAliasingMapper == null) {
2299 if (elementIgnoringMapper == null) {
20162300 throw new com.thoughtworks.xstream.InitializationException("No "
2017 + FieldAliasingMapper.class.getName()
2301 + ElementIgnoringMapper.class.getName()
20182302 + " available");
20192303 }
2020 fieldAliasingMapper.addFieldsToIgnore(pattern);
2304 elementIgnoringMapper.addElementsToIgnore(pattern);
20212305 }
20222306
20232307 /**
20742358 */
20752359 public void addPermission(TypePermission permission) {
20762360 if (securityMapper != null) {
2361 insecureWarning &= permission != NoTypePermission.NONE;
20772362 securityMapper.addPermission(permission);
20782363 }
20792364 }
22472532 super(message);
22482533 }
22492534 }
2535
2536 private class InternalBlackList implements Converter {
2537
2538 public boolean canConvert(final Class type) {
2539 return (type == void.class || type == Void.class)
2540 || (insecureWarning
2541 && type != null
2542 && (type.getName().equals("java.beans.EventHandler")
2543 || type.getName().endsWith("$LazyIterator")
2544 || type.getName().startsWith("javax.crypto.")));
2545 }
2546
2547 public void marshal(final Object source, final HierarchicalStreamWriter writer,
2548 final MarshallingContext context) {
2549 throw new ConversionException("Security alert. Marshalling rejected.");
2550 }
2551
2552 public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
2553 throw new ConversionException("Security alert. Unmarshalling rejected.");
2554 }
2555 }
22502556 }
00 /*
1 * Copyright (C) 2006, 2007, 2014, 2016 XStream Committers.
1 * Copyright (C) 2006, 2007, 2014, 2016, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
107107 public void toXML(final XStream xstream, final Object obj, final Writer out)
108108 throws IOException {
109109 final XStream outer = new XStream();
110 XStream.setupDefaultSecurity(outer);
110111 final ObjectOutputStream oos = outer.createObjectOutputStream(out);
111112 try {
112113 oos.writeObject(xstream);
267268 public Object fromXML(final HierarchicalStreamDriver driver, final Reader xml, final TypePermission[] permissions)
268269 throws IOException, ClassNotFoundException {
269270 final XStream outer = new XStream(driver);
271 XStream.setupDefaultSecurity(outer);
270272 for(int i = 0; i < permissions.length; ++i) {
271273 outer.addPermission(permissions[i]);
272274 }
00 /*
11 * Copyright (C) 2004, 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007 XStream Committers.
2 * Copyright (C) 2006, 2007, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1212
1313 import java.util.Calendar;
1414 import java.util.Date;
15 import java.util.GregorianCalendar;
16
17 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
1518
1619
1720 /**
2124 * @author Mauro Talevi
2225 * @author J&ouml;rg Schaible
2326 */
24 public class ISO8601DateConverter extends ISO8601GregorianCalendarConverter {
27 public class ISO8601DateConverter extends AbstractSingleValueConverter {
28 private final ISO8601GregorianCalendarConverter converter = new ISO8601GregorianCalendarConverter();
2529
2630 public boolean canConvert(Class type) {
27 return type.equals(Date.class);
31 return type.equals(Date.class) && converter.canConvert(GregorianCalendar.class);
2832 }
2933
3034 public Object fromString(String str) {
31 return ((Calendar)super.fromString(str)).getTime();
35 return ((Calendar)converter.fromString(str)).getTime();
3236 }
3337
3438 public String toString(Object obj) {
35 Calendar calendar = Calendar.getInstance();
39 final Calendar calendar = Calendar.getInstance();
3640 calendar.setTime((Date)obj);
37 return super.toString(calendar);
41 return converter.toString(calendar);
3842 }
3943 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2011, 2013, 2014, 2015, 2016 XStream Committers.
2 * Copyright (C) 2006, 2007, 2011, 2013, 2014, 2015, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1010 */
1111 package com.thoughtworks.xstream.converters.extended;
1212
13 import com.thoughtworks.xstream.converters.ConversionException;
13 import java.lang.reflect.InvocationTargetException;
14 import java.util.GregorianCalendar;
15
16 import com.thoughtworks.xstream.converters.SingleValueConverter;
1417 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
15
16 import org.joda.time.DateTime;
17 import org.joda.time.DateTimeZone;
18 import org.joda.time.format.DateTimeFormatter;
19 import org.joda.time.format.ISODateTimeFormat;
20
21 import java.util.Calendar;
22 import java.util.GregorianCalendar;
23 import java.util.TimeZone;
18 import com.thoughtworks.xstream.core.JVM;
2419
2520
2621 /**
27 * A GregorianCalendarConverter conforming to the ISO8601 standard. The converter will always
28 * serialize the calendar value in UTC and deserialize it to a value in the current default time
29 * zone.
22 * A GregorianCalendarConverter conforming to the ISO8601 standard. The converter will always serialize the calendar
23 * value in UTC and deserialize it to a value in the current default time zone.
3024 *
3125 * @author Mauro Talevi
3226 * @author J&ouml;rg Schaible
3428 * @since 1.1.3
3529 */
3630 public class ISO8601GregorianCalendarConverter extends AbstractSingleValueConverter {
37 private static final DateTimeFormatter[] formattersUTC = new DateTimeFormatter[]{
38 ISODateTimeFormat.dateTime(),
39 ISODateTimeFormat.dateTimeNoMillis(),
40 ISODateTimeFormat.basicDateTime(),
41 ISODateTimeFormat.basicOrdinalDateTime(),
42 ISODateTimeFormat.basicOrdinalDateTimeNoMillis(),
43 ISODateTimeFormat.basicTime(),
44 ISODateTimeFormat.basicTimeNoMillis(),
45 ISODateTimeFormat.basicTTime(),
46 ISODateTimeFormat.basicTTimeNoMillis(),
47 ISODateTimeFormat.basicWeekDateTime(),
48 ISODateTimeFormat.basicWeekDateTimeNoMillis(),
49 ISODateTimeFormat.ordinalDateTime(),
50 ISODateTimeFormat.ordinalDateTimeNoMillis(),
51 ISODateTimeFormat.time(),
52 ISODateTimeFormat.timeNoMillis(),
53 ISODateTimeFormat.tTime(),
54 ISODateTimeFormat.tTimeNoMillis(),
55 ISODateTimeFormat.weekDateTime(),
56 ISODateTimeFormat.weekDateTimeNoMillis()
57 };
58 private static final DateTimeFormatter[] formattersNoUTC = new DateTimeFormatter[]{
59 ISODateTimeFormat.basicDate(),
60 ISODateTimeFormat.basicOrdinalDate(),
61 ISODateTimeFormat.basicWeekDate(),
62 ISODateTimeFormat.date(),
63 ISODateTimeFormat.dateHour(),
64 ISODateTimeFormat.dateHourMinute(),
65 ISODateTimeFormat.dateHourMinuteSecond(),
66 ISODateTimeFormat.dateHourMinuteSecondFraction(),
67 ISODateTimeFormat.dateHourMinuteSecondMillis(),
68 ISODateTimeFormat.hour(),
69 ISODateTimeFormat.hourMinute(),
70 ISODateTimeFormat.hourMinuteSecond(),
71 ISODateTimeFormat.hourMinuteSecondFraction(),
72 ISODateTimeFormat.hourMinuteSecondMillis(),
73 ISODateTimeFormat.ordinalDate(),
74 ISODateTimeFormat.weekDate(),
75 ISODateTimeFormat.year(),
76 ISODateTimeFormat.yearMonth(),
77 ISODateTimeFormat.yearMonthDay(),
78 ISODateTimeFormat.weekyear(),
79 ISODateTimeFormat.weekyearWeek(),
80 ISODateTimeFormat.weekyearWeekDay()
81 };
82
83 public boolean canConvert(Class type) {
84 return type.equals(GregorianCalendar.class);
31 private final static Class[] EMPTY_CLASS_ARRAY = new Class[0];
32 private final static Object[] EMPTY_OBJECT_ARRAY = new Object[0];
33 private final SingleValueConverter converter;
34
35 public ISO8601GregorianCalendarConverter() {
36 SingleValueConverter svConverter = null;
37 final Class type = JVM.loadClassForName(JVM.is18()
38 ? "com.thoughtworks.xstream.core.util.ISO8601JavaTimeConverter"
39 : "com.thoughtworks.xstream.core.util.ISO8601JodaTimeConverter");
40 try {
41 svConverter = (SingleValueConverter)type.getDeclaredConstructor(EMPTY_CLASS_ARRAY).newInstance(
42 EMPTY_OBJECT_ARRAY);
43 } catch (final InstantiationException e) {
44 // ignore
45 } catch (final IllegalAccessException e) {
46 // ignore
47 } catch (final InvocationTargetException e) {
48 // ignore
49 } catch (final NoSuchMethodException e) {
50 // ignore
51 }
52 converter = svConverter;
8553 }
8654
87 public Object fromString(String str) {
88 for (int i = 0; i < formattersUTC.length; i++ ) {
89 DateTimeFormatter formatter = formattersUTC[i];
90 try {
91 DateTime dt = formatter.parseDateTime(str);
92 Calendar calendar = dt.toGregorianCalendar();
93 calendar.setTimeZone(TimeZone.getDefault());
94 return calendar;
95 } catch (IllegalArgumentException e) {
96 // try with next formatter
97 }
98 }
99 final DateTimeZone dateTimeZone = DateTimeZone.forTimeZone(TimeZone.getDefault());
100 for (int i = 0; i < formattersNoUTC.length; i++ ) {
101 try {
102 final DateTimeFormatter formatter = formattersNoUTC[i].withZone(dateTimeZone);
103 final DateTime dt = formatter.parseDateTime(str);
104 final Calendar calendar = dt.toGregorianCalendar();
105 calendar.setTimeZone(TimeZone.getDefault());
106 return calendar;
107 } catch (IllegalArgumentException e) {
108 // try with next formatter
109 }
110 }
111 ConversionException exception = new ConversionException("Cannot parse date");
112 exception.add("date", str);
113 throw exception;
55 public boolean canConvert(final Class type) {
56 return converter != null && type.equals(GregorianCalendar.class);
11457 }
11558
116 public String toString(Object obj) {
117 DateTime dt = new DateTime(obj);
118 return dt.toString(formattersUTC[0]);
59 public Object fromString(final String str) {
60 return converter.fromString(str);
61 }
62
63 public String toString(final Object obj) {
64 return converter.toString(obj);
11965 }
12066 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007 XStream Committers.
2 * Copyright (C) 2006, 2007, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
2626 private final static String PADDING = "000000000";
2727
2828 public boolean canConvert(Class type) {
29 return type.equals(Timestamp.class);
29 return type.equals(Timestamp.class) && super.canConvert(Date.class);
3030 }
3131
3232 public Object fromString(String str) {
99 */
1010 package com.thoughtworks.xstream.converters.extended;
1111
12 import java.io.File;
1213 import java.net.URI;
1314 import java.net.URISyntaxException;
1415 import java.nio.file.FileSystems;
1516 import java.nio.file.Path;
1617 import java.nio.file.Paths;
1718
18 import com.thoughtworks.xstream.converters.ConversionException;
1919 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
2020
2121
2828 public class PathConverter extends AbstractSingleValueConverter {
2929
3030 @Override
31 public boolean canConvert(final Class type) {
31 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
3232 return Path.class.isAssignableFrom(type);
3333 }
3434
3535 @Override
36 public Object fromString(final String str) {
36 public Path fromString(final String str) {
3737 try {
3838 final URI uri = new URI(str);
3939 if (uri.getScheme() == null) {
4242 return Paths.get(uri);
4343 }
4444 } catch (final URISyntaxException e) {
45 throw new ConversionException(e);
45 return Paths.get(str);
4646 }
4747 }
4848
5050 public String toString(final Object obj) {
5151 final Path path = (Path)obj;
5252 if (path.getFileSystem() == FileSystems.getDefault()) {
53 return path.toString();
53 final String localPath = path.toString();
54 if (File.separatorChar != '/') {
55 return localPath.replace(File.separatorChar, '/');
56 } else {
57 return localPath;
58 }
5459 } else {
5560 return path.toUri().toString();
5661 }
00 /*
11 * Copyright (C) 2003, 2004 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2012, 2014 XStream Committers.
2 * Copyright (C) 2006, 2007, 2012, 2014, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
66 * style license a copy of which has been included with this distribution in
77 * the LICENSE.txt file.
8 *
8 *
99 * Created on 01. October 2004 by Joe Walnes
1010 */
1111 package com.thoughtworks.xstream.converters.extended;
2020
2121
2222 /**
23 * Converts a java.sql.Timestamp to text.
24 *
23 * Converts a {@link Timestamp} to a string.
24 *
2525 * @author Joe Walnes
2626 * @author J&ouml;rg Schaible
2727 */
2828 public class SqlTimestampConverter extends AbstractSingleValueConverter {
2929
30 private final ThreadSafeSimpleDateFormat format = new ThreadSafeSimpleDateFormat(
31 "yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("UTC"), 0, 5, false);
30 private final ThreadSafeSimpleDateFormat format;
31
32 /**
33 * Constructs a SqlTimestampConverter using UTC format.
34 */
35 public SqlTimestampConverter() {
36 this(TimeZone.getTimeZone("UTC"));
37 }
38
39 /**
40 * Constructs a SqlTimestampConverter.
41 * <p>
42 * XStream uses by default UTC as time zone. However, if the resulting XML is used as feed for a data base (like MS
43 * SQL) the server might expect the timestamp to be in local time and does the conversion to UTC on its own. In such
44 * a case you can register an own instance of the SqlTimestamp converter using e.g. {@link TimeZone#getDefault()}.
45 * </p>
46 *
47 * @param timeZone the time zone used for the format
48 * @since 1.4.10
49 */
50 public SqlTimestampConverter(final TimeZone timeZone) {
51 format = new ThreadSafeSimpleDateFormat("yyyy-MM-dd HH:mm:ss", timeZone, 0, 5, false);
52 }
3253
3354 public boolean canConvert(Class type) {
3455 return type.equals(Timestamp.class);
3556 }
3657
37 public String toString(Object obj) {
38 Timestamp timestamp = (Timestamp)obj;
39 StringBuffer buffer = new StringBuffer(format.format(timestamp)).append('.');
40 if (timestamp.getNanos() == 0) {
41 buffer.append('0');
42 } else {
43 String nanos = String.valueOf(timestamp.getNanos() + 1000000000);
58 public String toString(final Object obj) {
59 final Timestamp timestamp = (Timestamp)obj;
60 final StringBuffer buffer = new StringBuffer(format.format(timestamp));
61 if (timestamp.getNanos() != 0) {
62 buffer.append('.');
63 final String nanos = String.valueOf(timestamp.getNanos() + 1000000000);
4464 int last = 10;
4565 while (last > 2 && nanos.charAt(last-1) == '0')
4666 --last;
4969 return buffer.toString();
5070 }
5171
52 public Object fromString(String str) {
53 int idx = str.lastIndexOf('.');
54 if (idx < 0 || str.length() - idx < 2 || str.length() - idx > 10) {
55 throw new ConversionException(
56 "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]");
72 public Object fromString(final String str) {
73 final int idx = str.lastIndexOf('.');
74 if (idx > 0 && (str.length() - idx < 2 || str.length() - idx > 10)) {
75 throw new ConversionException("Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]");
5776 }
5877 try {
59 Timestamp timestamp = new Timestamp(format.parse(str.substring(0, idx)).getTime());
60 StringBuffer buffer = new StringBuffer(str.substring(idx + 1));
61 while(buffer.length() != 9) {
62 buffer.append('0');
78 final Timestamp timestamp = new Timestamp(format.parse(idx < 0 ? str : str.substring(0, idx)).getTime());
79 if (idx > 0) {
80 final StringBuffer buffer = new StringBuffer(str.substring(idx + 1));
81 while (buffer.length() != 9) {
82 buffer.append('0');
83 }
84 timestamp.setNanos(Integer.parseInt(buffer.toString()));
6385 }
64 timestamp.setNanos(Integer.parseInt(buffer.toString()));
6586 return timestamp;
6687 } catch (NumberFormatException e) {
6788 throw new ConversionException(
127127 }
128128
129129 public boolean propertyDefinedInClass(String name, Class type) {
130 return getProperty(name, type) != null;
130 return propertyDictionary.propertyDescriptorOrNull(type, name) != null;
131131 }
132132
133133 /**
135135 */
136136 public boolean canInstantiate(Class type) {
137137 try {
138 return newInstance(type) != null;
139 } catch (ObjectAccessException e) {
138 return type != null && newInstance(type) != null;
139 } catch (final ErrorWritingException e) {
140140 return false;
141141 }
142142 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
143143 Object value = context.convertAnother(result, type);
144144 beanProvider.writeProperty(result, propertyName, value);
145145 seenProperties.add(new FastField(resultType, propertyName));
146 } else {
146 } else if (!mapper.isIgnoredElement(propertyName)) {
147147 throw new MissingFieldException(resultType.getName(), propertyName);
148148 }
149149 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2016 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
7070 */
7171 public BeanProperty property(Class cls, String name) {
7272 BeanProperty beanProperty = null;
73 PropertyDescriptor descriptor = (PropertyDescriptor)buildMap(cls).get(name);
73 PropertyDescriptor descriptor = propertyDescriptorOrNull(cls, name);
7474 if (descriptor == null) {
7575 throw new MissingFieldException(cls.getName(), name);
7676 }
9090 *
9191 * @param type
9292 * @param name
93 * @throws MissingFieldException if property does not exist
9394 */
9495 public PropertyDescriptor propertyDescriptor(Class type, String name) {
95 PropertyDescriptor descriptor = (PropertyDescriptor)buildMap(type).get(name);
96 PropertyDescriptor descriptor = propertyDescriptorOrNull(type, name);
9697 if (descriptor == null) {
9798 throw new MissingFieldException(type.getName(), name);
9899 }
99100 return descriptor;
101 }
102
103 /**
104 * Locates a property descriptor.
105 *
106 * @param type
107 * @param name
108 * @return {@code null} if property does not exist
109 * @since 1.4.10
110 */
111 public PropertyDescriptor propertyDescriptorOrNull(Class type, String name) {
112 return (PropertyDescriptor)buildMap(type).get(name);
100113 }
101114
102115 private Map buildMap(Class type) {
00 /*
11 * Copyright (C) 2004, 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2013, 2014 XStream Committers.
2 * Copyright (C) 2006, 2007, 2013, 2014, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1010 */
1111 package com.thoughtworks.xstream.converters.reflection;
1212
13 import com.thoughtworks.xstream.core.JVM;
1413 import com.thoughtworks.xstream.mapper.Mapper;
1514
1615 public class ReflectionConverter extends AbstractReflectionConverter {
1716
18 // Might be missing in Android
19 private final static Class eventHandlerType = JVM.loadClassForName("java.beans.EventHandler");
2017 private Class type;
2118
2219 public ReflectionConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
3734 }
3835
3936 public boolean canConvert(Class type) {
40 return ((this.type != null && this.type == type) || (this.type == null && type != null && type != eventHandlerType))
41 && canAccess(type);
37 return (this.type != null && this.type == type || this.type == null && type != null) && canAccess(type);
4238 }
4339 }
00 /*
11 * Copyright (C) 2004, 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
7777 throw ex;
7878 }
7979 ErrorWritingException ex = null;
80 try {
81 return unsafe.allocateInstance(type);
82 } catch (SecurityException e) {
83 ex = new ObjectAccessException("Cannot construct type", e);
84 } catch (InstantiationException e) {
85 ex = new ConversionException("Cannot construct type", e);
86 } catch (IllegalArgumentException e) {
87 ex = new ObjectAccessException("Cannot construct type", e);
80 if (type == void.class || type == Void.class) {
81 ex = new ConversionException("Type void cannot have an instance");
82 } else {
83 try {
84 return unsafe.allocateInstance(type);
85 } catch (final SecurityException e) {
86 ex = new ObjectAccessException("Cannot construct type", e);
87 } catch (final InstantiationException e) {
88 ex = new ConversionException("Cannot construct type", e);
89 } catch (final IllegalArgumentException e) {
90 ex = new ObjectAccessException("Cannot construct type", e);
91 }
8892 }
8993 ex.add("construction-type", type.getName());
9094 throw ex;
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 22. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.DateTimeException;
13 import java.time.chrono.ChronoLocalDate;
14 import java.time.chrono.Chronology;
15 import java.time.chrono.Era;
16 import java.util.Set;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
19
20 import com.thoughtworks.xstream.converters.ConversionException;
21 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
22
23
24 /**
25 * Abstract base class for converters handling derived classes of {@link java.time.chrono.ChronoLocalDate} instances.
26 *
27 * @author J&ouml;rg Schaible
28 * @since 1.4.10
29 */
30 abstract class AbstractChronoLocalDateConverter<E extends Era> extends AbstractSingleValueConverter {
31 protected abstract ChronoLocalDate chronoLocalDateOf(final E era, final int prolepticYear, final int month,
32 final int dayOfMonth);
33
34 protected abstract E eraOf(final String id);
35
36 private final static Pattern CHRONO_DATE_PATTERN = Pattern.compile("^ (\\w+) (\\d+)-(\\d+)-(\\d+)$");
37
38 protected ChronoLocalDate parseChronoLocalDate(final String str, final String dateTypeName,
39 final Set<Chronology> chronologies) {
40 if (str == null) {
41 return null;
42 }
43
44 ConversionException exception = null;
45 for (final Chronology chronology : chronologies) {
46 final String id = chronology.getId();
47 if (str.startsWith(id + ' ')) {
48 final Matcher matcher = CHRONO_DATE_PATTERN.matcher(str.subSequence(id.length(), str.length()));
49 if (matcher.matches()) {
50 E era = null;
51 try {
52 era = eraOf(matcher.group(1));
53 } catch (final IllegalArgumentException e) {
54 exception = new ConversionException("Cannot parse value as " + dateTypeName + " date", e);
55 break;
56 }
57 if (era != null) {
58 try {
59 return chronoLocalDateOf(era, Integer.parseInt(matcher.group(2)), Integer.parseInt(matcher
60 .group(3)), Integer.parseInt(matcher.group(4)));
61 } catch (final DateTimeException e) {
62 exception = new ConversionException("Cannot parse value as " + dateTypeName + " date", e);
63 break;
64 }
65 }
66 }
67 }
68 }
69 if (exception == null) {
70 exception = new ConversionException("Cannot parse value as " + dateTypeName + " date");
71 }
72 exception.add("value", str);
73 throw exception;
74 }
75
76 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 19. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.DateTimeException;
13 import java.time.chrono.Chronology;
14
15 import com.thoughtworks.xstream.converters.ConversionException;
16 import com.thoughtworks.xstream.converters.SingleValueConverter;
17
18
19 /**
20 * Converts a {@link Chronology} instance to a string using its id.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class ChronologyConverter implements SingleValueConverter {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return Chronology.class.isAssignableFrom(type);
30 }
31
32 @Override
33 public Chronology fromString(final String str) {
34 if (str == null) {
35 return null;
36 }
37 try {
38 return Chronology.of(str);
39 } catch (final DateTimeException e) {
40 final ConversionException exception = new ConversionException("Cannot parse value as chronology", e);
41 exception.add("value", str);
42 throw exception;
43 }
44 }
45
46 @Override
47 public String toString(final Object obj) {
48 return obj == null ? null : ((Chronology)obj).getId();
49 }
50 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.Duration;
13 import java.time.format.DateTimeParseException;
14
15 import com.thoughtworks.xstream.converters.ConversionException;
16 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
17
18
19 /**
20 * Converts a {@link Duration} instance to string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class DurationConverter extends AbstractSingleValueConverter {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return Duration.class == type;
30 }
31
32 @Override
33 public Duration fromString(final String str) {
34 try {
35 return Duration.parse(str);
36 } catch (final DateTimeParseException ex) {
37 final ConversionException exception = new ConversionException("Cannot parse value as duration", ex);
38 exception.add("value", str);
39 throw exception;
40 }
41 }
42 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 21. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.chrono.ChronoLocalDate;
13 import java.time.chrono.Chronology;
14 import java.time.chrono.HijrahChronology;
15 import java.time.chrono.HijrahDate;
16 import java.time.chrono.HijrahEra;
17 import java.util.HashSet;
18 import java.util.Set;
19
20
21 /**
22 * Converts a {@link java.time.chrono.HijrahDate} to a string.
23 *
24 * @author J&ouml;rg Schaible
25 * @since 1.4.10
26 */
27 public class HijrahDateConverter extends AbstractChronoLocalDateConverter<HijrahEra> {
28
29 private final Set<Chronology> hijrahChronologies;
30
31 /**
32 * Constructs a HijrahDateConverter instance.
33 */
34 public HijrahDateConverter() {
35 hijrahChronologies = new HashSet<>();
36 final Set<Chronology> chronologies = Chronology.getAvailableChronologies();
37 for (final Chronology chronology : chronologies) {
38 if (chronology instanceof HijrahChronology) {
39 hijrahChronologies.add(chronology);
40 }
41 }
42 }
43
44 @Override
45 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
46 return HijrahDate.class == type;
47 }
48
49 @Override
50 public Object fromString(final String str) {
51 return parseChronoLocalDate(str, "Hijrah", hijrahChronologies);
52 }
53
54 @Override
55 protected ChronoLocalDate chronoLocalDateOf(final HijrahEra era, final int prolepticYear, final int month,
56 final int dayOfMonth) {
57 return era != null ? HijrahDate.of(prolepticYear, month, dayOfMonth) : null;
58 }
59
60 @Override
61 protected HijrahEra eraOf(final String id) {
62 return HijrahEra.valueOf(id);
63 }
64
65 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 15. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.Instant;
13 import java.time.format.DateTimeParseException;
14
15 import com.thoughtworks.xstream.converters.ConversionException;
16 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
17
18
19 /**
20 * Converts a {@link Instant} instance to string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class InstantConverter extends AbstractSingleValueConverter {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return Instant.class == type;
30 }
31
32 @Override
33 public Instant fromString(final String str) {
34 try {
35 return Instant.parse(str);
36 } catch (final DateTimeParseException ex) {
37 final ConversionException exception = new ConversionException("Cannot parse value as instant", ex);
38 exception.add("value", str);
39 throw exception;
40 }
41 }
42 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 22. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.chrono.ChronoLocalDate;
13 import java.time.chrono.JapaneseChronology;
14 import java.time.chrono.JapaneseDate;
15 import java.time.chrono.JapaneseEra;
16 import java.util.Collections;
17
18
19 /**
20 * Converts a {@link java.time.chrono.JapaneseDate} to a string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class JapaneseDateConverter extends AbstractChronoLocalDateConverter<JapaneseEra> {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return JapaneseDate.class == type;
30 }
31
32 @Override
33 public Object fromString(final String str) {
34 return parseChronoLocalDate(str, "Japanese", Collections.singleton(JapaneseChronology.INSTANCE));
35 }
36
37 @Override
38 protected ChronoLocalDate chronoLocalDateOf(final JapaneseEra era, final int prolepticYear, final int month,
39 final int dayOfMonth) {
40 return JapaneseDate.of(era, prolepticYear, month, dayOfMonth);
41 }
42
43 @Override
44 protected JapaneseEra eraOf(final String id) {
45 return JapaneseEra.valueOf(id);
46 }
47
48 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 22. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.chrono.JapaneseEra;
13
14 import com.thoughtworks.xstream.converters.ConversionException;
15 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
16
17
18 /**
19 * Converts a {@link JapaneseEra} instance to a string using its id.
20 *
21 * @author J&ouml;rg Schaible
22 * @since 1.4.10
23 */
24 public class JapaneseEraConverter extends AbstractSingleValueConverter {
25
26 @Override
27 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
28 return JapaneseEra.class.isAssignableFrom(type);
29 }
30
31 @Override
32 public JapaneseEra fromString(final String str) {
33 if (str == null) {
34 return null;
35 }
36 try {
37 return JapaneseEra.valueOf(str);
38 } catch (final IllegalArgumentException e) {
39 final ConversionException exception = new ConversionException("Cannot parse value as Japanese era", e);
40 exception.add("value", str);
41 throw exception;
42 }
43 }
44 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. January 2017 by Matej Cimbora
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.LocalDate;
13 import java.time.format.DateTimeParseException;
14
15 import com.thoughtworks.xstream.converters.ConversionException;
16 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
17
18
19 /**
20 * Converts a {@link java.time.LocalDate} to a string.
21 *
22 * @author Matej Cimbora
23 * @since 1.4.10
24 */
25 public class LocalDateConverter extends AbstractSingleValueConverter {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return LocalDate.class == type;
30 }
31
32 @Override
33 public Object fromString(final String str) {
34 try {
35 return LocalDate.parse(str);
36 } catch (final DateTimeParseException e) {
37 final ConversionException exception = new ConversionException("Cannot parse value as local date", e);
38 exception.add("value", str);
39 throw exception;
40 }
41 }
42
43 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. January 2017 by Matej Cimbora
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.LocalDateTime;
13 import java.time.format.DateTimeFormatter;
14 import java.time.format.DateTimeFormatterBuilder;
15 import java.time.format.DateTimeParseException;
16 import java.time.temporal.ChronoField;
17
18 import com.thoughtworks.xstream.converters.ConversionException;
19 import com.thoughtworks.xstream.converters.SingleValueConverter;
20
21
22 /**
23 * Converts a {@link LocalDateTime} to a string.
24 *
25 * @author Matej Cimbora
26 * @since 1.4.10
27 */
28 public class LocalDateTimeConverter implements SingleValueConverter {
29
30 private static final DateTimeFormatter FORMATTER;
31
32 static {
33 FORMATTER = new DateTimeFormatterBuilder()
34 .appendPattern("uuuu-MM-dd'T'HH:mm:ss")
35 .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
36 .toFormatter();
37 }
38
39 @Override
40 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
41 return LocalDateTime.class == type;
42 }
43
44 @Override
45 public Object fromString(final String str) {
46 try {
47 return LocalDateTime.parse(str);
48 } catch (final DateTimeParseException e) {
49 final ConversionException exception = new ConversionException("Cannot parse value as local date time", e);
50 exception.add("value", str);
51 throw exception;
52 }
53 }
54
55 @Override
56 public String toString(final Object obj) {
57 if (obj == null) {
58 return null;
59 }
60
61 final LocalDateTime localDateTime = (LocalDateTime)obj;
62 return FORMATTER.format(localDateTime);
63 }
64 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. January 2017 by Matej Cimbora
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.LocalTime;
13 import java.time.format.DateTimeFormatter;
14 import java.time.format.DateTimeFormatterBuilder;
15 import java.time.format.DateTimeParseException;
16 import java.time.temporal.ChronoField;
17
18 import com.thoughtworks.xstream.converters.ConversionException;
19 import com.thoughtworks.xstream.converters.SingleValueConverter;
20
21
22 /**
23 * Converts a {@link LocalTime} to a string.
24 *
25 * @author Matej Cimbora
26 * @since 1.4.10
27 */
28 public class LocalTimeConverter implements SingleValueConverter {
29
30 private static final DateTimeFormatter FORMATTER;
31
32 static {
33 FORMATTER = new DateTimeFormatterBuilder()
34 .appendPattern("HH:mm:ss")
35 .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
36 .toFormatter();
37 }
38
39 @Override
40 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
41 return LocalTime.class == type;
42 }
43
44 @Override
45 public Object fromString(final String str) {
46 try {
47 return LocalTime.parse(str);
48 } catch (final DateTimeParseException e) {
49 final ConversionException exception = new ConversionException("Cannot parse value as local time", e);
50 exception.add("value", str);
51 throw exception;
52 }
53 }
54
55 @Override
56 public String toString(final Object obj) {
57 if (obj == null) {
58 return null;
59 }
60
61 final LocalTime localTime = (LocalTime)obj;
62 return FORMATTER.format(localTime);
63 }
64 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 22. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.chrono.ChronoLocalDate;
13 import java.time.chrono.MinguoChronology;
14 import java.time.chrono.MinguoDate;
15 import java.time.chrono.MinguoEra;
16 import java.util.Collections;
17
18
19 /**
20 * Converts a {@link java.time.chrono.MinguoDate} to a string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class MinguoDateConverter extends AbstractChronoLocalDateConverter<MinguoEra> {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return MinguoDate.class == type;
30 }
31
32 @Override
33 public Object fromString(final String str) {
34 return parseChronoLocalDate(str, "Minguo", Collections.singleton(MinguoChronology.INSTANCE));
35 }
36
37 @Override
38 protected ChronoLocalDate chronoLocalDateOf(final MinguoEra era, final int prolepticYear, final int month,
39 final int dayOfMonth) {
40 return MinguoDate.of(prolepticYear, month, dayOfMonth);
41 }
42
43 @Override
44 protected MinguoEra eraOf(final String id) {
45 return MinguoEra.valueOf(id);
46 }
47
48 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.MonthDay;
13 import java.time.format.DateTimeParseException;
14
15 import com.thoughtworks.xstream.converters.ConversionException;
16 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
17
18
19 /**
20 * Converts a {@link MonthDay} instance to string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class MonthDayConverter extends AbstractSingleValueConverter {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return MonthDay.class == type;
30 }
31
32 @Override
33 public MonthDay fromString(final String str) {
34 try {
35 return MonthDay.parse(str);
36 } catch (final DateTimeParseException ex) {
37 final ConversionException exception = new ConversionException("Cannot parse value as month day", ex);
38 exception.add("value", str);
39 throw exception;
40 }
41 }
42 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. January 2017 by Matej Cimbora
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.OffsetDateTime;
13 import java.time.format.DateTimeFormatter;
14 import java.time.format.DateTimeFormatterBuilder;
15 import java.time.format.DateTimeParseException;
16 import java.time.temporal.ChronoField;
17
18 import com.thoughtworks.xstream.converters.ConversionException;
19 import com.thoughtworks.xstream.converters.SingleValueConverter;
20
21
22 /**
23 * Converts a {@link OffsetDateTime} to a string.
24 *
25 * @author Matej Cimbora
26 * @since 1.4.10
27 */
28 public class OffsetDateTimeConverter implements SingleValueConverter {
29
30 private static final DateTimeFormatter FORMATTER;
31
32 static {
33 FORMATTER = new DateTimeFormatterBuilder()
34 .appendPattern("uuuu-MM-dd'T'HH:mm:ss")
35 .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
36 .appendOffsetId()
37 .toFormatter();
38 }
39
40 @Override
41 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
42 return OffsetDateTime.class == type;
43 }
44
45 @Override
46 public Object fromString(final String str) {
47 try {
48 return OffsetDateTime.parse(str);
49 } catch (final DateTimeParseException e) {
50 final ConversionException exception = new ConversionException("Cannot parse value as offset date time", e);
51 exception.add("value", str);
52 throw exception;
53 }
54 }
55
56 @Override
57 public String toString(final Object obj) {
58 if (obj == null) {
59 return null;
60 }
61
62 final OffsetDateTime offsetDateTime = (OffsetDateTime)obj;
63 return FORMATTER.format(offsetDateTime);
64 }
65 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 11. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.OffsetTime;
13 import java.time.format.DateTimeFormatter;
14 import java.time.format.DateTimeFormatterBuilder;
15 import java.time.format.DateTimeParseException;
16 import java.time.temporal.ChronoField;
17
18 import com.thoughtworks.xstream.converters.ConversionException;
19 import com.thoughtworks.xstream.converters.SingleValueConverter;
20
21
22 /**
23 * Converts a {@link OffsetTime} to a string.
24 *
25 * @author Matej Cimbora
26 * @author J&ouml;rg Schaible
27 * @since 1.4.10
28 */
29 public class OffsetTimeConverter implements SingleValueConverter {
30
31 private static final DateTimeFormatter FORMATTER;
32
33 static {
34 FORMATTER = new DateTimeFormatterBuilder()
35 .appendPattern("HH:mm:ss")
36 .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
37 .appendOffsetId()
38 .toFormatter();
39 }
40
41 @Override
42 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
43 return OffsetTime.class == type;
44 }
45
46 @Override
47 public Object fromString(final String str) {
48 try {
49 return OffsetTime.parse(str);
50 } catch (final DateTimeParseException e) {
51 final ConversionException exception = new ConversionException("Cannot parse value as offset time", e);
52 exception.add("value", str);
53 throw exception;
54 }
55 }
56
57 @Override
58 public String toString(final Object obj) {
59 if (obj == null) {
60 return null;
61 }
62
63 final OffsetTime offsetTime = (OffsetTime)obj;
64 return FORMATTER.format(offsetTime);
65 }
66 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.Period;
13 import java.time.format.DateTimeParseException;
14
15 import com.thoughtworks.xstream.converters.ConversionException;
16 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
17
18
19 /**
20 * Converts a {@link Period} instance to string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class PeriodConverter extends AbstractSingleValueConverter {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return Period.class == type;
30 }
31
32 @Override
33 public Period fromString(final String str) {
34 try {
35 return Period.parse(str);
36 } catch (final DateTimeParseException ex) {
37 final ConversionException exception = new ConversionException("Cannot parse period value", ex);
38 exception.add("period", str);
39 throw exception;
40 }
41 }
42 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 06. March 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.Clock;
13 import java.time.ZoneId;
14
15 import com.thoughtworks.xstream.converters.Converter;
16 import com.thoughtworks.xstream.converters.MarshallingContext;
17 import com.thoughtworks.xstream.converters.UnmarshallingContext;
18 import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
19 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
20 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
21 import com.thoughtworks.xstream.mapper.Mapper;
22
23
24 /**
25 * Converts a system {@link Clock}, using zone as nested element.
26 *
27 * @author J&ouml;rg Schaible
28 * @since 1.4.10
29 */
30 public class SystemClockConverter implements Converter {
31
32 private final Mapper mapper;
33 private final Class<?> type;
34
35 /**
36 * Constructs a SystemClockConverter instance.
37 *
38 * @param mapper the Mapper instance
39 */
40 public SystemClockConverter(final Mapper mapper) {
41 this.mapper = mapper;
42 type = Clock.systemUTC().getClass();
43 }
44
45 @Override
46 public boolean canConvert(final Class type) {
47 return type == this.type;
48 }
49
50 @Override
51 public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
52 final Clock clock = (Clock)source;
53 ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedMember(Clock.class, "zone"), null);
54 context.convertAnother(clock.getZone());
55 writer.endNode();
56 }
57
58 @Override
59 public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
60 reader.moveDown();
61 final ZoneId zone = (ZoneId)context.convertAnother(null, ZoneId.class);
62 reader.moveUp();
63 return Clock.system(zone);
64 }
65 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 22. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.chrono.ChronoLocalDate;
13 import java.time.chrono.ThaiBuddhistChronology;
14 import java.time.chrono.ThaiBuddhistDate;
15 import java.time.chrono.ThaiBuddhistEra;
16 import java.util.Collections;
17
18
19 /**
20 * Converts a {@link java.time.chrono.ThaiBuddhistDate} to a string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class ThaiBuddhistDateConverter extends AbstractChronoLocalDateConverter<ThaiBuddhistEra> {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return ThaiBuddhistDate.class == type;
30 }
31
32 @Override
33 public Object fromString(final String str) {
34 return parseChronoLocalDate(str, "Thai Buddhist", Collections.singleton(ThaiBuddhistChronology.INSTANCE));
35 }
36
37 @Override
38 protected ChronoLocalDate chronoLocalDateOf(final ThaiBuddhistEra era, final int prolepticYear, final int month,
39 final int dayOfMonth) {
40 return ThaiBuddhistDate.of(prolepticYear, month, dayOfMonth);
41 }
42
43 @Override
44 protected ThaiBuddhistEra eraOf(final String id) {
45 return ThaiBuddhistEra.valueOf(id);
46 }
47
48 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 22. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.temporal.ValueRange;
13 import java.util.HashMap;
14 import java.util.Map;
15
16 import com.thoughtworks.xstream.converters.Converter;
17 import com.thoughtworks.xstream.converters.MarshallingContext;
18 import com.thoughtworks.xstream.converters.UnmarshallingContext;
19 import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
20 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
21 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
22 import com.thoughtworks.xstream.mapper.Mapper;
23
24
25 /**
26 * Converts a temporal {@link ValueRange}, using four nested elements: maxLargest, maxSmallest, minLargest, and
27 * minSmallest.
28 *
29 * @author J&ouml;rg Schaible
30 * @since 1.4.10
31 */
32 public class ValueRangeConverter implements Converter {
33
34 private final Mapper mapper;
35
36 /**
37 * Constructs a ValueRangeConverter instance.
38 *
39 * @param mapper the Mapper instance
40 */
41 public ValueRangeConverter(final Mapper mapper) {
42 this.mapper = mapper;
43
44 }
45
46 @Override
47 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
48 return type == ValueRange.class;
49 }
50
51 @Override
52 public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
53 final ValueRange valueRange = (ValueRange)source;
54 write("maxLargest", valueRange.getMaximum(), writer);
55 write("maxSmallest", valueRange.getSmallestMaximum(), writer);
56 write("minLargest", valueRange.getLargestMinimum(), writer);
57 write("minSmallest", valueRange.getMinimum(), writer);
58 }
59
60 @Override
61 public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
62 final boolean oldFormat = "custom".equals(reader.getAttribute(mapper.aliasForSystemAttribute("serialization")));
63 if (oldFormat) {
64 reader.moveDown();
65 reader.moveDown();
66 }
67 final Map<String, Long> elements = new HashMap<>();
68 while (reader.hasMoreChildren()) {
69 reader.moveDown();
70
71 final String name = reader.getNodeName();
72 elements.put(oldFormat ? name : mapper.realMember(ValueRange.class, name), Long.valueOf(reader.getValue()));
73 reader.moveUp();
74 }
75 if (oldFormat) {
76 reader.moveUp();
77 reader.moveUp();
78 }
79 return ValueRange.of(elements.get("minSmallest").longValue(), elements.get("minLargest").longValue(), elements
80 .get("maxSmallest")
81 .longValue(), elements.get("maxLargest").longValue());
82 }
83
84 private void write(final String fieldName, final long value, final HierarchicalStreamWriter writer) {
85 ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedMember(ValueRange.class, fieldName),
86 long.class);
87 writer.setValue(String.valueOf(value));
88 writer.endNode();
89 }
90 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 22. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.DayOfWeek;
13 import java.time.temporal.WeekFields;
14
15 import com.thoughtworks.xstream.converters.Converter;
16 import com.thoughtworks.xstream.converters.MarshallingContext;
17 import com.thoughtworks.xstream.converters.UnmarshallingContext;
18 import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.UnknownFieldException;
19 import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
20 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
21 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
22 import com.thoughtworks.xstream.mapper.Mapper;
23
24
25 /**
26 * Converts a {@link WeekFields} instance, using two nested elements: minimalDays and minSmallest.
27 *
28 * @author J&ouml;rg Schaible
29 * @since 1.4.10
30 */
31 public class WeekFieldsConverter implements Converter {
32
33 private final Mapper mapper;
34
35 /**
36 * Constructs a WeekFieldsConverter instance.
37 *
38 * @param mapper the Mapper instance
39 */
40 public WeekFieldsConverter(final Mapper mapper) {
41 this.mapper = mapper;
42
43 }
44
45 @Override
46 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
47 return type == WeekFields.class;
48 }
49
50 @Override
51 public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
52 final WeekFields weekFields = (WeekFields)source;
53 ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedMember(WeekFields.class,
54 "minimalDays"), int.class);
55 writer.setValue(String.valueOf(weekFields.getMinimalDaysInFirstWeek()));
56 writer.endNode();
57 ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedMember(WeekFields.class,
58 "firstDayOfWeek"), DayOfWeek.class);
59 context.convertAnother(weekFields.getFirstDayOfWeek());
60 writer.endNode();
61 }
62
63 @Override
64 public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
65 final boolean oldFormat = "custom".equals(reader.getAttribute(mapper.aliasForSystemAttribute("serialization")));
66 if (oldFormat) {
67 reader.moveDown();
68 reader.moveDown();
69 }
70
71 int minimalDays = 0;
72 DayOfWeek firstDayOfWeek = null;
73 while (reader.hasMoreChildren()) {
74 reader.moveDown();
75 final String name = oldFormat
76 ? reader.getNodeName()
77 : mapper.realMember(WeekFields.class, reader.getNodeName());
78 if ("minimalDays".equals(name)) {
79 minimalDays = Integer.parseInt(reader.getValue());
80 } else if ("firstDayOfWeek".equals(name)) {
81 firstDayOfWeek = (DayOfWeek)context.convertAnother(null, DayOfWeek.class);
82 } else {
83 throw new UnknownFieldException(WeekFields.class.getName(), name);
84 }
85 reader.moveUp();
86 }
87 if (oldFormat) {
88 reader.moveUp();
89 reader.moveUp();
90 }
91 return WeekFields.of(firstDayOfWeek, minimalDays);
92 }
93 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 11. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.Year;
13
14 import com.thoughtworks.xstream.converters.ConversionException;
15 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
16
17
18 /**
19 * Converts a {@link Year} instance to string.
20 *
21 * @author J&ouml;rg Schaible
22 * @since 1.4.10
23 */
24 public class YearConverter extends AbstractSingleValueConverter {
25
26 @Override
27 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
28 return Year.class == type;
29 }
30
31 @Override
32 public Year fromString(final String str) {
33 try {
34 return Year.of(Integer.parseInt(str));
35 } catch (final NumberFormatException ex) {
36 final ConversionException exception = new ConversionException("Cannot parse value as year", ex);
37 exception.add("value", str);
38 throw exception;
39 }
40 }
41 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 11. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.YearMonth;
13 import java.time.format.DateTimeParseException;
14
15 import com.thoughtworks.xstream.converters.ConversionException;
16 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
17
18
19 /**
20 * Converts a {@link YearMonth} instance to string.
21 *
22 * @author J&ouml;rg Schaible
23 * @since 1.4.10
24 */
25 public class YearMonthConverter extends AbstractSingleValueConverter {
26
27 @Override
28 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
29 return YearMonth.class == type;
30 }
31
32 @Override
33 public YearMonth fromString(final String str) {
34 try {
35 return YearMonth.parse(str);
36 } catch (final DateTimeParseException ex) {
37 final ConversionException exception = new ConversionException("Cannot parse value as year month", ex);
38 exception.add("value", str);
39 throw exception;
40 }
41 }
42 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 8. February 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.DateTimeException;
13 import java.time.ZoneId;
14 import java.time.zone.ZoneRulesException;
15
16 import com.thoughtworks.xstream.converters.ConversionException;
17 import com.thoughtworks.xstream.converters.SingleValueConverter;
18
19
20 /**
21 * Converts a {@link ZoneId} instance to string.
22 *
23 * @author J&ouml;rg Schaible
24 * @since 1.4.10
25 */
26 public class ZoneIdConverter implements SingleValueConverter {
27
28 @Override
29 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
30 return ZoneId.class.isAssignableFrom(type);
31 }
32
33 @Override
34 public ZoneId fromString(final String str) {
35 ConversionException exception;
36 try {
37 return ZoneId.of(str);
38 } catch (final ZoneRulesException e) {
39 exception = new ConversionException("Not a valid zone id", e);
40 } catch (final DateTimeException e) {
41 exception = new ConversionException("Cannot parse value as zone id", e);
42 }
43 exception.add("value", str);
44 throw exception;
45 }
46
47 @Override
48 public String toString(final Object obj) {
49 if (obj == null) {
50 return null;
51 }
52 final ZoneId zoneId = (ZoneId)obj;
53 return zoneId.getId();
54 }
55 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. January 2017 by Matej Cimbora
9 */
10 package com.thoughtworks.xstream.converters.time;
11
12 import java.time.ZonedDateTime;
13 import java.time.format.DateTimeFormatter;
14 import java.time.format.DateTimeFormatterBuilder;
15 import java.time.format.DateTimeParseException;
16 import java.time.temporal.ChronoField;
17
18 import com.thoughtworks.xstream.converters.ConversionException;
19 import com.thoughtworks.xstream.converters.SingleValueConverter;
20
21
22 /**
23 * Converts a {@link ZonedDateTime} to a string.
24 *
25 * @author Matej Cimbora
26 * @since 1.4.10
27 */
28 public class ZonedDateTimeConverter implements SingleValueConverter {
29
30 private static final DateTimeFormatter FORMATTER;
31
32 static {
33 FORMATTER = new DateTimeFormatterBuilder()
34 .appendPattern("uuuu-MM-dd'T'HH:mm:ss")
35 .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
36 .appendOffsetId()
37 .appendLiteral("[")
38 .appendZoneId()
39 .appendLiteral("]")
40 .toFormatter();
41 }
42
43 @Override
44 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
45 return ZonedDateTime.class == type;
46 }
47
48 @Override
49 public String toString(final Object obj) {
50 if (obj == null) {
51 return null;
52 }
53
54 final ZonedDateTime zonedDateTime = (ZonedDateTime)obj;
55 return FORMATTER.format(zonedDateTime);
56 }
57
58 @Override
59 public Object fromString(final String str) {
60 try {
61 return ZonedDateTime.parse(str);
62 } catch (final DateTimeParseException e) {
63 final ConversionException exception = new ConversionException("Cannot parse value as zoned date time", e);
64 exception.add("value", str);
65 throw exception;
66 }
67 }
68
69 }
0 <!--
1 * Copyright (C) 2017 XStream committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 12. February 2017 by Joerg Schaible
9 -->
10 <body>
11 <p>Extra converters for the java.time package.</p>
12 </body>
00 /*
11 * Copyright (C) 2004, 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2016 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1919
2020 import java.util.Collections;
2121 import java.util.Iterator;
22 import java.util.LinkedHashMap;
2223 import java.util.Map;
2324 import java.util.WeakHashMap;
2425
4950 if (cachedConverter != null) {
5051 return cachedConverter;
5152 }
53
54 final Map errors = new LinkedHashMap();
5255 Iterator iterator = converters.iterator();
5356 while (iterator.hasNext()) {
5457 Converter converter = (Converter) iterator.next();
55 if (converter.canConvert(type)) {
56 typeToConverterMap.put(type, converter);
57 return converter;
58 try {
59 if (converter.canConvert(type)) {
60 typeToConverterMap.put(type, converter);
61 return converter;
62 }
63 } catch (final RuntimeException e) {
64 errors.put(converter.getClass().getName(), e.getMessage());
65 } catch (final LinkageError e) {
66 errors.put(converter.getClass().getName(), e.getMessage());
5867 }
5968 }
60 ConversionException exception = new ConversionException("No converter specified");
69
70 final ConversionException exception = new ConversionException(errors.isEmpty()
71 ? "No converter specified"
72 : "No converter available");
6173 exception.add("type", type.getName());
74 iterator = errors.entrySet().iterator();
75 while (iterator.hasNext()) {
76 final Map.Entry entry = (Map.Entry)iterator.next();
77 exception.add("converter", entry.getKey().toString());
78 exception.add("message", entry.getValue().toString());
79 }
6280 throw exception;
6381 }
6482
6684 converters.add(converter, priority);
6785 for (Iterator iter = typeToConverterMap.keySet().iterator(); iter.hasNext();) {
6886 Class type = (Class) iter.next();
69 if (converter.canConvert(type)) {
70 iter.remove();
87 try {
88 if (converter.canConvert(type)) {
89 iter.remove();
90 }
91 } catch (final RuntimeException e) {
92 // ignore
93 } catch (final LinkageError e) {
94 // ignore
7195 }
7296 }
7397 }
00 /*
11 * Copyright (C) 2004, 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2014, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
201201 }
202202
203203 /**
204 * @deprecated As of 1.4.4, minimal JDK version will be 1.6 for next major release
204 * @deprecated As of 1.4.4, minimal JDK version will be 1.7 for next major release
205205 */
206206 public static boolean is15() {
207207 return majorJavaVersion >= 1.5f;
208208 }
209209
210210 /**
211 * @deprecated As of 1.4.4, minimal JDK version will be 1.6 for next major release
211 * @deprecated As of 1.4.4, minimal JDK version will be 1.7 for next major release
212212 */
213213 public static boolean is16() {
214214 return majorJavaVersion >= 1.6f;
216216
217217 /**
218218 * @since 1.4
219 * @deprecated As of 1.4.10, minimal JDK version will be 1.7 for next major release
219220 */
220221 public static boolean is17() {
221222 return majorJavaVersion >= 1.7f;
230231
231232 /**
232233 * @since 1.4.8
234 * @deprecated As of upcoming use {@link #is9()}
233235 */
234236 public static boolean is19() {
235237 return majorJavaVersion >= 1.9f;
238 }
239
240 /**
241 * @since 1.4.10
242 */
243 public static boolean is9() {
244 return majorJavaVersion >= 9f;
236245 }
237246
238247 private static boolean isIBM() {
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 05. May 2017 by Joerg Schaible
9 */
10 package com.thoughtworks.xstream.core.util;
11
12 import java.time.Instant;
13 import java.time.LocalDate;
14 import java.time.LocalDateTime;
15 import java.time.LocalTime;
16 import java.time.MonthDay;
17 import java.time.OffsetDateTime;
18 import java.time.OffsetTime;
19 import java.time.Year;
20 import java.time.YearMonth;
21 import java.time.ZoneId;
22 import java.time.ZoneOffset;
23 import java.time.format.DateTimeFormatter;
24 import java.time.format.DateTimeFormatterBuilder;
25 import java.time.format.DateTimeParseException;
26 import java.time.temporal.ChronoField;
27 import java.time.temporal.IsoFields;
28 import java.time.temporal.TemporalAccessor;
29 import java.time.temporal.WeekFields;
30 import java.util.Calendar;
31 import java.util.GregorianCalendar;
32 import java.util.Locale;
33
34 import com.thoughtworks.xstream.converters.ConversionException;
35 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
36
37
38 /**
39 * A converter for {@link GregorianCalendar} conforming to the ISO8601 standard based on java.time.
40 * <p>
41 * The converter will always serialize the calendar value in UTC and deserialize it to a value in the current default
42 * time zone.
43 * </p>
44 *
45 * @author J&ouml;rg Schaible
46 * @see <a href="http://www.iso.org/iso/home/store/catalogue_ics/catalogue_detail_ics.htm?csnumber=40874">ISO 8601</a>
47 * @since 1.4.10
48 */
49 public class ISO8601JavaTimeConverter extends AbstractSingleValueConverter {
50 private static final DateTimeFormatter STD_DATE_TIME = new DateTimeFormatterBuilder()
51 .appendPattern("yyyy-MM-dd'T'HH:mm:ss")
52 .appendFraction(ChronoField.NANO_OF_SECOND, 3, 9, true)
53 .appendOffsetId()
54 .toFormatter();
55 private static final DateTimeFormatter STD_ORDINAL_DATE_TIME = new DateTimeFormatterBuilder()
56 .appendPattern("yyyy-DDD'T'HH:mm:ss")
57 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
58 .appendOffsetId()
59 .toFormatter();
60 private static final DateTimeFormatter BASIC_DATE_TIME = new DateTimeFormatterBuilder()
61 .appendPattern("yyyyMMdd'T'HHmmss")
62 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
63 .appendOffsetId()
64 .toFormatter();
65 private static final DateTimeFormatter BASIC_ORDINAL_DATE_TIME = new DateTimeFormatterBuilder()
66 .appendPattern("yyyyDDD'T'HHmmss")
67 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
68 .appendOffsetId()
69 .toFormatter();
70 private static final DateTimeFormatter BASIC_TIME = new DateTimeFormatterBuilder()
71 .appendPattern("HHmmss")
72 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
73 .appendOffsetId()
74 .toFormatter();
75 private static final DateTimeFormatter ISO_TTIME = new DateTimeFormatterBuilder()
76 .appendPattern("'T'HH:mm:ss")
77 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
78 .appendOffsetId()
79 .toFormatter();
80 private static final DateTimeFormatter BASIC_TTIME = new DateTimeFormatterBuilder()
81 .appendPattern("'T'HHmmss")
82 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
83 .appendOffsetId()
84 .toFormatter();
85 private static final DateTimeFormatter ISO_WEEK_DATE_TIME = new DateTimeFormatterBuilder()
86 .appendPattern("YYYY-'W'ww-e'T'HH:mm:ss")
87 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
88 .appendOffsetId()
89 .toFormatter();
90 private static final DateTimeFormatter BASIC_WEEK_DATE_TIME = new DateTimeFormatterBuilder()
91 .appendPattern("YYYY'W'wwe'T'HHmmss")
92 .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
93 .appendOffsetId()
94 .toFormatter();
95 private static final DateTimeFormatter BASIC_ORDINAL_DATE = new DateTimeFormatterBuilder()
96 .appendPattern("yyyyDDD")
97 .toFormatter();
98 private static final DateTimeFormatter BASIC_WEEK_DATE = new DateTimeFormatterBuilder()
99 .appendPattern("YYYY'W'wwe")
100 .toFormatter();
101 private static final DateTimeFormatter STD_DATE_HOUR = new DateTimeFormatterBuilder()
102 .appendPattern("yyyy-MM-dd'T'HH")
103 .toFormatter();
104 private static final DateTimeFormatter STD_HOUR = new DateTimeFormatterBuilder().appendPattern("HH").toFormatter();
105 private static final DateTimeFormatter STD_YEAR_WEEK = new DateTimeFormatterBuilder()
106 .appendPattern("YYYY-'W'ww")
107 .parseDefaulting(ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR, 1)
108 .toFormatter();
109
110 @Override
111 public boolean canConvert(@SuppressWarnings("rawtypes") final Class type) {
112 return false;
113 }
114
115 @Override
116 public Object fromString(final String str) {
117 try {
118 final OffsetDateTime odt = OffsetDateTime.parse(str);
119 return GregorianCalendar.from(odt.atZoneSameInstant(ZoneId.systemDefault()));
120 } catch (final DateTimeParseException e) {
121 // try with next formatter
122 }
123 try {
124 final LocalDateTime ldt = LocalDateTime.parse(str);
125 return GregorianCalendar.from(ldt.atZone(ZoneId.systemDefault()));
126 } catch (final DateTimeParseException e) {
127 // try with next formatter
128 }
129 try {
130 final Instant instant = Instant.parse(str);
131 return GregorianCalendar.from(instant.atZone(ZoneId.systemDefault()));
132 } catch (final DateTimeParseException e) {
133 // try with next formatter
134 }
135 try {
136 final OffsetDateTime odt = BASIC_DATE_TIME.parse(str, OffsetDateTime::from);
137 return GregorianCalendar.from(odt.atZoneSameInstant(ZoneId.systemDefault()));
138 } catch (final DateTimeParseException e) {
139 // try with next formatter
140 }
141 try {
142 final OffsetDateTime odt = STD_ORDINAL_DATE_TIME.parse(str, OffsetDateTime::from);
143 return GregorianCalendar.from(odt.atZoneSameInstant(ZoneId.systemDefault()));
144 } catch (final DateTimeParseException e) {
145 // try with next formatter
146 }
147 try {
148 final OffsetDateTime odt = BASIC_ORDINAL_DATE_TIME.parse(str, OffsetDateTime::from);
149 return GregorianCalendar.from(odt.atZoneSameInstant(ZoneId.systemDefault()));
150 } catch (final DateTimeParseException e) {
151 // try with next formatter
152 }
153 try {
154 final OffsetTime ot = OffsetTime.parse(str);
155 return GregorianCalendar.from(ot.atDate(LocalDate.ofEpochDay(0)).atZoneSameInstant(ZoneId.systemDefault()));
156 } catch (final DateTimeParseException e) {
157 // try with next formatter
158 }
159 try {
160 final OffsetTime ot = BASIC_TIME.parse(str, OffsetTime::from);
161 return GregorianCalendar.from(ot.atDate(LocalDate.ofEpochDay(0)).atZoneSameInstant(ZoneId.systemDefault()));
162 } catch (final DateTimeParseException e) {
163 // try with next formatter
164 }
165 try {
166 final OffsetTime ot = ISO_TTIME.parse(str, OffsetTime::from);
167 return GregorianCalendar.from(ot.atDate(LocalDate.ofEpochDay(0)).atZoneSameInstant(ZoneId.systemDefault()));
168 } catch (final DateTimeParseException e) {
169 // try with next formatter
170 }
171 try {
172 final OffsetTime ot = BASIC_TTIME.parse(str, OffsetTime::from);
173 return GregorianCalendar.from(ot.atDate(LocalDate.ofEpochDay(0)).atZoneSameInstant(ZoneId.systemDefault()));
174 } catch (final DateTimeParseException e) {
175 // try with next formatter
176 }
177 try {
178 final TemporalAccessor ta = ISO_WEEK_DATE_TIME.withLocale(Locale.getDefault()).parse(str);
179 final Year y = Year.from(ta);
180 final MonthDay md = MonthDay.from(ta);
181 final OffsetTime ot = OffsetTime.from(ta);
182 return GregorianCalendar.from(ot.atDate(y.atMonthDay(md)).atZoneSameInstant(ZoneId.systemDefault()));
183 } catch (final DateTimeParseException e) {
184 // try with next formatter
185 }
186 try {
187 final TemporalAccessor ta = BASIC_WEEK_DATE_TIME.withLocale(Locale.getDefault()).parse(str);
188 final Year y = Year.from(ta);
189 final MonthDay md = MonthDay.from(ta);
190 final OffsetTime ot = OffsetTime.from(ta);
191 return GregorianCalendar.from(ot.atDate(y.atMonthDay(md)).atZoneSameInstant(ZoneId.systemDefault()));
192 } catch (final DateTimeParseException e) {
193 // try with next formatter
194 }
195 try {
196 final LocalDate ld = LocalDate.parse(str);
197 return GregorianCalendar.from(ld.atStartOfDay(ZoneId.systemDefault()));
198 } catch (final DateTimeParseException e) {
199 // try with next formatter
200 }
201 try {
202 final LocalDate ld = LocalDate.parse(str, DateTimeFormatter.BASIC_ISO_DATE);
203 return GregorianCalendar.from(ld.atStartOfDay(ZoneId.systemDefault()));
204 } catch (final DateTimeParseException e) {
205 // try with next formatter
206 }
207 try {
208 final LocalDate ld = LocalDate.parse(str, DateTimeFormatter.ISO_ORDINAL_DATE);
209 return GregorianCalendar.from(ld.atStartOfDay(ZoneId.systemDefault()));
210 } catch (final DateTimeParseException e) {
211 // try with next formatter
212 }
213 try {
214 final LocalDate ld = BASIC_ORDINAL_DATE.parse(str, LocalDate::from);
215 return GregorianCalendar.from(ld.atStartOfDay(ZoneId.systemDefault()));
216 } catch (final DateTimeParseException e) {
217 // try with next formatter
218 }
219 try {
220 final LocalDate ld = LocalDate.parse(str, DateTimeFormatter.ISO_WEEK_DATE.withLocale(Locale.getDefault()));
221 return GregorianCalendar.from(ld.atStartOfDay(ZoneId.systemDefault()));
222 } catch (final DateTimeParseException e) {
223 // try with next formatter
224 }
225 try {
226 final TemporalAccessor ta = BASIC_WEEK_DATE.withLocale(Locale.getDefault()).parse(str);
227 final Year y = Year.from(ta);
228 final MonthDay md = MonthDay.from(ta);
229 return GregorianCalendar.from(y.atMonthDay(md).atStartOfDay(ZoneId.systemDefault()));
230 } catch (final DateTimeParseException e) {
231 // try with next formatter
232 }
233 try {
234 final LocalDateTime ldt = STD_DATE_HOUR.parse(str, LocalDateTime::from);
235 return GregorianCalendar.from(ldt.atZone(ZoneId.systemDefault()));
236 } catch (final DateTimeParseException e) {
237 // try with next formatter
238 }
239 try {
240 final LocalTime lt = STD_HOUR.parse(str, LocalTime::from);
241 return GregorianCalendar.from(lt.atDate(LocalDate.ofEpochDay(0)).atZone(ZoneId.systemDefault()));
242 } catch (final DateTimeParseException e) {
243 // try with next formatter
244 }
245 try {
246 final LocalTime lt = LocalTime.parse(str);
247 return GregorianCalendar.from(lt.atDate(LocalDate.ofEpochDay(0)).atZone(ZoneId.systemDefault()));
248 } catch (final DateTimeParseException e) {
249 // try with next formatter
250 }
251 try {
252 final YearMonth ym = YearMonth.parse(str);
253 return GregorianCalendar.from(ym.atDay(1).atStartOfDay(ZoneId.systemDefault()));
254 } catch (final DateTimeParseException e) {
255 // try with next formatter
256 }
257 try {
258 final Year y = Year.parse(str);
259 return GregorianCalendar.from(y.atDay(1).atStartOfDay(ZoneId.systemDefault()));
260 } catch (final DateTimeParseException e) {
261 // try with next formatter
262 }
263 try {
264 final TemporalAccessor ta = STD_YEAR_WEEK.withLocale(Locale.getDefault()).parse(str);
265 final int y = ta.get(WeekFields.ISO.weekBasedYear());
266 final int w = ta.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
267 return GregorianCalendar.from(LocalDateTime
268 .from(ta)
269 .with(WeekFields.ISO.weekOfYear(), y)
270 .with(WeekFields.ISO.weekOfWeekBasedYear(), w)
271 .atZone(ZoneId.systemDefault()));
272 // } catch (final IllegalArgumentException e) { // TODO: DateTimeParseException
273 } catch (final DateTimeParseException e) {
274 // try with next formatter
275 }
276 final ConversionException exception = new ConversionException("Cannot parse date");
277 exception.add("date", str);
278 throw exception;
279 }
280
281 @Override
282 public String toString(final Object obj) {
283 final Calendar calendar = (Calendar)obj;
284 final Instant instant = Instant.ofEpochMilli(calendar.getTimeInMillis());
285 final int offsetInMillis = calendar.getTimeZone().getOffset(calendar.getTimeInMillis());
286 final OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(instant, ZoneOffset.ofTotalSeconds(offsetInMillis
287 / 1000));
288 return STD_DATE_TIME.format(offsetDateTime);
289 }
290 }
0 /*
1 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2011, 2013, 2014, 2015, 2016, 2017 XStream Committers.
3 * All rights reserved.
4 *
5 * The software in this package is published under the terms of the BSD
6 * style license a copy of which has been included with this distribution in
7 * the LICENSE.txt file.
8 *
9 * Created on 05. May 2017 by Joerg Schaible, copied from ISO8601GregorianCalendarConverter
10 */
11 package com.thoughtworks.xstream.core.util;
12
13 import java.util.Calendar;
14 import java.util.GregorianCalendar;
15 import java.util.TimeZone;
16
17 import org.joda.time.DateTime;
18 import org.joda.time.DateTimeZone;
19 import org.joda.time.format.DateTimeFormatter;
20 import org.joda.time.format.ISODateTimeFormat;
21
22 import com.thoughtworks.xstream.converters.ConversionException;
23 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
24
25
26 /**
27 * A converter for {@link GregorianCalendar} conforming to the ISO8601 standard based on Joda-Time.
28 * <p>
29 * The converter will always serialize the calendar value in UTC and deserialize it to a value in the current default
30 * time zone.
31 * </p>
32 *
33 * @author Mauro Talevi
34 * @author J&ouml;rg Schaible
35 * @see <a href="http://www.iso.org/iso/home/store/catalogue_ics/catalogue_detail_ics.htm?csnumber=40874">ISO 8601</a>
36 * @since 1.4.10
37 */
38 public class ISO8601JodaTimeConverter extends AbstractSingleValueConverter {
39 private static final DateTimeFormatter[] formattersUTC = { //
40 ISODateTimeFormat.dateTime(), //
41 ISODateTimeFormat.dateTimeNoMillis(), //
42 ISODateTimeFormat.basicDateTime(), //
43 ISODateTimeFormat.basicDateTimeNoMillis(), //
44 ISODateTimeFormat.basicOrdinalDateTime(), //
45 ISODateTimeFormat.basicOrdinalDateTimeNoMillis(), //
46 ISODateTimeFormat.basicTime(), //
47 ISODateTimeFormat.basicTimeNoMillis(), //
48 ISODateTimeFormat.basicTTime(), //
49 ISODateTimeFormat.basicTTimeNoMillis(), //
50 ISODateTimeFormat.basicWeekDateTime(), //
51 ISODateTimeFormat.basicWeekDateTimeNoMillis(), //
52 ISODateTimeFormat.ordinalDateTime(), //
53 ISODateTimeFormat.ordinalDateTimeNoMillis(), //
54 ISODateTimeFormat.time(), //
55 ISODateTimeFormat.timeNoMillis(), //
56 ISODateTimeFormat.tTime(), //
57 ISODateTimeFormat.tTimeNoMillis(), //
58 ISODateTimeFormat.weekDateTime(), //
59 ISODateTimeFormat.weekDateTimeNoMillis() //
60 };
61 private static final DateTimeFormatter[] formattersNoUTC = { //
62 ISODateTimeFormat.basicDate(), //
63 ISODateTimeFormat.basicOrdinalDate(), //
64 ISODateTimeFormat.basicWeekDate(), //
65 ISODateTimeFormat.date(), //
66 ISODateTimeFormat.dateHour(), //
67 ISODateTimeFormat.dateHourMinute(), //
68 ISODateTimeFormat.dateHourMinuteSecond(), //
69 ISODateTimeFormat.dateHourMinuteSecondFraction(), //
70 ISODateTimeFormat.dateHourMinuteSecondMillis(), //
71 ISODateTimeFormat.hour(), //
72 ISODateTimeFormat.hourMinute(), //
73 ISODateTimeFormat.hourMinuteSecond(), //
74 ISODateTimeFormat.hourMinuteSecondFraction(), //
75 ISODateTimeFormat.hourMinuteSecondMillis(), //
76 ISODateTimeFormat.ordinalDate(), //
77 ISODateTimeFormat.weekDate(), //
78 ISODateTimeFormat.year(), //
79 ISODateTimeFormat.yearMonth(), //
80 ISODateTimeFormat.yearMonthDay(), //
81 ISODateTimeFormat.weekyear(), //
82 ISODateTimeFormat.weekyearWeek(), //
83 ISODateTimeFormat.weekyearWeekDay() //
84 };
85
86 public boolean canConvert(final Class type) {
87 return false;
88 }
89
90 public Object fromString(final String str) {
91 for (int i = 0; i < formattersUTC.length ; ++i) {
92 final DateTimeFormatter formatter = formattersUTC[i];
93 try {
94 final DateTime dt = formatter.parseDateTime(str);
95 final Calendar calendar = dt.toGregorianCalendar();
96 calendar.setTimeZone(TimeZone.getDefault());
97 return calendar;
98 } catch (final IllegalArgumentException e) {
99 // try with next formatter
100 }
101 }
102 final DateTimeZone dateTimeZone = DateTimeZone.forTimeZone(TimeZone.getDefault());
103 for (int i = 0; i < formattersNoUTC.length ; ++i) {
104 final DateTimeFormatter element = formattersNoUTC[i];
105 try {
106 final DateTimeFormatter formatter = element.withZone(dateTimeZone);
107 final DateTime dt = formatter.parseDateTime(str);
108 final Calendar calendar = dt.toGregorianCalendar();
109 calendar.setTimeZone(TimeZone.getDefault());
110 return calendar;
111 } catch (final IllegalArgumentException e) {
112 // try with next formatter
113 }
114 }
115 final ConversionException exception = new ConversionException("Cannot parse date");
116 exception.add("date", str);
117 throw exception;
118 }
119
120 public String toString(final Object obj) {
121 final DateTime dt = new DateTime(obj);
122 return dt.toString(formattersUTC[0]);
123 }
124 }
9797 if (writeReplaceMethod != null) {
9898 ErrorWritingException ex = null;
9999 try {
100 return writeReplaceMethod.invoke(object, EMPTY_ARGS);
101 } catch (IllegalAccessException e) {
100 Object replaced = writeReplaceMethod.invoke(object, EMPTY_ARGS);
101 if (replaced != null && !object.getClass().equals(replaced.getClass())) {
102 // call further writeReplace methods on replaced
103 replaced = callWriteReplace(replaced);
104 }
105 return replaced;
106 } catch (final IllegalAccessException e) {
102107 ex = new ObjectAccessException("Cannot access method", e);
103108 } catch (InvocationTargetException e) {
104109 ex = new ConversionException("Failed calling method", e.getTargetException());
110 } catch (final ErrorWritingException e) {
111 ex = e;
105112 }
106113 ex.add("method", objectType.getName() + ".writeReplace()");
107114 throw ex;
00 /*
11 * Copyright (C) 2004, 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2011 XStream Committers.
2 * Copyright (C) 2006, 2007, 2011, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
4848
4949 /**
5050 * Get the value of an attribute of the current node.
51 * <p>
52 * If no such attribute exists, the method returns null.
53 * </p>
5154 */
5255 String getAttribute(String name);
5356
5457 /**
5558 * Get the value of an attribute of the current node, by index.
59 * <p>
60 * Note, the behavior of this method is dependent on the underlying parser when calling it with a non-existing
61 * index. Typically some kind of RuntimeException is thrown.
62 * </p>
5663 */
5764 String getAttribute(int index);
5865
6370
6471 /**
6572 * Name of attribute in current node.
73 * <p>
74 * Note, the behavior of this method is dependent on the underlying parser when calling it with a non-existing
75 * index. Typically some kind of RuntimeException is thrown.
76 * </p>
6677 */
6778 String getAttributeName(int index);
6879
6980 /**
70 * Names of attributes (as Strings).
81 * Iterator with the names of the attributes.
82 * <p>
83 * Note, the iterator is only valid as long as the internal state of the underlying parser is still at the start of
84 * the current element. The behavior is undefined if the parser moved on.
85 * </p>
7186 */
7287 Iterator getAttributeNames();
7388
00 /*
11 * Copyright (C) 2004, 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2009, 2011 XStream Committers.
2 * Copyright (C) 2006, 2007, 2009, 2011, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
66 * style license a copy of which has been included with this distribution in
77 * the LICENSE.txt file.
8 *
8 *
99 * Created on 07. March 2004 by Joe Walnes
1010 */
1111 package com.thoughtworks.xstream.io.xml;
121121 public void close() {
122122 try {
123123 writer.endDocument();
124 writer.flush();
124125 } catch (SAXException e) {
126 throw new StreamException(e);
127 } catch (IOException e) {
125128 throw new StreamException(e);
126129 }
127130 }
6868 private transient DefaultImplementationsMapper defaultImplementationsMapper;
6969 private transient ImplicitCollectionMapper implicitCollectionMapper;
7070 private transient FieldAliasingMapper fieldAliasingMapper;
71 private transient ElementIgnoringMapper elementIgnoringMapper;
7172 private transient AttributeMapper attributeMapper;
7273 private transient LocalConversionMapper localConversionMapper;
7374 private final Map<Class<?>, Map<List<Object>, Converter>> converterCache =
456457 final XStreamOmitField omitFieldAnnotation = field
457458 .getAnnotation(XStreamOmitField.class);
458459 if (omitFieldAnnotation != null) {
459 if (fieldAliasingMapper == null) {
460 if (elementIgnoringMapper == null) {
460461 throw new InitializationException("No "
461 + FieldAliasingMapper.class.getName()
462 + ElementIgnoringMapper.class.getName()
462463 + " available");
463464 }
464 fieldAliasingMapper.omitField(field.getDeclaringClass(), field.getName());
465 elementIgnoringMapper.omitField(field.getDeclaringClass(), field.getName());
465466 }
466467 }
467468
568569 defaultImplementationsMapper = (DefaultImplementationsMapper)lookupMapperOfType(DefaultImplementationsMapper.class);
569570 implicitCollectionMapper = (ImplicitCollectionMapper)lookupMapperOfType(ImplicitCollectionMapper.class);
570571 fieldAliasingMapper = (FieldAliasingMapper)lookupMapperOfType(FieldAliasingMapper.class);
572 elementIgnoringMapper = (ElementIgnoringMapper)lookupMapperOfType(ElementIgnoringMapper.class);
571573 attributeMapper = (AttributeMapper)lookupMapperOfType(AttributeMapper.class);
572574 localConversionMapper = (LocalConversionMapper)lookupMapperOfType(LocalConversionMapper.class);
573575 }
00 /*
11 * Copyright (C) 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2015, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
120120 public boolean shouldSerializeMember(Class definedIn, String fieldName) {
121121 return true;
122122 }
123
124 public boolean isIgnoredElement(String name) {
125 return false;
126 }
123127
124128 public String lookupName(Class type) {
125129 return serializedClass(type);
0 /*
1 * Copyright (C) 2013, 2016 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 08. January 2016 by Joerg Schaible, factored out from FieldAliasingMapper.
9 */
10 package com.thoughtworks.xstream.mapper;
11
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.LinkedHashSet;
15 import java.util.Set;
16 import java.util.regex.Pattern;
17
18 import com.thoughtworks.xstream.core.util.FastField;
19
20 /**
21 * Mapper that allows an field of a specific class to be omitted entirely.
22 *
23 * @author Joerg Schaible
24 */
25 public class ElementIgnoringMapper extends MapperWrapper {
26
27 protected final Set fieldsToOmit = new HashSet();
28 protected final Set unknownElementsToIgnore = new LinkedHashSet();
29
30 public ElementIgnoringMapper(Mapper wrapped) {
31 super(wrapped);
32 }
33
34 public void addElementsToIgnore(final Pattern pattern) {
35 unknownElementsToIgnore.add(pattern);
36 }
37
38 public void omitField(Class definedIn, String fieldName) {
39 fieldsToOmit.add(key(definedIn, fieldName));
40 }
41
42 public boolean shouldSerializeMember(Class definedIn, String fieldName) {
43 if (fieldsToOmit.contains(key(definedIn, fieldName))) {
44 return false;
45 } else if (definedIn == Object.class && isIgnoredElement(fieldName)) {
46 return false;
47 }
48 return super.shouldSerializeMember(definedIn, fieldName);
49 }
50
51 public boolean isIgnoredElement(String name) {
52 if (!unknownElementsToIgnore.isEmpty()) {
53 for(Iterator iter = unknownElementsToIgnore.iterator(); iter.hasNext();) {
54 Pattern pattern = (Pattern)iter.next();
55 if (pattern.matcher(name).matches()) {
56 return true;
57 }
58 }
59 }
60 return super.isIgnoredElement(name);
61 }
62
63 private Object key(Class type, String name) {
64 return new FastField(type, name);
65 }
66 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2013, 2014 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2013, 2014, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1313 import com.thoughtworks.xstream.core.util.FastField;
1414
1515 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.LinkedHashSet;
1916 import java.util.Map;
20 import java.util.Set;
2117 import java.util.regex.Pattern;
2218
2319 /**
24 * Mapper that allows a field of a specific class to be replaced with a shorter alias, or omitted
25 * entirely.
20 * Mapper that allows a field of a specific class to be replaced with a shorter alias.
2621 *
2722 * @author Joe Walnes
2823 */
3025
3126 protected final Map fieldToAliasMap = new HashMap();
3227 protected final Map aliasToFieldMap = new HashMap();
33 protected final Set fieldsToOmit = new HashSet();
34 protected final Set unknownFieldsToIgnore = new LinkedHashSet();
28 private final ElementIgnoringMapper elementIgnoringMapper;
3529
3630 public FieldAliasingMapper(Mapper wrapped) {
3731 super(wrapped);
32 elementIgnoringMapper =
33 (ElementIgnoringMapper)lookupMapperOfType(ElementIgnoringMapper.class);
3834 }
3935
4036 public void addFieldAlias(String alias, Class type, String fieldName) {
4238 aliasToFieldMap.put(key(type, alias), fieldName);
4339 }
4440
41 /**
42 * @deprecated As of 1.4.9 use {@link ElementIgnoringMapper#addElementsToIgnore(Pattern)}.
43 */
4544 public void addFieldsToIgnore(final Pattern pattern) {
46 unknownFieldsToIgnore.add(pattern);
45 if (elementIgnoringMapper != null) {
46 elementIgnoringMapper.addElementsToIgnore(pattern);
47 }
48 }
49
50 /**
51 * @deprecated As of 1.4.9 use {@link ElementIgnoringMapper#omitField(Class, String)}.
52 */
53 public void omitField(Class definedIn, String fieldName) {
54 if (elementIgnoringMapper != null) {
55 elementIgnoringMapper.omitField(definedIn, fieldName);
56 }
4757 }
4858
4959 private Object key(Class type, String name) {
7787 }
7888 return member;
7989 }
80
81 public boolean shouldSerializeMember(Class definedIn, String fieldName) {
82 if (fieldsToOmit.contains(key(definedIn, fieldName))) {
83 return false;
84 } else if (definedIn == Object.class && !unknownFieldsToIgnore.isEmpty()) {
85 for(Iterator iter = unknownFieldsToIgnore.iterator(); iter.hasNext();) {
86 Pattern pattern = (Pattern)iter.next();
87 if (pattern.matcher(fieldName).matches()) {
88 return false;
89 }
90 }
91 }
92 return true;
93 }
94
95 public void omitField(Class definedIn, String fieldName) {
96 fieldsToOmit.add(key(definedIn, fieldName));
97 }
9890 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2009, 2011, 2012, 2013, 2014, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2009, 2011, 2012, 2013, 2014, 2015, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1111 package com.thoughtworks.xstream.mapper;
1212
1313 import com.thoughtworks.xstream.InitializationException;
14 import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
1415 import com.thoughtworks.xstream.core.util.Primitives;
1516
1617 import java.lang.reflect.Field;
2324
2425 public class ImplicitCollectionMapper extends MapperWrapper {
2526
26 public ImplicitCollectionMapper(Mapper wrapped) {
27 private ReflectionProvider reflectionProvider;
28
29 public ImplicitCollectionMapper(Mapper wrapped, ReflectionProvider reflectionProvider) {
2730 super(wrapped);
31 this.reflectionProvider = reflectionProvider;
2832 }
2933
3034 // { definedIn (Class) -> (ImplicitCollectionMapperForClass) }
3236
3337 private ImplicitCollectionMapperForClass getMapper(final Class declaredFor, final String fieldName) {
3438 Class definedIn = declaredFor;
39 Field field = fieldName != null ? reflectionProvider.getFieldOrNull(definedIn, fieldName) : null;
40 Class inheritanceStop = field != null ? field.getDeclaringClass() : null;
3541 while (definedIn != null) {
3642 ImplicitCollectionMapperForClass mapper = (ImplicitCollectionMapperForClass)classNameToMapper
3743 .get(definedIn);
3844 if (mapper != null) {
3945 return mapper;
40 } else {
41 if (fieldName != null) {
42 try {
43 // do not continue search for a hidden field
44 final Field field = definedIn.getDeclaredField(fieldName);
45 if (field != null && !Modifier.isStatic(field.getModifiers())) {
46 return null;
47 }
48 } catch (final SecurityException e) {
49 throw new InitializationException("Access denied for field with implicit collection", e);
50 } catch (final NoSuchFieldException e) {
51 // OK, we can continue the search in the class hierarchy
52 }
53 }
46 }
47 if (definedIn == inheritanceStop) {
48 break;
5449 }
5550 definedIn = definedIn.getSuperclass();
5651 }
00 /*
11 * Copyright (C) 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2015, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
101101 */
102102 boolean shouldSerializeMember(Class definedIn, String fieldName);
103103
104 /**
105 * Whether this name can be ignored.
106 *
107 * @since 1.4.9
108 */
109 boolean isIgnoredElement(String name);
110
104111 interface ImplicitCollectionMapping {
105112 String getFieldName();
106113 String getItemFieldName();
00 /*
11 * Copyright (C) 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2015, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1010 */
1111 package com.thoughtworks.xstream.mapper;
1212
13 import java.lang.reflect.Method;
14 import java.util.HashMap;
15 import java.util.Map;
16
1317 import com.thoughtworks.xstream.converters.Converter;
1418 import com.thoughtworks.xstream.converters.SingleValueConverter;
1519
20
1621 public abstract class MapperWrapper implements Mapper {
17
1822 private final Mapper wrapped;
23 private final Mapper aliasForAttributeMapper;
24 private final Mapper aliasForSystemAttributeMapper;
25 private final Mapper attributeForAliasMapper;
26 private final Mapper defaultImplementationOfMapper;
27 private final Mapper getConverterFromAttributeMapper;
28 private final Mapper getConverterFromItemTypeMapper;
29 private final Mapper getFieldNameForItemTypeAndNameMapper;
30 private final Mapper getImplicitCollectionDefForFieldNameMapper;
31 private final Mapper getItemTypeForItemFieldNameMapper;
32 private final Mapper getLocalConverterMapper;
33 private final Mapper isIgnoredElementMapper;
34 private final Mapper isImmutableValueTypeMapper;
35 private final Mapper isReferenceableMapper;
36 private final Mapper realClassMapper;
37 private final Mapper realMemberMapper;
38 private final Mapper serializedClassMapper;
39 private final Mapper serializedMemberMapper;
40 private final Mapper shouldSerializeMemberMapper;
1941
2042 public MapperWrapper(Mapper wrapped) {
2143 this.wrapped = wrapped;
44
45 if (wrapped instanceof MapperWrapper) {
46 final MapperWrapper wrapper = (MapperWrapper)wrapped;
47 final Map wrapperMap = new HashMap();
48 wrapperMap.put("aliasForAttribute", wrapper.aliasForAttributeMapper);
49 wrapperMap.put("aliasForSystemAttribute", wrapper.aliasForSystemAttributeMapper);
50 wrapperMap.put("attributeForAlias", wrapper.attributeForAliasMapper);
51 wrapperMap.put("defaultImplementationOf", wrapper.defaultImplementationOfMapper);
52 wrapperMap.put("getConverterFromAttribute", wrapper.getConverterFromAttributeMapper);
53 wrapperMap.put("getConverterFromItemType", wrapper.getConverterFromItemTypeMapper);
54 wrapperMap.put("getFieldNameForItemTypeAndName", wrapper.getFieldNameForItemTypeAndNameMapper);
55 wrapperMap.put("getImplicitCollectionDefForFieldName", wrapper.getImplicitCollectionDefForFieldNameMapper);
56 wrapperMap.put("getItemTypeForItemFieldName", wrapper.getItemTypeForItemFieldNameMapper);
57 wrapperMap.put("getLocalConverter", wrapper.getLocalConverterMapper);
58 wrapperMap.put("isIgnoredElement", wrapper.isIgnoredElementMapper);
59 wrapperMap.put("isImmutableValueType", wrapper.isImmutableValueTypeMapper);
60 wrapperMap.put("isReferenceable", wrapper.isReferenceableMapper);
61 wrapperMap.put("realClass", wrapper.realClassMapper);
62 wrapperMap.put("realMember", wrapper.realMemberMapper);
63 wrapperMap.put("serializedClass", wrapper.serializedClassMapper);
64 wrapperMap.put("serializedMember", wrapper.serializedMemberMapper);
65 wrapperMap.put("shouldSerializeMember", wrapper.shouldSerializeMemberMapper);
66
67 final Method[] methods = wrapped.getClass().getMethods();
68 for (int i = 0; i < methods.length; ++i) {
69 final Method method = methods[i];
70 if (method.getDeclaringClass() != MapperWrapper.class) {
71 final String name = method.getName();
72 if (wrapperMap.containsKey(name)) {
73 wrapperMap.put(name, wrapped);
74 }
75 }
76 }
77
78 aliasForAttributeMapper = (Mapper)wrapperMap.get("aliasForAttribute");
79 aliasForSystemAttributeMapper = (Mapper)wrapperMap.get("aliasForSystemAttribute");
80 attributeForAliasMapper = (Mapper)wrapperMap.get("attributeForAlias");
81 defaultImplementationOfMapper = (Mapper)wrapperMap.get("defaultImplementationOf");
82 getConverterFromAttributeMapper = (Mapper)wrapperMap.get("getConverterFromAttribute");
83 getConverterFromItemTypeMapper = (Mapper)wrapperMap.get("getConverterFromItemType");
84 getFieldNameForItemTypeAndNameMapper = (Mapper)wrapperMap.get("getFieldNameForItemTypeAndName");
85 getImplicitCollectionDefForFieldNameMapper = (Mapper)wrapperMap.get("getImplicitCollectionDefForFieldName");
86 getItemTypeForItemFieldNameMapper = (Mapper)wrapperMap.get("getItemTypeForItemFieldName");
87 getLocalConverterMapper = (Mapper)wrapperMap.get("getLocalConverter");
88 isIgnoredElementMapper = (Mapper)wrapperMap.get("isIgnoredElement");
89 isImmutableValueTypeMapper = (Mapper)wrapperMap.get("isImmutableValueType");
90 isReferenceableMapper = (Mapper)wrapperMap.get("isReferenceable");
91 realClassMapper = (Mapper)wrapperMap.get("realClass");
92 realMemberMapper = (Mapper)wrapperMap.get("realMember");
93 serializedClassMapper = (Mapper)wrapperMap.get("serializedClass");
94 serializedMemberMapper = (Mapper)wrapperMap.get("serializedMember");
95 shouldSerializeMemberMapper = (Mapper)wrapperMap.get("shouldSerializeMember");
96 } else {
97 aliasForAttributeMapper = wrapped;
98 aliasForSystemAttributeMapper = wrapped;
99 attributeForAliasMapper = wrapped;
100 defaultImplementationOfMapper = wrapped;
101 getConverterFromAttributeMapper = wrapped;
102 getConverterFromItemTypeMapper = wrapped;
103 getFieldNameForItemTypeAndNameMapper = wrapped;
104 getImplicitCollectionDefForFieldNameMapper = wrapped;
105 getItemTypeForItemFieldNameMapper = wrapped;
106 getLocalConverterMapper = wrapped;
107 isIgnoredElementMapper = wrapped;
108 isImmutableValueTypeMapper = wrapped;
109 isReferenceableMapper = wrapped;
110 realClassMapper = wrapped;
111 realMemberMapper = wrapped;
112 serializedClassMapper = wrapped;
113 serializedMemberMapper = wrapped;
114 shouldSerializeMemberMapper = wrapped;
115 }
116
22117 }
23118
24119 public String serializedClass(Class type) {
25 return wrapped.serializedClass(type);
120 return serializedClassMapper.serializedClass(type);
26121 }
27122
28123 public Class realClass(String elementName) {
29 return wrapped.realClass(elementName);
124 return realClassMapper.realClass(elementName);
30125 }
31126
32127 public String serializedMember(Class type, String memberName) {
33 return wrapped.serializedMember(type, memberName);
128 return serializedMemberMapper.serializedMember(type, memberName);
34129 }
35130
36131 public String realMember(Class type, String serialized) {
37 return wrapped.realMember(type, serialized);
132 return realMemberMapper.realMember(type, serialized);
38133 }
39134
40135 public boolean isImmutableValueType(Class type) {
41 return wrapped.isImmutableValueType(type);
136 return isImmutableValueTypeMapper.isImmutableValueType(type);
42137 }
43138
44139 public boolean isReferenceable(Class type) {
45 return wrapped.isReferenceable(type);
140 return isReferenceableMapper.isReferenceable(type);
46141 }
47142
48143 public Class defaultImplementationOf(Class type) {
49 return wrapped.defaultImplementationOf(type);
144 return defaultImplementationOfMapper.defaultImplementationOf(type);
50145 }
51146
52147 public String aliasForAttribute(String attribute) {
53 return wrapped.aliasForAttribute(attribute);
148 return aliasForAttributeMapper.aliasForAttribute(attribute);
54149 }
55150
56151 public String attributeForAlias(String alias) {
57 return wrapped.attributeForAlias(alias);
152 return attributeForAliasMapper.attributeForAlias(alias);
58153 }
59154
60155 public String aliasForSystemAttribute(String attribute) {
61 return wrapped.aliasForSystemAttribute(attribute);
156 return aliasForSystemAttributeMapper.aliasForSystemAttribute(attribute);
62157 }
63158
64159 public String getFieldNameForItemTypeAndName(Class definedIn, Class itemType, String itemFieldName) {
65 return wrapped.getFieldNameForItemTypeAndName(definedIn, itemType, itemFieldName);
160 return getFieldNameForItemTypeAndNameMapper.getFieldNameForItemTypeAndName(definedIn, itemType, itemFieldName);
66161 }
67162
68163 public Class getItemTypeForItemFieldName(Class definedIn, String itemFieldName) {
69 return wrapped.getItemTypeForItemFieldName(definedIn, itemFieldName);
164 return getItemTypeForItemFieldNameMapper.getItemTypeForItemFieldName(definedIn, itemFieldName);
70165 }
71166
72167 public ImplicitCollectionMapping getImplicitCollectionDefForFieldName(Class itemType, String fieldName) {
73 return wrapped.getImplicitCollectionDefForFieldName(itemType, fieldName);
168 return getImplicitCollectionDefForFieldNameMapper.getImplicitCollectionDefForFieldName(itemType, fieldName);
74169 }
75170
76171 public boolean shouldSerializeMember(Class definedIn, String fieldName) {
77 return wrapped.shouldSerializeMember(definedIn, fieldName);
172 return shouldSerializeMemberMapper.shouldSerializeMember(definedIn, fieldName);
173 }
174
175 public boolean isIgnoredElement(String name) {
176 return isIgnoredElementMapper.isIgnoredElement(name);
78177 }
79178
80179 /**
81180 * @deprecated As of 1.3, use {@link #getConverterFromItemType(String, Class, Class)}
82181 */
83182 public SingleValueConverter getConverterFromItemType(String fieldName, Class type) {
84 return wrapped.getConverterFromItemType(fieldName, type);
183 return getConverterFromItemTypeMapper.getConverterFromItemType(fieldName, type);
85184 }
86185
87186 /**
88187 * @deprecated As of 1.3, use {@link #getConverterFromItemType(String, Class, Class)}
89188 */
90189 public SingleValueConverter getConverterFromItemType(Class type) {
91 return wrapped.getConverterFromItemType(type);
190 return getConverterFromItemTypeMapper.getConverterFromItemType(type);
92191 }
93192
94193 /**
95194 * @deprecated As of 1.3, use {@link #getConverterFromAttribute(Class, String, Class)}
96195 */
97196 public SingleValueConverter getConverterFromAttribute(String name) {
98 return wrapped.getConverterFromAttribute(name);
197 return getConverterFromAttributeMapper.getConverterFromAttribute(name);
99198 }
100199
101200 public Converter getLocalConverter(Class definedIn, String fieldName) {
102 return wrapped.getLocalConverter(definedIn, fieldName);
201 return getLocalConverterMapper.getLocalConverter(definedIn, fieldName);
103202 }
104203
105204 public Mapper lookupMapperOfType(Class type) {
106205 return type.isAssignableFrom(getClass()) ? this : wrapped.lookupMapperOfType(type);
107206 }
108
207
109208 public SingleValueConverter getConverterFromItemType(String fieldName, Class type, Class definedIn) {
110 return wrapped.getConverterFromItemType(fieldName, type, definedIn);
111 }
112
113 /**
114 * @deprecated As of 1.3, use combination of {@link #serializedMember(Class, String)} and {@link #getConverterFromItemType(String, Class, Class)}
209 return getConverterFromItemTypeMapper.getConverterFromItemType(fieldName, type, definedIn);
210 }
211
212 /**
213 * @deprecated As of 1.3, use combination of {@link #serializedMember(Class, String)} and
214 * {@link #getConverterFromItemType(String, Class, Class)}
115215 */
116216 public String aliasForAttribute(Class definedIn, String fieldName) {
117 return wrapped.aliasForAttribute(definedIn, fieldName);
118 }
119
120 /**
121 * @deprecated As of 1.3, use combination of {@link #realMember(Class, String)} and {@link #getConverterFromItemType(String, Class, Class)}
217 return aliasForAttributeMapper.aliasForAttribute(definedIn, fieldName);
218 }
219
220 /**
221 * @deprecated As of 1.3, use combination of {@link #realMember(Class, String)} and
222 * {@link #getConverterFromItemType(String, Class, Class)}
122223 */
123224 public String attributeForAlias(Class definedIn, String alias) {
124 return wrapped.attributeForAlias(definedIn, alias);
125 }
126
127 /**
128 * @deprecated As of 1.3.1, use {@link #getConverterFromAttribute(Class, String, Class)}
225 return attributeForAliasMapper.attributeForAlias(definedIn, alias);
226 }
227
228 /**
229 * @deprecated As of 1.3.1, use {@link #getConverterFromAttribute(Class, String, Class)}
129230 */
130231 public SingleValueConverter getConverterFromAttribute(Class type, String attribute) {
131 return wrapped.getConverterFromAttribute(type, attribute);
132 }
133
232 return getConverterFromAttributeMapper.getConverterFromAttribute(type, attribute);
233 }
234
134235 public SingleValueConverter getConverterFromAttribute(Class definedIn, String attribute, Class type) {
135 return wrapped.getConverterFromAttribute(definedIn, attribute, type);
236 return getConverterFromAttributeMapper.getConverterFromAttribute(definedIn, attribute, type);
136237 }
137238
138239 }
00 /*
1 * Copyright (C) 2014 XStream Committers.
1 * Copyright (C) 2014, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * Created on 09. January 2014 by Joerg Schaible
77
88 import com.thoughtworks.xstream.core.util.Primitives;
99
10
1011 /**
11 * Permission for any primitive type and its boxed counterpart (incl. void).
12 * Permission for any primitive type and its boxed counterpart (excl. void).
1213 *
1314 * @author J&ouml;rg Schaible
1415 * @since 1.4.7
2021 public static final TypePermission PRIMITIVES = new PrimitiveTypePermission();
2122
2223 public boolean allows(Class type) {
23 return type != null && type.isPrimitive() || Primitives.isBoxed(type);
24 return type != null && type != void.class && type != Void.class && type.isPrimitive()
25 || Primitives.isBoxed(type);
2426 }
2527
2628 public int hashCode() {
00 /*
11 * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
269269 properties.setProperty("1", "I");
270270 properties.setProperty("3", "III");
271271
272 assertBothWays(properties,
272 assertBothWaysNormalized(properties,
273273 "<properties>\n" +
274274 " <property name=\"3\" value=\"III\"/>\n" +
275275 " <property name=\"1\" value=\"I\"/>\n" +
277277 " <property name=\"2\" value=\"two\"/>\n" +
278278 " <property name=\"1\" value=\"one\"/>\n" +
279279 " </defaults>\n" +
280 "</properties>");
280 "</properties>", "properties", "property", "@name");
281281 }
282282
283283 public void testUnmodifiableList() {
00 /*
1 * Copyright (C) 2006, 2007 XStream Committers.
1 * Copyright (C) 2006, 2007, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
99 */
1010 package com.thoughtworks.acceptance;
1111
12 import java.util.ArrayList;
1213 import java.util.Arrays;
1314 import java.util.HashMap;
1415 import java.util.List;
2728 xstream.alias("thing", WithNamedList.class);
2829 xstream.addImplicitCollection(WithNamedList.class, "things");
2930
30 final List reference = Arrays.asList(new String[]{"A", "B", "C", "D"});
31 final List reference = new ArrayList(Arrays.asList(new String[]{"A", "B", "C", "D"}));
3132 final WithNamedList[] namedLists = new WithNamedList[5];
3233 for (int i = 0; i < namedLists.length; ++i) {
3334 namedLists[i] = new WithNamedList("Name " + (i + 1));
4445 }
4546 };
4647
47 final Object object = Arrays.asList(namedLists);
48 final Object object = new ArrayList(Arrays.asList(namedLists));
4849 final String xml = xstream.toXML(object);
4950 final int[] counter = new int[1];
5051 counter[0] = 0;
00 /*
1 * Copyright (C) 2012, 2015 XStream Committers.
1 * Copyright (C) 2012, 2015, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
1212 import java.util.Map;
1313 import java.util.concurrent.ConcurrentHashMap;
1414
15 import com.thoughtworks.xstream.converters.collections.MapConverter;
1516 import com.thoughtworks.xstream.core.JVM;
1617
1718
4142 public void testDerivedConcurrentHashMap() {
4243 if (JVM.is18()) {
4344 xstream.alias("derived-map", DerivedConcurrentHashMap.class);
45 xstream.registerConverter(new MapConverter(xstream.getMapper(), DerivedConcurrentHashMap.class));
4446
4547 Map<Object, Object> map = new DerivedConcurrentHashMap();
4648 map.put("test", "JUnit");
4749
4850 String xml = ""
49 + "<derived-map serialization=\"custom\">\n"
50 + " <unserializable-parents/>\n"
51 + " <concurrent-hash-map>\n"
52 + " <default>\n"
53 + " <segmentMask>15</segmentMask>\n"
54 + " </default>\n"
51 + "<derived-map>\n"
52 + " <entry>\n"
5553 + " <string>test</string>\n"
5654 + " <string>JUnit</string>\n"
57 + " <null/>\n"
58 + " <null/>\n"
59 + " </concurrent-hash-map>\n"
55 + " </entry>\n"
6056 + "</derived-map>";
6157
6258 assertBothWays(map, xml);
00 /*
11 * Copyright (C) 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
66 * style license a copy of which has been included with this distribution in
77 * the LICENSE.txt file.
8 *
8 *
99 * Created on 25. June 2006 by Guilherme Silveira
1010 */
1111 package com.thoughtworks.acceptance;
1818
1919 import javax.xml.stream.XMLInputFactory;
2020
21 import junit.framework.Assert;
22 import junit.framework.Test;
23 import junit.framework.TestCase;
24 import junit.framework.TestSuite;
21 import org.apache.commons.lang.SystemUtils;
2522
2623 import com.bea.xml.stream.MXParserFactory;
2724 import com.thoughtworks.acceptance.objects.StandardObject;
2825 import com.thoughtworks.xstream.XStream;
26 import com.thoughtworks.xstream.core.JVM;
2927 import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
28 import com.thoughtworks.xstream.io.xml.BEAStaxDriver;
3029 import com.thoughtworks.xstream.io.xml.Dom4JDriver;
3130 import com.thoughtworks.xstream.io.xml.DomDriver;
3231 import com.thoughtworks.xstream.io.xml.JDomDriver;
32 import com.thoughtworks.xstream.io.xml.KXml2DomDriver;
33 import com.thoughtworks.xstream.io.xml.KXml2Driver;
3334 import com.thoughtworks.xstream.io.xml.StaxDriver;
35 import com.thoughtworks.xstream.io.xml.WstxDriver;
3436 import com.thoughtworks.xstream.io.xml.XomDriver;
3537 import com.thoughtworks.xstream.io.xml.XppDomDriver;
3638 import com.thoughtworks.xstream.io.xml.XppDriver;
39
40 import junit.framework.Assert;
41 import junit.framework.AssertionFailedError;
42 import junit.framework.Test;
43 import junit.framework.TestCase;
44 import junit.framework.TestSuite;
3745
3846
3947 /**
5260 addDriverTest(new Dom4JDriver());
5361 addDriverTest(new DomDriver());
5462 addDriverTest(new JDomDriver());
63 if (JVM.is15()) {
64 final Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.xml.JDom2Driver");
65 try {
66 addDriverTest((HierarchicalStreamDriver)driverType.newInstance());
67 } catch (final InstantiationException e) {
68 throw new AssertionFailedError("Cannot instantiate " + driverType.getName());
69 } catch (final IllegalAccessException e) {
70 throw new AssertionFailedError("Cannot access default constructor of " + driverType.getName());
71 }
72 }
5573 addDriverTest(new StaxDriver());
74 if (!SystemUtils.IS_OS_WINDOWS) { // see comment below for Windows
75 if (JVM.is16()) {
76 final Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.xml.StandardStaxDriver");
77 try {
78 addDriverTest((HierarchicalStreamDriver)driverType.newInstance());
79 } catch (final InstantiationException e) {
80 throw new AssertionFailedError("Cannot instantiate " + driverType.getName());
81 } catch (final IllegalAccessException e) {
82 throw new AssertionFailedError("Cannot access default constructor of " + driverType.getName());
83 }
84 }
85 addDriverTest(new BEAStaxDriver());
86 addDriverTest(new WstxDriver());
87 }
88 addDriverTest(new KXml2DomDriver());
89 addDriverTest(new KXml2Driver());
5690 addDriverTest(new XppDomDriver());
5791 addDriverTest(new XppDriver());
5892 addDriverTest(new XomDriver());
5993 }
6094
61 private void test(HierarchicalStreamDriver driver, String encoding) throws IOException {
62 String headerLine = encoding != null
63 ? ("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n")
64 : "";
65 String xmlData = headerLine // force code format
95 private void test(final HierarchicalStreamDriver driver, final String encoding) throws IOException {
96 final String headerLine = encoding != null ? "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n" : "";
97 final String xmlData = headerLine // force code format
6698 + "<test>\n"
6799 + " <data>J\u00f6rg</data>\n"
68100 + "</test>";
69101
70 XStream xstream = new XStream(driver);
102 final XStream xstream = new XStream(driver);
103 XStream.setupDefaultSecurity(xstream);
104 xstream.allowTypesByWildcard(new String[] {getClass().getName()+"$*"});
71105 xstream.alias("test", TestObject.class);
72 TestObject obj = new TestObject();
106 final TestObject obj = new TestObject();
73107 obj.data = "J\u00f6rg";
74108
75 ByteArrayOutputStream bos = new ByteArrayOutputStream();
76 OutputStreamWriter writer = encoding != null
109 final ByteArrayOutputStream bos = new ByteArrayOutputStream();
110 final OutputStreamWriter writer = encoding != null
77111 ? new OutputStreamWriter(bos, encoding)
78112 : new OutputStreamWriter(bos);
79113 xstream.toXML(obj, writer);
80114 writer.close();
81115
82 String generated = encoding != null ? bos.toString(encoding) : bos.toString();
116 final String generated = encoding != null ? bos.toString(encoding) : bos.toString();
83117 Assert.assertTrue("'" + obj.data + "' was not found", generated.indexOf(obj.data) > 0);
84118
85 Object restored = xstream.fromXML(new ByteArrayInputStream(encoding != null ? xmlData
86 .getBytes(encoding) : xmlData.getBytes()));
119 final Object restored = xstream.fromXML(new ByteArrayInputStream(encoding != null
120 ? xmlData.getBytes(encoding)
121 : xmlData.getBytes()));
87122 Assert.assertEquals(obj, restored);
88123 }
89124
90125 private void addDriverTest(final HierarchicalStreamDriver driver) {
91 String testName = getShortName(driver);
126 final String testName = getShortName(driver);
92127 final String allEncodingTests = System.getProperty("xstream.test.encoding.all");
93128 if ("true".equals(allEncodingTests)) {
94129 // Native encoding normally fails on most systems!!
106141 try {
107142 // Use BEA reference implementation for StAX
108143 // (Woodstox will fail on Windows because of unknown system encoding)
109 System.setProperty(
110 XMLInputFactory.class.getName(), MXParserFactory.class.getName());
144 System.setProperty(XMLInputFactory.class.getName(), MXParserFactory.class.getName());
111145 test(driver, systemEncoding);
112146 } finally {
113147 System.setProperties(systemProperties);
127161 });
128162 }
129163
130 private String getShortName(HierarchicalStreamDriver driver) {
164 private String getShortName(final HierarchicalStreamDriver driver) {
131165 String result = driver.getClass().getName();
132166 result = result.substring(result.lastIndexOf('.') + 1);
133167 return result;
99 */
1010 package com.thoughtworks.acceptance;
1111
12 import java.io.File;
1213 import java.io.IOException;
1314 import java.net.URI;
1415 import java.nio.file.FileSystem;
3738 assertBothWays(Paths.get("../a/relative/path"), "<path>../a/relative/path</path>");
3839 assertBothWays(Paths.get("/an/absolute/path"), "<path>/an/absolute/path</path>");
3940
40 final String absolutePathName = Paths.get("target").toAbsolutePath().toString();
41 final URI uri = URI.create("file://" + absolutePathName);
41 String absolutePathName = Paths.get("target").toAbsolutePath().toString();
42 if (File.separatorChar != '/') {
43 absolutePathName = absolutePathName.replace(File.separatorChar, '/');
44 }
45 final URI uri = URI.create("file:" + absolutePathName);
4246 assertBothWays(Paths.get(uri), "<path>" + absolutePathName + "</path>");
47 }
48
49 public void testPathWithSpecialCharacters() {
50 assertBothWays(Paths.get("with space"), "<path>with space</path>");
51 assertBothWays(Paths.get("with+plus"), "<path>with+plus</path>");
52 assertBothWays(Paths.get("with&ampersand"), "<path>with&amp;ampersand</path>");
4353 }
4454
4555 public void testPathOfNonDefaultFileSystem() throws IOException {
4656 final Map<String, String> env = new HashMap<String, String>();
4757 env.put("create", "true");
48 final URI uri = URI.create("jar:file://"
49 + Paths.get("target/lib/proxytoys-0.2.1.jar").toAbsolutePath().toString());
58 final URI uri = URI.create("jar:"
59 + Paths.get("target/lib/proxytoys-0.2.1.jar").toAbsolutePath().toUri().toString());
5060
5161 FileSystem zipfs = null;
5262 try {
6070 }
6171 }
6272 }
73
74 public void testPathIsImmutable() {
75 Path[] array = new Path[2];
76 array[0] = array[1] = Paths.get("same");
77 assertBothWays(array, "" //
78 + "<path-array>\n" //
79 + " <path>same</path>\n" //
80 + " <path>same</path>\n" //
81 + "</path-array>");
82 }
6383 }
00 /*
11 * Copyright (C) 2003, 2004, 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2012, 2014 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2012, 2014, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1010 */
1111 package com.thoughtworks.acceptance;
1212
13 import com.thoughtworks.xstream.converters.extended.SqlTimestampConverter;
1314 import com.thoughtworks.xstream.core.JVM;
1415 import com.thoughtworks.xstream.testutil.TimeZoneChanger;
1516
2223 import java.sql.Time;
2324 import java.sql.Timestamp;
2425 import java.util.Locale;
26 import java.util.TimeZone;
2527
2628 public class ExtendedTypesTest extends AbstractAcceptanceTest {
2729
5961 }
6062
6163 public void testSqlTimestamp() {
64 assertBothWays(new Timestamp(1000),
65 "<sql-timestamp>1970-01-01 00:00:01</sql-timestamp>");
66 }
67
68 public void testSqlTimestampWithFraction() {
6269 Timestamp timestamp = new Timestamp(1234);
6370 timestamp.setNanos(78900);
6471 assertBothWays(timestamp,
6572 "<sql-timestamp>1970-01-01 00:00:01.0000789</sql-timestamp>");
73 }
74
75 public void testSqlTimestampWithLocalTimeZone() {
76 xstream.registerConverter(new SqlTimestampConverter(TimeZone.getDefault()));
77 Timestamp timestamp = new Timestamp(1234);
78 timestamp.setNanos(78900);
79 assertBothWays(timestamp,
80 "<sql-timestamp>"+timestamp.toString()+"</sql-timestamp>");
6681 }
6782
6883 public void testSqlTime() {
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2010, 2012, 2013, 2014 XStream Committers.
2 * Copyright (C) 2006, 2007, 2010, 2012, 2013, 2014, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1515 import com.thoughtworks.xstream.converters.ConversionException;
1616 import com.thoughtworks.xstream.mapper.Mapper;
1717 import com.thoughtworks.xstream.mapper.MapperWrapper;
18 import com.thoughtworks.xstream.security.NoTypePermission;
1819
1920
2021 public class OmitFieldsTest extends AbstractAcceptanceTest {
162163 return new OmitFieldsWithMyPrefixMapper(next);
163164 }
164165 };
166 xstream.addPermission(NoTypePermission.NONE); // clear out defaults
165167
166168 xstream.allowTypes(new Class[]{AnotherThing.class});
167169 xstream.alias("thing", AnotherThing.class);
00 /*
1 * Copyright (C) 2006, 2007, 2009, 2010, 2013, 2015 XStream Committers.
1 * Copyright (C) 2006, 2007, 2009, 2010, 2013, 2015, 2016, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
179179 sm.addPermission(source, new PropertyPermission("jdk.util.TimeZone.allowSetDefault", "read"));
180180 sm.addPermission(source, new PropertyPermission("jdk.xml.elementAttributeLimit", "read"));
181181 sm.addPermission(source, new PropertyPermission("jdk.xml.entityExpansionLimit", "read"));
182 sm.addPermission(source, new PropertyPermission("jdk.xml.entityReplacementLimit", "read"));
182183 sm.addPermission(source, new PropertyPermission("jdk.xml.maxElementDepth", "read"));
183184 sm.addPermission(source, new PropertyPermission("jdk.xml.maxGeneralEntitySizeLimit", "read"));
184185 sm.addPermission(source, new PropertyPermission("jdk.xml.maxParameterEntitySizeLimit", "read"));
203204 }
204205
205206 private void assertBothWays() {
206
207 XStream.setupDefaultSecurity(xstream);
208 xstream.allowTypesByWildcard(new String[] {"com.thoughtworks.acceptance.objects.*"});
207209 xstream.alias("software", Software.class);
208210
209211 final Software sw = new Software("jw", "xstr");
00 /*
1 * Copyright (C) 2013, 2014 XStream Committers.
1 * Copyright (C) 2013, 2014, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
1212 import java.beans.EventHandler;
1313
1414 import com.thoughtworks.xstream.XStreamException;
15 import com.thoughtworks.xstream.converters.ConversionException;
1516 import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
17 import com.thoughtworks.xstream.security.ForbiddenClassException;
1618 import com.thoughtworks.xstream.security.ProxyTypePermission;
19
1720
1821 /**
1922 * @author J&ouml;rg Schaible
2629 super.setUp();
2730 BUFFER.setLength(0);
2831 xstream.alias("runnable", Runnable.class);
29 xstream.allowTypes(new Class[]{EventHandler.class});
3032 xstream.allowTypeHierarchy(Runnable.class);
3133 xstream.addPermission(ProxyTypePermission.PROXIES);
3234 }
6466 + " </dynamic-proxy>\n"
6567 + "</string>";
6668
69 xstream.allowTypes(new Class[]{EventHandler.class});
6770 xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream
6871 .getReflectionProvider(), EventHandler.class));
6972
7982 BUFFER.append("Executed!");
8083 }
8184 }
85
86 public void testDeniedInstanceOfVoid() {
87 try {
88 xstream.fromXML("<void/>");
89 fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
90 } catch (final ForbiddenClassException e) {
91 // OK
92 }
93 }
94
95 public void testAllowedInstanceOfVoid() {
96 xstream.allowTypes(new Class[] { void.class, Void.class });
97 try {
98 xstream.fromXML("<void/>");
99 fail("Thrown " + ConversionException.class.getName() + " expected");
100 } catch (final ConversionException e) {
101 assertEquals("void", e.get("required-type"));
102 }
103 }
82104 }
0 /*
1 * Copyright (C) 2017 XStream Committers.
2 * All rights reserved.
3 *
4 * The software in this package is published under the terms of the BSD
5 * style license a copy of which has been included with this distribution in
6 * the LICENSE.txt file.
7 *
8 * Created on 13. January 2017 by Matej Cimbora
9 */
10 package com.thoughtworks.acceptance;
11
12 import java.time.Clock;
13 import java.time.DayOfWeek;
14 import java.time.Duration;
15 import java.time.Instant;
16 import java.time.LocalDate;
17 import java.time.LocalDateTime;
18 import java.time.LocalTime;
19 import java.time.Month;
20 import java.time.MonthDay;
21 import java.time.OffsetDateTime;
22 import java.time.OffsetTime;
23 import java.time.Period;
24 import java.time.Year;
25 import java.time.YearMonth;
26 import java.time.ZoneId;
27 import java.time.ZoneOffset;
28 import java.time.ZonedDateTime;
29 import java.time.chrono.Chronology;
30 import java.time.chrono.HijrahChronology;
31 import java.time.chrono.HijrahDate;
32 import java.time.chrono.HijrahEra;
33 import java.time.chrono.IsoChronology;
34 import java.time.chrono.JapaneseChronology;
35 import java.time.chrono.JapaneseDate;
36 import java.time.chrono.JapaneseEra;
37 import java.time.chrono.MinguoChronology;
38 import java.time.chrono.MinguoDate;
39 import java.time.chrono.MinguoEra;
40 import java.time.chrono.ThaiBuddhistChronology;
41 import java.time.chrono.ThaiBuddhistDate;
42 import java.time.chrono.ThaiBuddhistEra;
43 import java.time.temporal.ChronoField;
44 import java.time.temporal.ChronoUnit;
45 import java.time.temporal.IsoFields;
46 import java.time.temporal.JulianFields;
47 import java.time.temporal.TemporalField;
48 import java.time.temporal.ValueRange;
49 import java.time.temporal.WeekFields;
50
51 import com.thoughtworks.xstream.XStream;
52 import com.thoughtworks.xstream.converters.ConversionException;
53
54
55 /**
56 * Test types of java.time.* package.
57 *
58 * @author Matej Cimbora
59 * @author J&ouml;rg Schaible
60 */
61 public class Time18TypesTest extends AbstractAcceptanceTest {
62
63 @Override
64 protected void setupSecurity(XStream xstream) {
65 super.setupSecurity(xstream);
66 xstream.allowTypesByWildcard(new String[]{ "java.time.**" });
67 }
68
69 public void testFixedClock() {
70 assertBothWays(Clock.fixed(Instant.parse("2017-02-15T18:49:25Z"), ZoneOffset.of("Z")), "" //
71 + "<fixed-clock>\n" //
72 + " <instant>2017-02-15T18:49:25Z</instant>\n" //
73 + " <zone>Z</zone>\n" //
74 + "</fixed-clock>");
75 }
76
77 public void testOffsetClock() {
78 assertBothWays(Clock.offset(Clock.systemUTC(), Duration.ofHours(1)), "" //
79 + "<offset-clock>\n" //
80 + " <baseClock class=\"system-clock\">\n" //
81 + " <zone>Z</zone>\n" //
82 + " </baseClock>\n" //
83 + " <offset>PT1H</offset>\n" //
84 + "</offset-clock>");
85 }
86
87 public void testSystemClock() {
88 assertBothWays(Clock.systemUTC(), "" //
89 + "<system-clock>\n" //
90 + " <zone>Z</zone>\n" //
91 + "</system-clock>");
92 assertBothWays(Clock.system(ZoneId.of("Europe/Berlin")), "" //
93 + "<system-clock>\n" //
94 + " <zone>Europe/Berlin</zone>\n" //
95 + "</system-clock>");
96 }
97
98 public void testTickClock() {
99 assertBothWays(Clock.tick(Clock.systemUTC(), Duration.ofMillis(42)), "" //
100 + "<tick-clock>\n" //
101 + " <baseClock class=\"system-clock\">\n" //
102 + " <zone>Z</zone>\n" //
103 + " </baseClock>\n" //
104 + " <tickNanos>42000000</tickNanos>\n" //
105 + "</tick-clock>");
106 }
107
108 public void testDuration() {
109 assertBothWays(Duration.ofDays(1000), "<duration>PT24000H</duration>");
110 assertBothWays(Duration.ofHours(50), "<duration>PT50H</duration>");
111 assertBothWays(Duration.ofMinutes(77), "<duration>PT1H17M</duration>");
112 assertBothWays(Duration.ofSeconds(55), "<duration>PT55S</duration>");
113 assertBothWays(Duration.ofMillis(4444), "<duration>PT4.444S</duration>");
114 assertBothWays(Duration.ofNanos(123456789), "<duration>PT0.123456789S</duration>");
115 assertBothWays(Duration.ofNanos(100000000), "<duration>PT0.1S</duration>");
116 assertBothWays(Duration.ofNanos(9), "<duration>PT0.000000009S</duration>");
117 assertBothWays(Duration.ofNanos(6333123456789L), "<duration>PT1H45M33.123456789S</duration>");
118 assertBothWays(Duration.ofSeconds(-3), "<duration>PT-3S</duration>");
119 assertBothWays(Duration.ofSeconds(-30001), "<duration>PT-8H-20M-1S</duration>");
120 }
121
122 public void testDurationConversionExceptionContainsInvalidValue() {
123 try {
124 xstream.fromXML("<duration>PT77XS</duration>");
125 fail("Thrown " + ConversionException.class.getName() + " expected");
126 } catch (final ConversionException e) {
127 assertEquals(Duration.class.getName(), e.get("class"));
128 assertEquals("PT77XS", e.get("value"));
129 }
130 }
131
132 public void testDurationWithOldFormat() {
133 assertEquals(Duration.ofSeconds(7777), xstream.fromXML("" //
134 + "<java.time.Duration resolves-to=\"java.time.Ser\">\n" //
135 + " <byte>1</byte>\n" //
136 + " <long>7777</long>\n" //
137 + " <int>0</int>\n" //
138 + "</java.time.Duration>"));
139 }
140
141 public void testDurationIsImmutable() {
142 final Duration[] array = new Duration[2];
143 array[0] = array[1] = Duration.ofHours(50);
144 assertBothWays(array, "" //
145 + "<duration-array>\n" //
146 + " <duration>PT50H</duration>\n" //
147 + " <duration>PT50H</duration>\n" //
148 + "</duration-array>");
149 }
150
151 public void testInstant() {
152 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 0, ZoneOffset.of("Z"))),
153 "<instant>2017-07-30T20:40:00Z</instant>");
154 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 0, ZoneId.of("Europe/London"))),
155 "<instant>2017-07-30T19:40:00Z</instant>");
156 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 0, ZoneId.of("Europe/Paris"))),
157 "<instant>2017-07-30T18:40:00Z</instant>");
158 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 123456789, ZoneOffset.of("Z"))),
159 "<instant>2017-07-30T20:40:00.123456789Z</instant>");
160 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 100000000, ZoneOffset.of("Z"))),
161 "<instant>2017-07-30T20:40:00.100Z</instant>");
162 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 100000, ZoneOffset.of("Z"))),
163 "<instant>2017-07-30T20:40:00.000100Z</instant>");
164 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 1000, ZoneOffset.of("Z"))),
165 "<instant>2017-07-30T20:40:00.000001Z</instant>");
166 assertBothWays(Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 100, ZoneOffset.of("Z"))),
167 "<instant>2017-07-30T20:40:00.000000100Z</instant>");
168 }
169
170 public void testInstantConversionExceptionContainsInvalidValue() {
171 try {
172 xstream.fromXML("<instant>2017-07-30X20:40:00Z</instant>");
173 fail("Thrown " + ConversionException.class.getName() + " expected");
174 } catch (final ConversionException e) {
175 assertEquals(Instant.class.getName(), e.get("class"));
176 assertEquals("2017-07-30X20:40:00Z", e.get("value"));
177 }
178 }
179
180 public void testInstantWithOldFormat() {
181 assertEquals(Instant.parse("2017-02-15T18:49:25Z"), xstream.fromXML("" //
182 + "<java.time.Instant resolves-to=\"java.time.Ser\">\n" //
183 + " <byte>2</byte>\n" //
184 + " <long>1487184565</long>\n" //
185 + " <int>0</int>\n" //
186 + "</java.time.Instant>"));
187 }
188
189 public void testInstantIsImmutable() {
190 final Instant[] array = new Instant[2];
191 array[0] = array[1] = Instant.from(ZonedDateTime.of(2017, 7, 30, 20, 40, 0, 0, ZoneOffset.of("Z")));
192 assertBothWays(array, "" //
193 + "<instant-array>\n" //
194 + " <instant>2017-07-30T20:40:00Z</instant>\n" //
195 + " <instant>2017-07-30T20:40:00Z</instant>\n" //
196 + "</instant-array>");
197 }
198
199 public void testPeriod() {
200 assertBothWays(Period.ofDays(1000), "<period>P1000D</period>");
201 assertBothWays(Period.ofWeeks(70), "<period>P490D</period>");
202 assertBothWays(Period.ofMonths(70), "<period>P70M</period>");
203 assertBothWays(Period.ofYears(2017), "<period>P2017Y</period>");
204 assertBothWays(Period.of(-5, 70, -45), "<period>P-5Y70M-45D</period>");
205 assertBothWays(Period.ofYears(0), "<period>P0D</period>");
206 assertBothWays(Period.of(1, 0, 2), "<period>P1Y2D</period>");
207 assertEquals(Period.ofDays(21), xstream.fromXML("<period>P3W</period>"));
208 }
209
210 public void testPeriodConversionExceptionContainsInvalidValue() {
211 try {
212 xstream.fromXML("<period>P1YXD</period>");
213 fail("Thrown " + ConversionException.class.getName() + " expected");
214 } catch (final ConversionException e) {
215 assertEquals(Period.class.getName(), e.get("class"));
216 assertEquals("P1YXD", e.get("period"));
217 }
218 }
219
220 public void testPeriodWithOldFormat() {
221 assertEquals(Period.ofDays(7777), xstream.fromXML("" //
222 + "<java.time.Period resolves-to=\"java.time.Ser\">\n" //
223 + " <byte>14</byte>\n" //
224 + " <int>0</int>\n" //
225 + " <int>0</int>\n" //
226 + " <int>7777</int>\n" //
227 + "</java.time.Period>"));
228 }
229
230 public void testPeriodIsImmutable() {
231 final Period[] array = new Period[2];
232 array[0] = array[1] = Period.ofDays(1);
233 assertBothWays(array, "" //
234 + "<period-array>\n" //
235 + " <period>P1D</period>\n" //
236 + " <period>P1D</period>\n" //
237 + "</period-array>");
238 }
239
240 public void testLocalDate() {
241 assertBothWays(LocalDate.of(2017, 10, 30), "<local-date>2017-10-30</local-date>");
242 }
243
244 public void testLocalDateConversionExceptionContainsInvalidValue() {
245 try {
246 xstream.fromXML("<local-date>2017-13-30</local-date>");
247 fail("Thrown " + ConversionException.class.getName() + " expected");
248 } catch (final ConversionException e) {
249 assertEquals(LocalDate.class.getName(), e.get("class"));
250 assertEquals("2017-13-30", e.get("value"));
251 }
252 }
253
254 public void testLocalDateWithOldFormat() {
255 assertEquals(LocalDate.of(2017, 10, 30), xstream.fromXML("" //
256 + "<java.time.LocalDate resolves-to=\"java.time.Ser\">\n" //
257 + " <byte>3</byte>\n" //
258 + " <int>2017</int>\n" //
259 + " <byte>10</byte>\n" //
260 + " <byte>30</byte>\n" //
261 + "</java.time.LocalDate>"));
262 }
263
264 public void testLocalDateIsImmutable() {
265 final LocalDate[] array = new LocalDate[2];
266 array[0] = array[1] = LocalDate.of(2017, 10, 30);
267 assertBothWays(array, "" //
268 + "<local-date-array>\n" //
269 + " <local-date>2017-10-30</local-date>\n" //
270 + " <local-date>2017-10-30</local-date>\n" //
271 + "</local-date-array>");
272 }
273
274 public void testLocalDateTime() {
275 assertBothWays(LocalDateTime.of(2017, 7, 30, 20, 40), "<local-date-time>2017-07-30T20:40:00</local-date-time>");
276 assertBothWays(LocalDateTime.of(2017, 10, 30, 20, 40, 15),
277 "<local-date-time>2017-10-30T20:40:15</local-date-time>");
278 assertBothWays(LocalDateTime.of(2017, 10, 30, 20, 40, 15, 123456789),
279 "<local-date-time>2017-10-30T20:40:15.123456789</local-date-time>");
280 assertBothWays(LocalDateTime.of(2017, 10, 30, 20, 40, 15, 9),
281 "<local-date-time>2017-10-30T20:40:15.000000009</local-date-time>");
282 assertEquals(LocalDateTime.of(2017, 7, 30, 20, 40), xstream.fromXML(
283 "<local-date-time>2017-07-30T20:40</local-date-time>"));
284 }
285
286 public void testLocalDateTimeConversionExceptionContainsInvalidValue() {
287 try {
288 xstream.fromXML("<local-date-time>2017-13-30T20:40:00</local-date-time>");
289 fail("Thrown " + ConversionException.class.getName() + " expected");
290 } catch (final ConversionException e) {
291 assertEquals(LocalDateTime.class.getName(), e.get("class"));
292 assertEquals("2017-13-30T20:40:00", e.get("value"));
293 }
294 }
295
296 public void testLocalDateTimeWithOldFormat() {
297 assertEquals(LocalDateTime.of(2017, 7, 30, 20, 40), xstream.fromXML("" //
298 + "<java.time.LocalDateTime resolves-to=\"java.time.Ser\">\n" //
299 + " <byte>5</byte>\n" //
300 + " <int>2017</int>\n" //
301 + " <byte>7</byte>\n" //
302 + " <byte>30</byte>\n" //
303 + " <byte>20</byte>\n" //
304 + " <byte>-41</byte>\n" //
305 + "</java.time.LocalDateTime>"));
306 }
307
308 public void testLocalDateTimeIsImmutable() {
309 final LocalDateTime[] array = new LocalDateTime[2];
310 array[0] = array[1] = LocalDateTime.of(2017, 7, 30, 20, 40);
311 assertBothWays(array, "" //
312 + "<local-date-time-array>\n" //
313 + " <local-date-time>2017-07-30T20:40:00</local-date-time>\n" //
314 + " <local-date-time>2017-07-30T20:40:00</local-date-time>\n" //
315 + "</local-date-time-array>");
316 }
317
318 public void testLocalTime() {
319 assertBothWays(LocalTime.of(10, 30), "<local-time>10:30:00</local-time>");
320 assertBothWays(LocalTime.of(10, 30, 20), "<local-time>10:30:20</local-time>");
321 assertBothWays(LocalTime.of(10, 30, 20, 123456789), "<local-time>10:30:20.123456789</local-time>");
322 assertBothWays(LocalTime.of(10, 30, 20, 9), "<local-time>10:30:20.000000009</local-time>");
323 assertBothWays(LocalTime.of(10, 30, 20, 1000000), "<local-time>10:30:20.001</local-time>");
324 assertBothWays(LocalTime.of(10, 30, 20, 100000000), "<local-time>10:30:20.1</local-time>");
325 assertEquals(LocalTime.of(10, 30), xstream.fromXML("<local-time>10:30</local-time>"));
326 }
327
328 public void testLocalTimeConversionExceptionContainsInvalidValue() {
329 try {
330 xstream.fromXML("<local-time>10:30:77</local-time>");
331 fail("Thrown " + ConversionException.class.getName() + " expected");
332 } catch (final ConversionException e) {
333 assertEquals(LocalTime.class.getName(), e.get("class"));
334 assertEquals("10:30:77", e.get("value"));
335 }
336 }
337
338 public void testLocalTimeWithOldFormat() {
339 assertEquals(LocalTime.of(10, 30), xstream.fromXML("" //
340 + "<java.time.LocalTime resolves-to=\"java.time.Ser\">\n" //
341 + " <byte>4</byte>\n" //
342 + " <byte>10</byte>\n" //
343 + " <byte>-31</byte>\n" //
344 + "</java.time.LocalTime>"));
345 }
346
347 public void testLocalTimeIsImmutable() {
348 final LocalTime array[] = new LocalTime[2];
349 array[0] = array[1] = LocalTime.of(10, 30);
350 assertBothWays(array, "" //
351 + "<local-time-array>\n"
352 + " <local-time>10:30:00</local-time>\n" //
353 + " <local-time>10:30:00</local-time>\n" //
354 + "</local-time-array>");
355 }
356
357 public void testDayOfWeek() {
358 assertBothWays(DayOfWeek.MONDAY, "<day-of-week>MONDAY</day-of-week>");
359 }
360
361 public void testMonth() {
362 assertBothWays(Month.FEBRUARY, "<month>FEBRUARY</month>");
363 }
364
365 public void testMonthDay() {
366 assertBothWays(MonthDay.of(1, 13), "<month-day>--01-13</month-day>");
367 assertBothWays(MonthDay.of(2, 29), "<month-day>--02-29</month-day>");
368 }
369
370 public void testMonthDayConversionExceptionContainsInvalidValue() {
371 try {
372 xstream.fromXML("<month-day>--00-13</month-day>");
373 fail("Thrown " + ConversionException.class.getName() + " expected");
374 } catch (final ConversionException e) {
375 assertEquals(MonthDay.class.getName(), e.get("class"));
376 assertEquals("--00-13", e.get("value"));
377 }
378 }
379
380 public void testMonthDayWithOldFormat() {
381 assertEquals(MonthDay.of(Month.JANUARY, 13), xstream.fromXML("" //
382 + "<java.time.MonthDay resolves-to=\"java.time.Ser\">\n" //
383 + " <byte>13</byte>\n" //
384 + " <byte>1</byte>\n" //
385 + " <byte>13</byte>\n" //
386 + "</java.time.MonthDay>"));
387 }
388
389 public void testMonthDayIsImmutable() {
390 final MonthDay array[] = new MonthDay[2];
391 array[0] = array[1] = MonthDay.of(Month.APRIL, 10);
392 assertBothWays(array, "" //
393 + "<month-day-array>\n"
394 + " <month-day>--04-10</month-day>\n" //
395 + " <month-day>--04-10</month-day>\n" //
396 + "</month-day-array>");
397 }
398
399 public void testOffsetDateTime() {
400 assertBothWays(OffsetDateTime.of(2017, 7, 30, 20, 40, 0, 0, ZoneOffset.ofHours(0)),
401 "<offset-date-time>2017-07-30T20:40:00Z</offset-date-time>");
402 assertBothWays(OffsetDateTime.of(2017, 7, 30, 20, 40, 15, 0, ZoneOffset.ofHours(0)),
403 "<offset-date-time>2017-07-30T20:40:15Z</offset-date-time>");
404 assertBothWays(OffsetDateTime.of(2017, 7, 30, 20, 40, 15, 0, ZoneOffset.ofHours(1)),
405 "<offset-date-time>2017-07-30T20:40:15+01:00</offset-date-time>");
406 assertBothWays(OffsetDateTime.of(2017, 10, 30, 20, 40, 15, 123456789, ZoneOffset.ofHours(1)),
407 "<offset-date-time>2017-10-30T20:40:15.123456789+01:00</offset-date-time>");
408 assertBothWays(OffsetDateTime.of(2017, 10, 30, 20, 40, 15, 9, ZoneOffset.ofHours(1)),
409 "<offset-date-time>2017-10-30T20:40:15.000000009+01:00</offset-date-time>");
410 assertBothWays(OffsetDateTime.of(2017, 10, 30, 20, 40, 15, 1000000, ZoneOffset.ofHours(1)),
411 "<offset-date-time>2017-10-30T20:40:15.001+01:00</offset-date-time>");
412 assertBothWays(OffsetDateTime.of(2017, 10, 30, 20, 40, 15, 100000000, ZoneOffset.ofHours(1)),
413 "<offset-date-time>2017-10-30T20:40:15.1+01:00</offset-date-time>");
414 assertBothWays(OffsetDateTime.of(2017, 10, 30, 20, 40, 15, 123456789, ZoneOffset.ofHoursMinutesSeconds(1, 30,
415 15)), "<offset-date-time>2017-10-30T20:40:15.123456789+01:30:15</offset-date-time>");
416 assertEquals(OffsetDateTime.of(2017, 7, 30, 20, 40, 0, 0, ZoneOffset.ofHours(0)), xstream.fromXML(
417 "<offset-date-time>2017-07-30T20:40Z</offset-date-time>"));
418 assertEquals(OffsetDateTime.of(2017, 10, 30, 20, 40, 15, 100000000, ZoneOffset.ofHours(1)), xstream.fromXML(
419 "<offset-date-time>2017-10-30T20:40:15.100+01:00</offset-date-time>"));
420 }
421
422 public void testOffsetDateTimeConversionExceptionContainsInvalidValue() {
423 try {
424 xstream.fromXML("<offset-date-time>2017-07-30T27:40:00Z</offset-date-time>");
425 fail("Thrown " + ConversionException.class.getName() + " expected");
426 } catch (final ConversionException e) {
427 assertEquals(OffsetDateTime.class.getName(), e.get("class"));
428 assertEquals("2017-07-30T27:40:00Z", e.get("value"));
429 }
430 }
431
432 public void testOffsetDateTimeWithOldFormat() {
433 assertEquals(OffsetDateTime.of(2017, 7, 30, 20, 40, 0, 0, ZoneOffset.ofHours(0)), xstream.fromXML("" //
434 + "<java.time.OffsetDateTime resolves-to=\"java.time.Ser\">\n" //
435 + " <byte>10</byte>\n" //
436 + " <int>2017</int>\n" //
437 + " <byte>7</byte>\n" //
438 + " <byte>30</byte>\n" //
439 + " <byte>20</byte>\n" //
440 + " <byte>-41</byte>\n" //
441 + " <byte>0</byte>\n" //
442 + "</java.time.OffsetDateTime>"));
443 }
444
445 public void testOffsetDateTimeIsImmutable() {
446 final OffsetDateTime array[] = new OffsetDateTime[2];
447 array[0] = array[1] = OffsetDateTime.of(2017, 7, 30, 20, 40, 15, 0, ZoneOffset.ofHours(1));
448 assertBothWays(array, "" //
449 + "<offset-date-time-array>\n"
450 + " <offset-date-time>2017-07-30T20:40:15+01:00</offset-date-time>\n" //
451 + " <offset-date-time>2017-07-30T20:40:15+01:00</offset-date-time>\n" //
452 + "</offset-date-time-array>");
453 }
454
455 public void testOffsetTime() {
456 assertBothWays(OffsetTime.of(20, 40, 0, 0, ZoneOffset.ofHours(0)), "<offset-time>20:40:00Z</offset-time>");
457 assertBothWays(OffsetTime.of(20, 40, 15, 0, ZoneOffset.ofHours(0)), "<offset-time>20:40:15Z</offset-time>");
458 assertBothWays(OffsetTime.of(20, 40, 15, 0, ZoneOffset.ofHours(1)),
459 "<offset-time>20:40:15+01:00</offset-time>");
460 assertBothWays(OffsetTime.of(20, 40, 15, 123456789, ZoneOffset.ofHours(1)),
461 "<offset-time>20:40:15.123456789+01:00</offset-time>");
462 assertBothWays(OffsetTime.of(20, 40, 15, 9, ZoneOffset.ofHours(1)),
463 "<offset-time>20:40:15.000000009+01:00</offset-time>");
464 assertBothWays(OffsetTime.of(20, 40, 15, 1000000, ZoneOffset.ofHours(1)),
465 "<offset-time>20:40:15.001+01:00</offset-time>");
466 assertBothWays(OffsetTime.of(20, 40, 15, 100000000, ZoneOffset.ofHours(1)),
467 "<offset-time>20:40:15.1+01:00</offset-time>");
468 assertBothWays(OffsetTime.of(20, 40, 15, 123456789, ZoneOffset.ofHoursMinutesSeconds(1, 30, 15)),
469 "<offset-time>20:40:15.123456789+01:30:15</offset-time>");
470 assertEquals(OffsetTime.of(20, 40, 0, 0, ZoneOffset.ofHours(0)), xstream.fromXML(
471 "<offset-time>20:40Z</offset-time>"));
472 assertEquals(OffsetTime.of(20, 40, 15, 100000000, ZoneOffset.ofHours(1)), xstream.fromXML(
473 "<offset-time>20:40:15.100+01:00</offset-time>"));
474 }
475
476 public void testOffsetTimeConversionExceptionContainsInvalidValue() {
477 try {
478 xstream.fromXML("<offset-time>20:77:00Z</offset-time>");
479 fail("Thrown " + ConversionException.class.getName() + " expected");
480 } catch (final ConversionException e) {
481 assertEquals(OffsetTime.class.getName(), e.get("class"));
482 assertEquals("20:77:00Z", e.get("value"));
483 }
484 }
485
486 public void testOffsetTimeWithOldFormat() {
487 assertEquals(OffsetTime.of(20, 40, 0, 0, ZoneOffset.ofHours(0)), xstream.fromXML("" //
488 + "<java.time.OffsetTime resolves-to=\"java.time.Ser\">\n" //
489 + " <byte>9</byte>\n" //
490 + " <byte>20</byte>\n" //
491 + " <byte>-41</byte>\n" //
492 + " <byte>0</byte>\n" //
493 + "</java.time.OffsetTime>"));
494 }
495
496 public void testOffsetTimeIsImmutable() {
497 final OffsetTime array[] = new OffsetTime[2];
498 array[0] = array[1] = OffsetTime.of(20, 40, 15, 0, ZoneOffset.ofHours(1));
499 assertBothWays(array, "" //
500 + "<offset-time-array>\n"
501 + " <offset-time>20:40:15+01:00</offset-time>\n" //
502 + " <offset-time>20:40:15+01:00</offset-time>\n" //
503 + "</offset-time-array>");
504 }
505
506 public void testYear() {
507 assertBothWays(Year.of(2017), "<year>2017</year>");
508 assertBothWays(Year.of(0), "<year>0</year>");
509 assertBothWays(Year.of(-1), "<year>-1</year>");
510 }
511
512 public void testYearConversionExceptionContainsInvalidValue() {
513 try {
514 xstream.fromXML("<year>Z</year>");
515 fail("Thrown " + ConversionException.class.getName() + " expected");
516 } catch (final ConversionException e) {
517 assertEquals(Year.class.getName(), e.get("class"));
518 assertEquals("Z", e.get("value"));
519 }
520 }
521
522 public void testYearWithOldFormat() {
523 assertEquals(Year.of(2017), xstream.fromXML("" //
524 + "<java.time.Year resolves-to=\"java.time.Ser\">\n" //
525 + " <byte>11</byte>\n" //
526 + " <int>2017</int>\n" //
527 + "</java.time.Year>"));
528 }
529
530 public void testYearIsImmutable() {
531 final Year array[] = new Year[2];
532 array[0] = array[1] = Year.of(2017);
533 assertBothWays(array, "" //
534 + "<year-array>\n"
535 + " <year>2017</year>\n" //
536 + " <year>2017</year>\n" //
537 + "</year-array>");
538 }
539
540 public void testYearMonth() {
541 assertBothWays(YearMonth.of(2017, 2), "<year-month>2017-02</year-month>");
542 assertBothWays(YearMonth.of(0, 2), "<year-month>0000-02</year-month>");
543 assertBothWays(YearMonth.of(-1, 2), "<year-month>-0001-02</year-month>");
544 }
545
546 public void testYearMonthConversionExceptionContainsInvalidValue() {
547 try {
548 xstream.fromXML("<year-month>Z-02</year-month>");
549 fail("Thrown " + ConversionException.class.getName() + " expected");
550 } catch (final ConversionException e) {
551 assertEquals(YearMonth.class.getName(), e.get("class"));
552 assertEquals("Z-02", e.get("value"));
553 }
554 }
555
556 public void testYearMonthWithOldFormat() {
557 assertEquals(YearMonth.of(2017, 2), xstream.fromXML("" //
558 + "<java.time.YearMonth resolves-to=\"java.time.Ser\">\n" //
559 + " <byte>12</byte>\n" //
560 + " <int>2017</int>\n" //
561 + " <byte>2</byte>\n" //
562 + "</java.time.YearMonth>"));
563 }
564
565 public void testYearMonthIsImmutable() {
566 final YearMonth array[] = new YearMonth[2];
567 array[0] = array[1] = YearMonth.of(2017, 2);
568 assertBothWays(array, "" //
569 + "<year-month-array>\n"
570 + " <year-month>2017-02</year-month>\n" //
571 + " <year-month>2017-02</year-month>\n" //
572 + "</year-month-array>");
573 }
574
575 public void testZonedDateTime() {
576 assertBothWays(ZonedDateTime.of(2017, 10, 30, 20, 40, 0, 0, ZoneId.of("Europe/London")),
577 "<zoned-date-time>2017-10-30T20:40:00Z[Europe/London]</zoned-date-time>");
578 assertBothWays(ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 0, ZoneId.of("Europe/London")),
579 "<zoned-date-time>2017-10-30T20:40:15Z[Europe/London]</zoned-date-time>");
580 assertBothWays(ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 0, ZoneId.of("Europe/Paris")),
581 "<zoned-date-time>2017-10-30T20:40:15+01:00[Europe/Paris]</zoned-date-time>");
582 assertBothWays(ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 123456789, ZoneId.of("Europe/Paris")),
583 "<zoned-date-time>2017-10-30T20:40:15.123456789+01:00[Europe/Paris]</zoned-date-time>");
584 assertBothWays(ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 9, ZoneId.of("Europe/Paris")),
585 "<zoned-date-time>2017-10-30T20:40:15.000000009+01:00[Europe/Paris]</zoned-date-time>");
586 assertBothWays(ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 1000000, ZoneId.of("Europe/Paris")),
587 "<zoned-date-time>2017-10-30T20:40:15.001+01:00[Europe/Paris]</zoned-date-time>");
588 assertBothWays(ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 100000000, ZoneId.of("Europe/Paris")),
589 "<zoned-date-time>2017-10-30T20:40:15.1+01:00[Europe/Paris]</zoned-date-time>");
590 assertEquals(ZonedDateTime.of(2017, 10, 30, 20, 40, 0, 0, ZoneId.of("Europe/London")), xstream.fromXML(
591 "<zoned-date-time>2017-10-30T20:40Z[Europe/London]</zoned-date-time>"));
592 assertEquals(ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 100000000, ZoneId.of("Europe/Paris")), xstream.fromXML(
593 "<zoned-date-time>2017-10-30T20:40:15.100+01:00[Europe/Paris]</zoned-date-time>"));
594 }
595
596 public void testZonedDateTimeConversionExceptionContainsInvalidValue() {
597 try {
598 xstream.fromXML("<zoned-date-time>2017-10-30T20:40:00Z[Europe/Bonn]</zoned-date-time>");
599 fail("Thrown " + ConversionException.class.getName() + " expected");
600 } catch (final ConversionException e) {
601 assertEquals(ZonedDateTime.class.getName(), e.get("class"));
602 assertEquals("2017-10-30T20:40:00Z[Europe/Bonn]", e.get("value"));
603 }
604 }
605
606 public void testZonedDateTimeWithOldFormat() {
607 assertEquals(ZonedDateTime.of(2017, 10, 30, 20, 40, 0, 0, ZoneId.of("Europe/London")), xstream.fromXML("" //
608 + "<java.time.ZonedDateTime resolves-to=\"java.time.Ser\">\n" //
609 + " <byte>6</byte>\n" //
610 + " <int>2017</int>\n" //
611 + " <byte>10</byte>\n" //
612 + " <byte>30</byte>\n" //
613 + " <byte>20</byte>\n" //
614 + " <byte>-41</byte>\n" //
615 + " <byte>0</byte>\n" //
616 + " <byte>7</byte>\n" //
617 + " <string>Europe/London</string>\n" //
618 + "</java.time.ZonedDateTime>"));
619 }
620
621 public void testZonedDateTimeIsImmutable() {
622 final ZonedDateTime array[] = new ZonedDateTime[2];
623 array[0] = array[1] = ZonedDateTime.of(2017, 10, 30, 20, 40, 15, 0, ZoneId.of("Europe/Paris"));
624 assertBothWays(array, ""
625 + "<zoned-date-time-array>\n"
626 + " <zoned-date-time>2017-10-30T20:40:15+01:00[Europe/Paris]</zoned-date-time>\n"
627 + " <zoned-date-time>2017-10-30T20:40:15+01:00[Europe/Paris]</zoned-date-time>\n"
628 + "</zoned-date-time-array>");
629 }
630
631 public void testZoneOffest() {
632 assertBothWays(ZoneOffset.of("Z"), "<zone-id>Z</zone-id>");
633 assertBothWays(ZoneOffset.ofTotalSeconds(7777), "<zone-id>+02:09:37</zone-id>");
634 assertBothWays(ZoneId.ofOffset("GMT", ZoneOffset.ofTotalSeconds(7777)), "<zone-id>GMT+02:09:37</zone-id>");
635 assertBothWays(ZoneId.of("ECT", ZoneId.SHORT_IDS), "<zone-id>Europe/Paris</zone-id>");
636 assertBothWays(ZoneId.of("CET"), "<zone-id>CET</zone-id>");
637 }
638
639 public void testZoneIdConversionExceptionContainsInvalidValue() {
640 try {
641 xstream.fromXML("<zone-id>X</zone-id>");
642 fail("Thrown " + ConversionException.class.getName() + " expected");
643 } catch (final ConversionException e) {
644 assertEquals(ZoneId.class.getName(), e.get("class"));
645 assertEquals("X", e.get("value"));
646 }
647 try {
648 xstream.fromXML("<zone-id>Europe/X</zone-id>");
649 fail("Thrown " + ConversionException.class.getName() + " expected");
650 } catch (final ConversionException e) {
651 assertEquals(ZoneId.class.getName(), e.get("class"));
652 assertEquals("Europe/X", e.get("value"));
653 }
654 }
655
656 public void testZoneOffestWithOldFormat() {
657 assertEquals(ZoneOffset.ofTotalSeconds(7777), xstream.fromXML("" //
658 + "<java.time.ZoneOffset resolves-to=\"java.time.Ser\">\n" //
659 + " <byte>8</byte>\n" //
660 + " <byte>127</byte>\n" //
661 + " <int>7777</int>\n" //
662 + "</java.time.ZoneOffset>"));
663 }
664
665 public void testZoneOffestIsImmutable() {
666 final ZoneOffset[] array = new ZoneOffset[2];
667 array[0] = array[1] = ZoneOffset.of("Z");
668 assertBothWays(array, "" //
669 + "<zone-id-array>\n" //
670 + " <zone-id>Z</zone-id>\n" //
671 + " <zone-id>Z</zone-id>\n" //
672 + "</zone-id-array>");
673 }
674
675 public void testZoneRegion() {
676 assertBothWays(ZoneId.of("America/Caracas"), "<zone-id>America/Caracas</zone-id>");
677 assertBothWays(ZoneId.of("Europe/Berlin"), "<zone-id>Europe/Berlin</zone-id>");
678 }
679
680 public void testZoneRegionWithOldFormat() {
681 assertEquals(ZoneId.of("America/Caracas"), xstream.fromXML("" //
682 + "<java.time.ZoneRegion resolves-to=\"java.time.Ser\">\n" //
683 + " <byte>7</byte>\n" //
684 + " <string>America/Caracas</string>\n" //
685 + "</java.time.ZoneRegion>"));
686 }
687
688 public void testZoneRegionIsImmutable() {
689 final ZoneId[] array = new ZoneId[2];
690 array[0] = array[1] = ZoneId.of("Europe/Rome");
691 assertBothWays(array, "" //
692 + "<zone-id-array>\n" //
693 + " <zone-id>Europe/Rome</zone-id>\n" //
694 + " <zone-id>Europe/Rome</zone-id>\n" //
695 + "</zone-id-array>");
696 }
697
698 public void testChronology() {
699 assertBothWays(IsoChronology.INSTANCE, "<chronology>ISO</chronology>");
700 assertBothWays(JapaneseChronology.INSTANCE, "<chronology>Japanese</chronology>");
701 }
702
703 public void testChronologyConversionExceptionContainsInvalidValue() {
704 try {
705 xstream.fromXML("<chronology>Z</chronology>");
706 fail("Thrown " + ConversionException.class.getName() + " expected");
707 } catch (final ConversionException e) {
708 assertEquals(Chronology.class.getName(), e.get("class"));
709 assertEquals("Z", e.get("value"));
710 }
711 }
712
713 public void testChronologyWithOldFormat() {
714 assertSame(IsoChronology.INSTANCE, xstream.fromXML("" //
715 + "<java.time.chrono.IsoChronology resolves-to=\"java.time.chrono.Ser\">\n" //
716 + " <byte>1</byte>\n" //
717 + " <string>ISO</string>\n" //
718 + "</java.time.chrono.IsoChronology>"));
719 }
720
721 public void testChronologyIsImmutable() {
722 final Chronology[] array = new Chronology[2];
723 array[0] = array[1] = IsoChronology.INSTANCE;
724 assertBothWays(array, "" //
725 + "<chronology-array>\n" //
726 + " <chronology>ISO</chronology>\n" //
727 + " <chronology>ISO</chronology>\n" //
728 + "</chronology-array>");
729 }
730
731 public void testHijrahDate() {
732 assertBothWays(HijrahChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)),
733 "<hijrah-date>Hijrah-umalqura AH 1438-11-07</hijrah-date>");
734 }
735
736 public void testHijrahDateWithOldFormat() {
737 assertEquals(HijrahChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)), xstream.fromXML("" //
738 + "<java.time.chrono.HijrahDate resolves-to=\"java.time.chrono.Ser\">\n" //
739 + " <byte>6</byte>\n" //
740 + " <java.time.chrono.HijrahChronology resolves-to=\"java.time.chrono.Ser\">\n" //
741 + " <byte>1</byte>\n" //
742 + " <string>Hijrah-umalqura</string>\n" //
743 + " </java.time.chrono.HijrahChronology>\n" //
744 + " <int>1438</int>\n" //
745 + " <byte>11</byte>\n" //
746 + " <byte>7</byte>\n" //
747 + "</java.time.chrono.HijrahDate>"));
748 }
749
750 public void testHijrahDateConversionExceptionContainsInvalidValue() {
751 try {
752 xstream.fromXML("<hijrah-date>Hijrah-X AH 1438-11-07</hijrah-date>");
753 fail("Thrown " + ConversionException.class.getName() + " expected");
754 } catch (final ConversionException e) {
755 assertEquals(HijrahDate.class.getName(), e.get("class"));
756 assertEquals("Hijrah-X AH 1438-11-07", e.get("value"));
757 }
758 try {
759 xstream.fromXML("<hijrah-date>Hijrah-umalqura X 1438-11-07</hijrah-date>");
760 fail("Thrown " + ConversionException.class.getName() + " expected");
761 } catch (final ConversionException e) {
762 assertEquals(HijrahDate.class.getName(), e.get("class"));
763 assertEquals("Hijrah-umalqura X 1438-11-07", e.get("value"));
764 }
765 try {
766 xstream.fromXML("<hijrah-date>Hijrah-umalqura AH 1438-42-07</hijrah-date>");
767 fail("Thrown " + ConversionException.class.getName() + " expected");
768 } catch (final ConversionException e) {
769 assertEquals(HijrahDate.class.getName(), e.get("class"));
770 assertEquals("Hijrah-umalqura AH 1438-42-07", e.get("value"));
771 }
772 }
773
774 public void testHijrahDateIsImmutable() {
775 final HijrahDate[] array = new HijrahDate[2];
776 array[0] = array[1] = HijrahChronology.INSTANCE.date(LocalDate.of(2017, 7, 30));
777 assertBothWays(array, "" //
778 + "<hijrah-date-array>\n" //
779 + " <hijrah-date>Hijrah-umalqura AH 1438-11-07</hijrah-date>\n" //
780 + " <hijrah-date>Hijrah-umalqura AH 1438-11-07</hijrah-date>\n" //
781 + "</hijrah-date-array>");
782 }
783
784 public void testHijrahEra() {
785 assertBothWays(HijrahEra.AH, "<hijrah-era>AH</hijrah-era>");
786 }
787
788 public void testJapaneseDate() {
789 assertBothWays(JapaneseChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)),
790 "<japanese-date>Japanese Heisei 29-07-30</japanese-date>");
791 }
792
793 public void testJapaneseDateWithOldFormat() {
794 assertEquals(JapaneseChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)), xstream.fromXML("" //
795 + "<java.time.chrono.JapaneseDate resolves-to=\"java.time.chrono.Ser\">\n" //
796 + " <byte>4</byte>\n" //
797 + " <int>2017</int>\n" //
798 + " <byte>7</byte>\n" //
799 + " <byte>30</byte>\n" //
800 + "</java.time.chrono.JapaneseDate>"));
801 }
802
803 public void testJapaneseDateConversionExceptionContainsInvalidValue() {
804 try {
805 xstream.fromXML("<japanese-date>Chinese Heisei 29-07-30</japanese-date>");
806 fail("Thrown " + ConversionException.class.getName() + " expected");
807 } catch (final ConversionException e) {
808 assertEquals(JapaneseDate.class.getName(), e.get("class"));
809 assertEquals("Chinese Heisei 29-07-30", e.get("value"));
810 }
811 try {
812 xstream.fromXML("<japanese-date>Japanese Mitsubishi 29-07-30</japanese-date>");
813 fail("Thrown " + ConversionException.class.getName() + " expected");
814 } catch (final ConversionException e) {
815 assertEquals(JapaneseDate.class.getName(), e.get("class"));
816 assertEquals("Japanese Mitsubishi 29-07-30", e.get("value"));
817 }
818 try {
819 xstream.fromXML("<japanese-date>Japanese Heisei 29-13-30</japanese-date>");
820 fail("Thrown " + ConversionException.class.getName() + " expected");
821 } catch (final ConversionException e) {
822 assertEquals(JapaneseDate.class.getName(), e.get("class"));
823 assertEquals("Japanese Heisei 29-13-30", e.get("value"));
824 }
825 }
826
827 public void testJapaneseDateIsImmutable() {
828 final JapaneseDate[] array = new JapaneseDate[2];
829 array[0] = array[1] = JapaneseChronology.INSTANCE.date(LocalDate.of(2017, 7, 30));
830 assertBothWays(array, "" //
831 + "<japanese-date-array>\n" //
832 + " <japanese-date>Japanese Heisei 29-07-30</japanese-date>\n" //
833 + " <japanese-date>Japanese Heisei 29-07-30</japanese-date>\n" //
834 + "</japanese-date-array>");
835 }
836
837 public void testJapaneseEra() {
838 assertBothWays(JapaneseEra.TAISHO, "<japanese-era>Taisho</japanese-era>");
839 }
840
841 public void testJapaneseEraWithOldFormat() {
842 assertEquals(JapaneseEra.TAISHO, xstream.fromXML("" //
843 + "<java.time.chrono.JapaneseEra resolves-to=\"java.time.chrono.Ser\">\n" //
844 + " <byte>5</byte>\n" //
845 + " <byte>0</byte>\n" //
846 + "</java.time.chrono.JapaneseEra>"));
847 }
848
849 public void testJapaneseEraConversionExceptionContainsInvalidValue() {
850 try {
851 xstream.fromXML("<japanese-era>NEMO</japanese-era>");
852 fail("Thrown " + ConversionException.class.getName() + " expected");
853 } catch (final ConversionException e) {
854 assertEquals(JapaneseEra.class.getName(), e.get("class"));
855 assertEquals("NEMO", e.get("value"));
856 }
857 }
858
859 public void testJapaneseEraIsImmutable() {
860 final JapaneseEra[] array = new JapaneseEra[2];
861 array[0] = array[1] = JapaneseEra.SHOWA;
862 assertBothWays(array, "" //
863 + "<japanese-era-array>\n" //
864 + " <japanese-era>Showa</japanese-era>\n" //
865 + " <japanese-era>Showa</japanese-era>\n" //
866 + "</japanese-era-array>");
867 }
868
869 public void testMinguoDate() {
870 assertBothWays(MinguoChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)),
871 "<minguo-date>Minguo ROC 106-07-30</minguo-date>");
872 }
873
874 public void testMinguoDateWithOldFormat() {
875 assertEquals(MinguoChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)), xstream.fromXML("" //
876 + "<java.time.chrono.MinguoDate resolves-to=\"java.time.chrono.Ser\">\n" //
877 + " <byte>7</byte>\n" //
878 + " <int>106</int>\n" //
879 + " <byte>7</byte>\n" //
880 + " <byte>30</byte>\n" //
881 + "</java.time.chrono.MinguoDate>"));
882 }
883
884 public void testMinguoDateConversionExceptionContainsInvalidValue() {
885 try {
886 xstream.fromXML("<minguo-date>Chinese ROC 106-07-30</minguo-date>");
887 fail("Thrown " + ConversionException.class.getName() + " expected");
888 } catch (final ConversionException e) {
889 assertEquals(MinguoDate.class.getName(), e.get("class"));
890 assertEquals("Chinese ROC 106-07-30", e.get("value"));
891 }
892 try {
893 xstream.fromXML("<minguo-date>Minguo X 106-07-30</minguo-date>");
894 fail("Thrown " + ConversionException.class.getName() + " expected");
895 } catch (final ConversionException e) {
896 assertEquals(MinguoDate.class.getName(), e.get("class"));
897 assertEquals("Minguo X 106-07-30", e.get("value"));
898 }
899 try {
900 xstream.fromXML("<minguo-date>Minguo ROC 106-13-30</minguo-date>");
901 fail("Thrown " + ConversionException.class.getName() + " expected");
902 } catch (final ConversionException e) {
903 assertEquals(MinguoDate.class.getName(), e.get("class"));
904 assertEquals("Minguo ROC 106-13-30", e.get("value"));
905 }
906 }
907
908 public void testMinguoDateIsImmutable() {
909 final MinguoDate[] array = new MinguoDate[2];
910 array[0] = array[1] = MinguoChronology.INSTANCE.date(LocalDate.of(2017, 7, 30));
911 assertBothWays(array, "" //
912 + "<minguo-date-array>\n" //
913 + " <minguo-date>Minguo ROC 106-07-30</minguo-date>\n" //
914 + " <minguo-date>Minguo ROC 106-07-30</minguo-date>\n" //
915 + "</minguo-date-array>");
916 }
917
918 public void testMinguoEra() {
919 assertBothWays(MinguoEra.ROC, "<minguo-era>ROC</minguo-era>");
920 }
921
922 public void testThaiBuddhistDate() {
923 assertBothWays(ThaiBuddhistChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)),
924 "<thai-buddhist-date>ThaiBuddhist BE 2560-07-30</thai-buddhist-date>");
925 }
926
927 public void testThaiBuddhistDateWithOldFormat() {
928 assertEquals(ThaiBuddhistChronology.INSTANCE.date(LocalDate.of(2017, 7, 30)), xstream.fromXML("" //
929 + "<java.time.chrono.ThaiBuddhistDate resolves-to=\"java.time.chrono.Ser\">\n" //
930 + " <byte>8</byte>\n" //
931 + " <int>2560</int>\n" //
932 + " <byte>7</byte>\n" //
933 + " <byte>30</byte>\n" //
934 + "</java.time.chrono.ThaiBuddhistDate>"));
935 }
936
937 public void testThaiBuddhistDateConversionExceptionContainsInvalidValue() {
938 try {
939 xstream.fromXML("<thai-buddhist-date>Chinese BE 2560-07-30</thai-buddhist-date>");
940 fail("Thrown " + ConversionException.class.getName() + " expected");
941 } catch (final ConversionException e) {
942 assertEquals(ThaiBuddhistDate.class.getName(), e.get("class"));
943 assertEquals("Chinese BE 2560-07-30", e.get("value"));
944 }
945 try {
946 xstream.fromXML("<thai-buddhist-date>ThaiBuddhist X 2560-07-30</thai-buddhist-date>");
947 fail("Thrown " + ConversionException.class.getName() + " expected");
948 } catch (final ConversionException e) {
949 assertEquals(ThaiBuddhistDate.class.getName(), e.get("class"));
950 assertEquals("ThaiBuddhist X 2560-07-30", e.get("value"));
951 }
952 try {
953 xstream.fromXML("<thai-buddhist-date>ThaiBuddhist BE 2560-13-30</thai-buddhist-date>");
954 fail("Thrown " + ConversionException.class.getName() + " expected");
955 } catch (final ConversionException e) {
956 assertEquals(ThaiBuddhistDate.class.getName(), e.get("class"));
957 assertEquals("ThaiBuddhist BE 2560-13-30", e.get("value"));
958 }
959 }
960
961 public void testThaiBuddhistDateIsImmutable() {
962 final ThaiBuddhistDate[] array = new ThaiBuddhistDate[2];
963 array[0] = array[1] = ThaiBuddhistChronology.INSTANCE.date(LocalDate.of(2017, 7, 30));
964 assertBothWays(array, "" //
965 + "<thai-buddhist-date-array>\n" //
966 + " <thai-buddhist-date>ThaiBuddhist BE 2560-07-30</thai-buddhist-date>\n" //
967 + " <thai-buddhist-date>ThaiBuddhist BE 2560-07-30</thai-buddhist-date>\n" //
968 + "</thai-buddhist-date-array>");
969 }
970
971 public void testThaiBuddhistEra() {
972 assertBothWays(ThaiBuddhistEra.BE, "<thai-buddhist-era>BE</thai-buddhist-era>");
973 }
974
975 public void testChronoField() {
976 assertBothWays(ChronoField.ERA, "<chrono-field>ERA</chrono-field>");
977 }
978
979 public void testChronoUnit() {
980 assertBothWays(ChronoUnit.DECADES, "<chrono-unit>DECADES</chrono-unit>");
981 }
982
983 public void testIsoFields() {
984 assertBothWays(IsoFields.DAY_OF_QUARTER, "<iso-field>DAY_OF_QUARTER</iso-field>");
985 assertBothWays(IsoFields.QUARTER_OF_YEAR, "<iso-field>QUARTER_OF_YEAR</iso-field>");
986 assertBothWays(IsoFields.QUARTER_YEARS, "<iso-unit>QUARTER_YEARS</iso-unit>");
987 assertBothWays(IsoFields.WEEK_BASED_YEAR, "<iso-field>WEEK_BASED_YEAR</iso-field>");
988 assertBothWays(IsoFields.WEEK_BASED_YEARS, "<iso-unit>WEEK_BASED_YEARS</iso-unit>");
989 assertBothWays(IsoFields.WEEK_OF_WEEK_BASED_YEAR, "<iso-field>WEEK_OF_WEEK_BASED_YEAR</iso-field>");
990 }
991
992 public void testIsoFieldsAreImmutable() {
993 final Object[] array = new Object[4];
994 array[0] = array[1] = IsoFields.DAY_OF_QUARTER;
995 array[2] = array[3] = IsoFields.QUARTER_YEARS;
996 assertBothWays(array, "" //
997 + "<object-array>\n" //
998 + " <iso-field>DAY_OF_QUARTER</iso-field>\n" //
999 + " <iso-field>DAY_OF_QUARTER</iso-field>\n" //
1000 + " <iso-unit>QUARTER_YEARS</iso-unit>\n" //
1001 + " <iso-unit>QUARTER_YEARS</iso-unit>\n" //
1002 + "</object-array>");
1003 }
1004
1005 public void testJulianFields() {
1006 assertBothWays(JulianFields.JULIAN_DAY, "<julian-field>JULIAN_DAY</julian-field>");
1007 assertBothWays(JulianFields.MODIFIED_JULIAN_DAY, "<julian-field>MODIFIED_JULIAN_DAY</julian-field>");
1008 assertBothWays(JulianFields.RATA_DIE, "<julian-field>RATA_DIE</julian-field>");
1009 }
1010
1011 public void testJulianFieldsAreImmutable() {
1012 final TemporalField[] array = new TemporalField[2];
1013 array[0] = array[1] = JulianFields.JULIAN_DAY;
1014 assertBothWays(array, "" //
1015 + "<java.time.temporal.TemporalField-array>\n" //
1016 + " <julian-field>JULIAN_DAY</julian-field>\n" //
1017 + " <julian-field>JULIAN_DAY</julian-field>\n" //
1018 + "</java.time.temporal.TemporalField-array>");
1019 }
1020
1021 public void testValueRange() {
1022 assertBothWays(ValueRange.of(0, 1, 30, 45), "" //
1023 + "<temporal-value-range>\n" //
1024 + " <maxLargest>45</maxLargest>\n" //
1025 + " <maxSmallest>30</maxSmallest>\n" //
1026 + " <minLargest>1</minLargest>\n" //
1027 + " <minSmallest>0</minSmallest>\n" //
1028 + "</temporal-value-range>");
1029 }
1030
1031 public void testValueRangeWithAlias() {
1032 xstream.aliasField("max", ValueRange.class, "maxLargest");
1033 xstream.aliasField("max-s", ValueRange.class, "maxSmallest");
1034 xstream.aliasField("min-l", ValueRange.class, "minLargest");
1035 xstream.aliasField("min", ValueRange.class, "minSmallest");
1036 assertBothWays(ValueRange.of(0, 1, 30, 45), "" //
1037 + "<temporal-value-range>\n" //
1038 + " <max>45</max>\n" //
1039 + " <max-s>30</max-s>\n" //
1040 + " <min-l>1</min-l>\n" //
1041 + " <min>0</min>\n" //
1042 + "</temporal-value-range>");
1043 }
1044
1045 public void testValueRangeWithOldFormat() {
1046 assertEquals(ValueRange.of(0, 1, 30, 45), xstream.fromXML("" //
1047 + "<java.time.temporal.ValueRange serialization=\"custom\">\n" //
1048 + " <java.time.temporal.ValueRange>\n" //
1049 + " <default>\n" //
1050 + " <maxLargest>45</maxLargest>\n" //
1051 + " <maxSmallest>30</maxSmallest>\n" //
1052 + " <minLargest>1</minLargest>\n" //
1053 + " <minSmallest>0</minSmallest>\n" //
1054 + " </default>\n" //
1055 + " </java.time.temporal.ValueRange>\n" //
1056 + "</java.time.temporal.ValueRange>"));
1057 }
1058
1059 public void testWeekFields() {
1060 assertBothWays(WeekFields.of(DayOfWeek.TUESDAY, 2), "" //
1061 + "<week-fields>\n" //
1062 + " <minimalDays>2</minimalDays>\n" //
1063 + " <firstDayOfWeek>TUESDAY</firstDayOfWeek>\n" //
1064 + "</week-fields>");
1065 assertBothWays(WeekFields.ISO, "" //
1066 + "<week-fields>\n" //
1067 + " <minimalDays>4</minimalDays>\n" //
1068 + " <firstDayOfWeek>MONDAY</firstDayOfWeek>\n" //
1069 + "</week-fields>");
1070 }
1071
1072 public void testWeekFieldsWithFieldAlias() {
1073 xstream.aliasField("days", WeekFields.class, "minimalDays");
1074 xstream.aliasField("week-day", WeekFields.class, "firstDayOfWeek");
1075 assertBothWays(WeekFields.of(DayOfWeek.TUESDAY, 2), "" //
1076 + "<week-fields>\n" //
1077 + " <days>2</days>\n" //
1078 + " <week-day>TUESDAY</week-day>\n" //
1079 + "</week-fields>");
1080 }
1081
1082 public void testWeekFieldsWithOldFormat() {
1083 assertEquals(WeekFields.of(DayOfWeek.TUESDAY, 2), xstream.fromXML("" //
1084 + "<java.time.temporal.WeekFields serialization=\"custom\">\n" //
1085 + " <java.time.temporal.WeekFields>\n" //
1086 + " <default>\n" //
1087 + " <minimalDays>2</minimalDays>\n" //
1088 + " <firstDayOfWeek>TUESDAY</firstDayOfWeek>\n" //
1089 + " </default>\n" //
1090 + " </java.time.temporal.WeekFields>\n" //
1091 + "</java.time.temporal.WeekFields>"));
1092 }
1093 }
00 /*
11 * Copyright (C) 2004, 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2014, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2014, 2015, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
66 * style license a copy of which has been included with this distribution in
77 * the LICENSE.txt file.
8 *
8 *
99 * Created on 24. August 2004 by Joe Walnes
1010 */
1111 package com.thoughtworks.acceptance;
12
13 import com.thoughtworks.acceptance.objects.Original;
14 import com.thoughtworks.acceptance.objects.Replaced;
15 import com.thoughtworks.acceptance.objects.StandardObject;
1612
1713 import java.io.ByteArrayInputStream;
1814 import java.io.ByteArrayOutputStream;
2824
2925 import org.apache.commons.lang.StringUtils;
3026
27 import com.thoughtworks.acceptance.objects.Original;
28 import com.thoughtworks.acceptance.objects.Replaced;
29 import com.thoughtworks.acceptance.objects.StandardObject;
30
31
3132 public class WriteReplaceTest extends AbstractAcceptanceTest {
3233
3334 public static class Thing extends StandardObject implements Serializable {
3839 public Thing() {
3940 }
4041
41 public Thing(int a, int b) {
42 public Thing(final int a, final int b) {
4243 this.a = a;
4344 this.b = b;
4445 }
5455 }
5556
5657 public void testReplacesAndResolves() throws IOException, ClassNotFoundException {
57 Thing thing = new Thing(3, 6);
58 final Thing thing = new Thing(3, 6);
5859
5960 // ensure that Java serialization does not cause endless loop for a Thing
60 ByteArrayOutputStream baos = new ByteArrayOutputStream();
61 ObjectOutputStream oos = new ObjectOutputStream(baos);
61 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
62 final ObjectOutputStream oos = new ObjectOutputStream(baos);
6263 oos.writeObject(thing);
6364 oos.close();
64
65 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
66 ObjectInputStream ios = new ObjectInputStream(bais);
65
66 final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
67 final ObjectInputStream ios = new ObjectInputStream(bais);
6768 assertEquals(thing, ios.readObject());
6869 ios.close();
69
70
7071 // ensure that XStream does not cause endless loop for a Thing
7172 xstream.alias("thing", Thing.class);
7273
73 String expectedXml = ""
74 + "<thing>\n"
75 + " <a>3000</a>\n"
76 + " <b>6000</b>\n"
77 + "</thing>";
74 final String expectedXml = "" + "<thing>\n" + " <a>3000</a>\n" + " <b>6000</b>\n" + "</thing>";
7875
7976 assertBothWays(thing, expectedXml);
8077 }
8380 xstream.alias("original-class", Original.class);
8481 xstream.alias("replaced-class", Replaced.class);
8582
86 Original in = new Original("hello world");
87
88 String expectedXml = ""
89 + "<original-class resolves-to=\"replaced-class\">\n"
90 + " <replacedValue>HELLO WORLD</replacedValue>\n"
91 + "</original-class>";
83 final Original in = new Original("hello world");
84
85 final String expectedXml = ""
86 + "<original-class resolves-to=\"replaced-class\">\n"
87 + " <replacedValue>HELLO WORLD</replacedValue>\n"
88 + "</original-class>";
9289
9390 assertBothWays(in, expectedXml);
9491 }
9794 xstream.alias("original-class", Original.class);
9895 xstream.alias("replaced-class", Replaced.class);
9996
100 List in = new ArrayList();
97 final List in = new ArrayList();
10198 in.add(new Original("hello world"));
10299
103 String expectedXml = ""
104 + "<list>\n"
105 + " <original-class resolves-to=\"replaced-class\">\n"
106 + " <replacedValue>HELLO WORLD</replacedValue>\n"
107 + " </original-class>\n"
108 + "</list>";
100 final String expectedXml = ""
101 + "<list>\n"
102 + " <original-class resolves-to=\"replaced-class\">\n"
103 + " <replacedValue>HELLO WORLD</replacedValue>\n"
104 + " </original-class>\n"
105 + "</list>";
109106
110107 assertBothWays(in, expectedXml);
111108 }
113110 public static class Container extends StandardObject {
114111 Original original;
115112 }
116
113
117114 public void testAllowsDifferentTypeToBeSubstitutedAsMember() {
118115 xstream.alias("container", Container.class);
119116 xstream.alias("original-class", Original.class);
120117 xstream.alias("replaced-class", Replaced.class);
121118
122 Container in = new Container();
119 final Container in = new Container();
123120 in.original = new Original("hello world");
124121
125 String expectedXml = ""
126 + "<container>\n"
127 + " <original resolves-to=\"replaced-class\">\n"
128 + " <replacedValue>HELLO WORLD</replacedValue>\n"
129 + " </original>\n"
130 + "</container>";
122 final String expectedXml = ""
123 + "<container>\n"
124 + " <original resolves-to=\"replaced-class\">\n"
125 + " <replacedValue>HELLO WORLD</replacedValue>\n"
126 + " </original>\n"
127 + "</container>";
131128
132129 assertBothWays(in, expectedXml);
133130 }
134131
135132 public static class ExternalizableContainer extends StandardObject implements Externalizable {
136133 Original original;
137
138 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
134
135 public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
139136 original = (Original)in.readObject();
140137 }
141138
142 public void writeExternal(ObjectOutput out) throws IOException {
139 public void writeExternal(final ObjectOutput out) throws IOException {
143140 out.writeObject(original);
144141 }
145142 }
146
143
147144 public void testAllowsDifferentTypeToBeSubstitutedInExternalizable() {
148145 xstream.alias("container", ExternalizableContainer.class);
149146 xstream.alias("original-class", Original.class);
150147 xstream.alias("replaced-class", Replaced.class);
151148
152 ExternalizableContainer in = new ExternalizableContainer();
149 final ExternalizableContainer in = new ExternalizableContainer();
153150 in.original = new Original("hello world");
154151
155 String expectedXml = ""
156 + "<container>\n"
157 + " <original-class resolves-to=\"replaced-class\">\n"
158 + " <replacedValue>HELLO WORLD</replacedValue>\n"
159 + " </original-class>\n"
160 + "</container>";
152 final String expectedXml = ""
153 + "<container>\n"
154 + " <original-class resolves-to=\"replaced-class\">\n"
155 + " <replacedValue>HELLO WORLD</replacedValue>\n"
156 + " </original-class>\n"
157 + "</container>";
161158
162159 assertBothWays(in, expectedXml);
163160 }
166163 xstream.alias("original-class", Original.class);
167164 xstream.alias("replaced-class", Replaced.class);
168165
169 Original in = new Original("hello world");
170
171 String xml = ""
172 + "<original-class resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
173 + " <replacedValue>HELLO WORLD</replacedValue>\n"
174 + "</original-class>";
166 final Original in = new Original("hello world");
167
168 final String xml = ""
169 + "<original-class resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
170 + " <replacedValue>HELLO WORLD</replacedValue>\n"
171 + "</original-class>";
175172
176173 assertEquals(in, xstream.fromXML(xml));
177174 }
180177 xstream.alias("original-class", Original.class);
181178 xstream.alias("replaced-class", Replaced.class);
182179
183 List in = new ArrayList();
180 final List in = new ArrayList();
184181 in.add(new Original("hello world"));
185182
186 String xml = ""
187 + "<list>\n"
188 + " <original-class resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
189 + " <replacedValue>HELLO WORLD</replacedValue>\n"
190 + " </original-class>\n"
191 + "</list>";
183 final String xml = ""
184 + "<list>\n"
185 + " <original-class resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
186 + " <replacedValue>HELLO WORLD</replacedValue>\n"
187 + " </original-class>\n"
188 + "</list>";
192189
193190 assertEquals(in, xstream.fromXML(xml));
194191 }
198195 xstream.alias("original-class", Original.class);
199196 xstream.alias("replaced-class", Replaced.class);
200197
201 Container in = new Container();
198 final Container in = new Container();
202199 in.original = new Original("hello world");
203200
204 String xml = ""
205 + "<container>\n"
206 + " <original resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
207 + " <replacedValue>HELLO WORLD</replacedValue>\n"
208 + " </original>\n"
209 + "</container>";
201 final String xml = ""
202 + "<container>\n"
203 + " <original resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
204 + " <replacedValue>HELLO WORLD</replacedValue>\n"
205 + " </original>\n"
206 + "</container>";
210207
211208 assertEquals(in, xstream.fromXML(xml));
212209 }
213
210
214211 public void testAllowsDifferentTypeToBeSubstitutedWithNonExistingClassInExternalizable() {
215212 xstream.alias("container", ExternalizableContainer.class);
216213 xstream.alias("original-class", Original.class);
217214 xstream.alias("replaced-class", Replaced.class);
218215
219 ExternalizableContainer in = new ExternalizableContainer();
216 final ExternalizableContainer in = new ExternalizableContainer();
220217 in.original = new Original("hello world");
221218
222 String xml = ""
223 + "<container>\n"
224 + " <original-class resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
225 + " <replacedValue>HELLO WORLD</replacedValue>\n"
226 + " </original-class>\n"
227 + "</container>";
219 final String xml = ""
220 + "<container>\n"
221 + " <original-class resolves-to=\"replaced-class\" class=\"not.Existing\">\n"
222 + " <replacedValue>HELLO WORLD</replacedValue>\n"
223 + " </original-class>\n"
224 + "</container>";
228225
229226 assertEquals(in, xstream.fromXML(xml));
230227 }
235232 public OriginalSerializable() {
236233 }
237234
238 public OriginalSerializable(String originalValue) {
235 public OriginalSerializable(final String originalValue) {
239236 this.originalValue = originalValue;
240237 }
241238
243240 return new ReplacedSerializable(originalValue.toUpperCase());
244241 }
245242
246 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
243 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
247244 in.defaultReadObject();
248245 }
249246 }
254251 public ReplacedSerializable() {
255252 }
256253
257 public ReplacedSerializable(String replacedValue) {
254 public ReplacedSerializable(final String replacedValue) {
258255 this.replacedValue = replacedValue;
259256 }
260257
262259 return new OriginalSerializable(replacedValue.toLowerCase());
263260 }
264261
265 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
262 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
266263 in.defaultReadObject();
267264 }
268265 }
271268 xstream.alias("original-serializable-class", OriginalSerializable.class);
272269 xstream.alias("replaced-serializable-class", ReplacedSerializable.class);
273270
274 OriginalSerializable in = new OriginalSerializable("hello world");
275
276 String expectedXml = ""
277 + "<original-serializable-class resolves-to=\"replaced-serializable-class\" serialization=\"custom\">\n"
278 + " <replaced-serializable-class>\n"
279 + " <default>\n"
280 + " <replacedValue>HELLO WORLD</replacedValue>\n"
281 + " </default>\n"
282 + " </replaced-serializable-class>\n"
283 + "</original-serializable-class>";
271 final OriginalSerializable in = new OriginalSerializable("hello world");
272
273 final String expectedXml = ""
274 + "<original-serializable-class resolves-to=\"replaced-serializable-class\" serialization=\"custom\">\n"
275 + " <replaced-serializable-class>\n"
276 + " <default>\n"
277 + " <replacedValue>HELLO WORLD</replacedValue>\n"
278 + " </default>\n"
279 + " </replaced-serializable-class>\n"
280 + "</original-serializable-class>";
284281
285282 assertBothWays(in, expectedXml);
286283 }
291288 public OriginalExternalizable() {
292289 }
293290
294 public OriginalExternalizable(String originalValue) {
291 public OriginalExternalizable(final String originalValue) {
295292 this.originalValue = originalValue;
296293 }
297294
299296 return new ReplacedExternalizable(originalValue.toUpperCase());
300297 }
301298
302 public void writeExternal(ObjectOutput out) throws IOException {
299 public void writeExternal(final ObjectOutput out) throws IOException {
303300 out.writeObject(originalValue);
304301 }
305302
306 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
303 public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
307304 originalValue = (String)in.readObject();
308305 }
309306 }
314311 public ReplacedExternalizable() {
315312 }
316313
317 public ReplacedExternalizable(String replacedValue) {
314 public ReplacedExternalizable(final String replacedValue) {
318315 this.replacedValue = replacedValue;
319316 }
320317
322319 return new OriginalExternalizable(replacedValue.toLowerCase());
323320 }
324321
325 public void writeExternal(ObjectOutput out) throws IOException {
322 public void writeExternal(final ObjectOutput out) throws IOException {
326323 out.writeObject(StringUtils.reverse(replacedValue));
327324 }
328325
329 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
326 public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
330327 replacedValue = StringUtils.reverse((String)in.readObject());
331328 }
332329 }
335332 xstream.alias("original-externalizable-class", OriginalExternalizable.class);
336333 xstream.alias("replaced-externalizable-class", ReplacedExternalizable.class);
337334
338 OriginalExternalizable in = new OriginalExternalizable("hello world");
339
340 String expectedXml = ""
341 + "<original-externalizable-class resolves-to=\"replaced-externalizable-class\">\n"
342 + " <string>DLROW OLLEH</string>\n"
343 + "</original-externalizable-class>";
335 final OriginalExternalizable in = new OriginalExternalizable("hello world");
336
337 final String expectedXml = ""
338 + "<original-externalizable-class resolves-to=\"replaced-externalizable-class\">\n"
339 + " <string>DLROW OLLEH</string>\n"
340 + "</original-externalizable-class>";
341
342 assertBothWays(in, expectedXml);
343 }
344
345 public static class OriginalThing extends StandardObject {
346 private final String value;
347
348 public OriginalThing() {
349 this("");
350 }
351
352 public OriginalThing(final String value) {
353 this.value = value;
354 }
355
356 private Object writeReplace() {
357 return new IntermediateThing(value);
358 }
359 }
360
361 public static class IntermediateThing {
362 private final String value;
363
364 public IntermediateThing(final String value) {
365 this.value = value;
366 }
367
368 private Object writeReplace() {
369 return new ReplacedThing(value);
370 }
371 }
372
373 public static class ReplacedThing {
374 private final String value;
375
376 public ReplacedThing(final String value) {
377 this.value = value;
378 }
379
380 private Object readResolve() {
381 return new OriginalThing(value);
382 }
383 }
384
385 public void testCascadedWriteReplace() {
386 xstream.alias("original-thing", OriginalThing.class);
387 xstream.alias("intermediate-thing", IntermediateThing.class);
388 xstream.alias("replaced-thing", ReplacedThing.class);
389
390 final OriginalThing in = new OriginalThing("hello world");
391
392 final String expectedXml = ""
393 + "<original-thing resolves-to=\"replaced-thing\">\n"
394 + " <value>hello world</value>\n"
395 + "</original-thing>";
344396
345397 assertBothWays(in, expectedXml);
346398 }
00 /*
11 * Copyright (C) 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2014 XStream Committers.
2 * Copyright (C) 2006, 2007, 2014, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
8181 public void testCanSerializeSelfContained() throws ClassNotFoundException, ObjectStreamException {
8282 final OpenSourceSoftware oos = new OpenSourceSoftware("Walnes", "XStream", "BSD");
8383 xstream.alias("software", OpenSourceSoftware.class);
84 final TypePermission[] permissions = XStreamer.getDefaultPermissions();
85 for(int i = 0; i < permissions.length; ++i)
86 xstream.addPermission(permissions[i]);
8487 String xml = new XStreamer().toXML(xstream, oos);
85 assertEquals(oos, new XStreamer().fromXML(xml));
88 assertEquals(oos, new XStreamer().fromXML(xml, XStreamer.getDefaultPermissions()));
8689 }
8790
8891 private String normalizedXStreamXML(String xml) throws TransformerException {
00 /*
11 * Copyright (C) 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2011 XStream Committers.
2 * Copyright (C) 2006, 2007, 2011, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
203203 + " <percent>%</percent>\n"
204204 + " <serialVersionOnStream>1</serialVersionOnStream>\n"
205205 + " <zeroDigit>0</zeroDigit>\n"
206 + " <NaN>\ufffd</NaN>\n"
206 + " <NaN>NaN</NaN>\n"
207207 + " <currencySymbol>DM</currencySymbol>\n"
208208 + " <infinity>\u221e</infinity>\n"
209209 + " <intlCurrencySymbol>DEM</intlCurrencySymbol>\n"
225225 + " <percent>%</percent>\n"
226226 + " <serialVersionOnStream>2</serialVersionOnStream>\n"
227227 + " <zeroDigit>0</zeroDigit>\n"
228 + " <NaN>\ufffd</NaN>\n"
228 + " <NaN>NaN</NaN>\n"
229229 + " <currencySymbol>\u20ac</currencySymbol>\n"
230230 + " <infinity>\u221e</infinity>\n"
231231 + " <intlCurrencySymbol>EUR</intlCurrencySymbol>\n"
248248 + " <percent>%</percent>\n"
249249 + " <serialVersionOnStream>3</serialVersionOnStream>\n"
250250 + " <zeroDigit>0</zeroDigit>\n"
251 + " <NaN>\ufffd</NaN>\n"
251 + " <NaN>NaN</NaN>\n"
252252 + " <currencySymbol>\u20ac</currencySymbol>\n"
253253 + " <exponentialSeparator>E</exponentialSeparator>\n"
254254 + " <infinity>\u221e</infinity>\n"
259259 + "</java.text.DecimalFormatSymbols>";
260260 }
261261 final DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.GERMANY);
262 format.setNaN("NaN");
263 assertEquals("EUR", format.getInternationalCurrencySymbol());
262264 assertBothWays(format, xml);
263265 }
264266
00 /*
1 * Copyright (C) 2007 XStream Committers.
1 * Copyright (C) 2007, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
2626 protected void setUp() throws Exception {
2727 super.setUp();
2828 xstream = new XStream();
29 xstream.registerConverter(
30 new AnnotationReflectionConverter(xstream.getMapper(), xstream
31 .getReflectionProvider(), new AnnotationProvider()), XStream.PRIORITY_VERY_LOW);
29 XStream.setupDefaultSecurity(xstream);
30 xstream.allowTypes(new Class[]{
31 FieldConverterTest.TaskWithAnnotations.class, ImplicitCollectionTest.ImplicitRootOne.class});
32 xstream.registerConverter(new AnnotationReflectionConverter(xstream.getMapper(), xstream
33 .getReflectionProvider(), new AnnotationProvider()), XStream.PRIORITY_VERY_LOW);
3234 xstream.alias("annotatedTask", FieldConverterTest.TaskWithAnnotations.class);
3335 }
3436
00 /*
11 * Copyright (C) 2004, 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1010 */
1111 package com.thoughtworks.xstream.converters.collections;
1212
13 import com.thoughtworks.xstream.XStream;
14
15 import junit.framework.TestCase;
13 import com.thoughtworks.acceptance.AbstractAcceptanceTest;
1614
1715 import java.util.Properties;
1816
19 public class PropertiesConverterTest extends TestCase {
17 public class PropertiesConverterTest extends AbstractAcceptanceTest {
2018
2119 public void testConvertsPropertiesObjectToShortKeyValueElements() {
22 Properties in = new Properties();
23 in.setProperty("hello", "world");
24 in.setProperty("foo", "cheese");
20 Properties properties = new Properties();
21 properties.setProperty("hello", "world");
22 properties.setProperty("foo", "cheese");
2523
26 String expectedXML = "" +
24 String expected = "" +
2725 "<properties>\n" +
2826 " <property name=\"hello\" value=\"world\"/>\n" +
2927 " <property name=\"foo\" value=\"cheese\"/>\n" +
3028 "</properties>";
31 XStream xstream = new XStream();
32 String actualXML = xstream.toXML(in);
33 assertEquals(expectedXML, actualXML);
34
35 Properties expectedOut = new Properties();
36 expectedOut.setProperty("hello", "world");
37 expectedOut.setProperty("foo", "cheese");
38 Properties actualOut = (Properties) xstream.fromXML(actualXML);
39 assertEquals(in, actualOut);
40 assertEquals(in.toString(), actualOut.toString());
41
29 assertBothWaysNormalized(properties, expected, "properties", "property", "@name");
4230 }
4331
4432 public void testIncludesDefaultProperties() {
5341 assertEquals("Unexpected overriden property", "999", override.getProperty("port"));
5442 assertEquals("Unexpected default property", "localhost", override.getProperty("host"));
5543
56 String expectedXML = "" +
44 String expected = "" +
5745 "<properties>\n" +
5846 " <property name=\"port\" value=\"999\"/>\n" +
5947 " <defaults>\n" +
6250 " </defaults>\n" +
6351 "</properties>";
6452
65 XStream xstream = new XStream();
66 String actualXML = xstream.toXML(override);
67 assertEquals(expectedXML, actualXML);
68
69 Properties out = (Properties) xstream.fromXML(actualXML);
53 Properties out = (Properties) assertBothWays(override, expected);
7054 assertEquals("Unexpected overriden property", "999", out.getProperty("port"));
7155 assertEquals("Unexpected default property", "localhost", out.getProperty("host"));
7256 assertEquals(override, out);
8165 override.setProperty("port", "999");
8266 override.setProperty("domain", "codehaus.org");
8367
84 String expectedXML = "" +
68 String expected = "" +
8569 "<properties>\n" +
8670 " <property name=\"domain\" value=\"codehaus.org\"/>\n" +
8771 " <property name=\"port\" value=\"999\"/>\n" +
9175 " </defaults>\n" +
9276 "</properties>";
9377
94 XStream xstream = new XStream();
9578 xstream.registerConverter(new PropertiesConverter(true));
96 String actualXML = xstream.toXML(override);
97 assertEquals(expectedXML, actualXML);
98
99 Properties out = (Properties) xstream.fromXML(actualXML);
79 Properties out = (Properties) assertBothWays(override, expected);
10080 assertEquals("Unexpected overriden property", "999", out.getProperty("port"));
10181 assertEquals("Unexpected default property", "localhost", out.getProperty("host"));
10282 assertEquals(override, out);
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1111 package com.thoughtworks.xstream.converters.enums;
1212
1313 import com.thoughtworks.xstream.XStream;
14
1415 import junit.framework.TestCase;
1516
1617 // ***** READ THIS *****
2829 protected void setUp() throws Exception {
2930 super.setUp();
3031 xstream = new XStream();
32 XStream.setupDefaultSecurity(xstream);
3133 xstream.alias("simple", SimpleEnum.class);
3234 xstream.alias("polymorphic", PolymorphicEnum.class);
3335 }
00 /*
1 * Copyright (C) 2008 XStream Committers.
1 * Copyright (C) 2008, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
2929 protected void setUp() throws Exception {
3030 super.setUp();
3131 xstream = new XStream();
32 XStream.setupDefaultSecurity(xstream);
33 xstream.allowTypes(new Class[] {TypeWithEnums.class});
3234 xstream.alias("simple", SimpleEnum.class);
3335 xstream.alias("polymorphic", PolymorphicEnum.class);
3436 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007 XStream Committers.
2 * Copyright (C) 2006, 2007, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
2323 protected void setUp() throws Exception {
2424 super.setUp();
2525 xstream = new XStream();
26 XStream.setupDefaultSecurity(xstream);
2627 }
2728
2829 public void testIncludesEnumTypeInSerializedForm() {
00 /*
1 * Copyright (C) 2008 XStream Committers.
1 * Copyright (C) 2008, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
3333 protected void setUp() throws Exception {
3434 super.setUp();
3535 xstream = new XStream();
36 XStream.setupDefaultSecurity(xstream);
37 xstream.allowTypesByWildcard(new String[] {getClass().getName()+"$*"});
3638 xstream.alias("simple", SimpleEnum.class);
3739 xstream.alias("polymorphic", PolymorphicEnum.class);
3840 }
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2013 XStream Committers.
2 * Copyright (C) 2006, 2007, 2013, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1111 package com.thoughtworks.xstream.converters.enums;
1212
1313 import com.thoughtworks.xstream.XStream;
14
1415 import junit.framework.TestCase;
1516
1617 import java.util.EnumSet;
2223 protected void setUp() throws Exception {
2324 super.setUp();
2425 xstream = new XStream();
26 XStream.setupDefaultSecurity(xstream);
2527 }
2628
2729 public void testPutsEnumsInCompactCommaSeparatedString() {
00 /*
1 * Copyright (C) 2013 XStream Committers.
1 * Copyright (C) 2013, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
1313 import java.util.Map;
1414
1515 import com.thoughtworks.xstream.XStream;
16
1617 import junit.framework.TestCase;
1718
1819
3031 protected void setUp() throws Exception {
3132 super.setUp();
3233 xstream = new XStream();
34 XStream.setupDefaultSecurity(xstream);
3335 xstream.alias("simple", SimpleEnum.class);
3436 xstream.alias("big", BigEnum.class);
3537 xstream.alias("polymorphic", PolymorphicEnum.class);
00 /*
11 * Copyright (C) 2004 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2013 XStream Committers.
2 * Copyright (C) 2006, 2007, 2013, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
2121 import java.awt.Font;
2222 import java.awt.Toolkit;
2323 import java.awt.font.TextAttribute;
24 import java.awt.font.TransformAttribute;
25 import java.awt.geom.AffineTransform;
2426 import java.util.Map;
2527
2628 public class FontConverterTest extends TestCase {
4143 super.setUp();
4244 // fonts should be serializable also with pure Java
4345 xstream = new XStream(new PureJavaReflectionProvider());
46 XStream.setupDefaultSecurity(xstream);
47 xstream.allowTypes(new Class[] {Font.class, TextAttribute.class, TransformAttribute.class, AffineTransform.class});
4448 in = new Font("Arial", Font.BOLD, 20);
4549 }
4650
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007 XStream Committers.
2 * Copyright (C) 2006, 2007, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
2525 public void testCalendar() {
2626 final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
2727 final XStream xstream = new XStream();
28 XStream.setupDefaultSecurity(xstream);
2829 final String xml = xstream.toXML(cal);
2930 final Calendar serialized = (Calendar)xstream.fromXML(xml);
3031 assertEquals(cal, serialized);
00 /*
1 * 2013 XStream Committers.
1 * 2013, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
4545
4646 String converterXML = converter.toString(in);
4747 Calendar out = (Calendar) converter.fromString(converterXML);
48 assertEquals(in, out);
48 assertEquals(in.getTime(), out.getTime());
4949 } finally {
5050 Locale.setDefault(defaultLocale);
5151 Locale.setDefault(defaultLocaleForFormat);
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2011 XStream Committers.
2 * Copyright (C) 2006, 2007, 2011, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
66 * style license a copy of which has been included with this distribution in
77 * the LICENSE.txt file.
8 *
8 *
99 * Created on 03. October 2005 by Joerg Schaible
1010 */
1111 package com.thoughtworks.xstream.converters.extended;
12
13 import com.thoughtworks.xstream.converters.ConversionException;
14 import com.thoughtworks.xstream.testutil.TimeZoneChanger;
15
16 import junit.framework.TestCase;
17
18 import org.joda.time.DateTime;
1912
2013 import java.util.ArrayList;
2114 import java.util.Calendar;
2215 import java.util.Collections;
2316 import java.util.List;
17 import java.util.Locale;
2418 import java.util.TimeZone;
2519
20 import org.joda.time.DateTime;
21
22 import com.thoughtworks.xstream.converters.ConversionException;
23 import com.thoughtworks.xstream.core.JVM;
24 import com.thoughtworks.xstream.testutil.TimeZoneChanger;
25
26 import junit.framework.TestCase;
27
28
2629 public class ISO8601GregorianCalendarConverterTest extends TestCase {
2730
31 private Locale locale;
2832 private ISO8601GregorianCalendarConverter converter;
2933
3034 protected void setUp() throws Exception {
3135 super.setUp();
3236 converter = new ISO8601GregorianCalendarConverter();
33
37 locale = Locale.getDefault();
38 Locale.setDefault(Locale.GERMANY);
39
3440 // Ensure that this test always run as if it were in the timezone of Panama.
3541 // This prevents failures when running the tests in different zones.
3642 // Note: 'America/Panama' has no relevance - it was just a randomly chosen zone.
3945
4046 protected void tearDown() throws Exception {
4147 TimeZoneChanger.reset();
48 Locale.setDefault(locale);
4249 super.tearDown();
4350 }
4451
4552 public void testRetainsDetailDownToMillisecondLevel() {
4653 // setup
47 Calendar in = Calendar.getInstance();
54 final Calendar in = Calendar.getInstance();
4855
4956 // execute
50 String text = converter.toString(in);
51 Calendar out = (Calendar) converter.fromString(text);
57 final String text = converter.toString(in);
58 final Calendar out = (Calendar)converter.fromString(text);
5259
5360 // verify
54 assertEquals(in, out);
55 }
56
61 assertEquals(in.getTime(), out.getTime());
62 }
63
5764 public void testSavedTimeIsInUTC() {
58 Calendar in = Calendar.getInstance();
65 final Calendar in = Calendar.getInstance();
5966 final String iso8601;
6067 iso8601 = new DateTime(in).toString();
61 String converterXML = converter.toString(in);
68 final String converterXML = converter.toString(in);
6269 assertEquals(iso8601, converterXML);
63
64 Calendar out = (Calendar) converter.fromString(converterXML);
65 assertEquals(in, out);
66 }
67
70
71 final Calendar out = (Calendar)converter.fromString(converterXML);
72 assertEquals(in.getTime(), out.getTime());
73 }
74
6875 public void testCanLoadTimeInDifferentTimeZone() {
69 Calendar in = Calendar.getInstance();
70 String converterXML = converter.toString(in);
76 final Calendar in = Calendar.getInstance();
77 final String converterXML = converter.toString(in);
7178
7279 TimeZone.setDefault(TimeZone.getTimeZone("Europe/Moscow"));
73 Calendar timeInMoscow = Calendar.getInstance();
80 final Calendar timeInMoscow = Calendar.getInstance();
7481 timeInMoscow.setTime(in.getTime());
75 Calendar out = (Calendar) converter.fromString(converterXML);
76 assertEquals(timeInMoscow, out);
77 }
78
82 final Calendar out = (Calendar)converter.fromString(converterXML);
83 assertEquals(timeInMoscow.getTime(), out.getTime());
84 }
85
86 public void testParsesBasicDateTime() {
87 final Calendar expected = Calendar.getInstance();
88 expected.clear();
89 expected.set(2017, 4, 7, 19, 11, 22);
90 Calendar out = (Calendar)converter.fromString("20170508T001122Z");
91 assertEquals(expected.getTime(), out.getTime());
92 expected.set(Calendar.MILLISECOND, 300);
93 out = (Calendar)converter.fromString("20170508T001122.300Z");
94 assertEquals(expected.getTime(), out.getTime());
95 expected.set(2017, 3, 20, 19, 11, 22);
96 }
97
98 public void testParsesBasicOrdinalDateTime() {
99 final Calendar expected = Calendar.getInstance();
100 expected.clear();
101 expected.set(2017, 3, 20, 19, 11, 22);
102 Calendar out = (Calendar)converter.fromString("2017111T001122Z");
103 assertEquals(expected.getTime(), out.getTime());
104 expected.set(Calendar.MILLISECOND, 300);
105 out = (Calendar)converter.fromString("2017111T001122.300Z");
106 assertEquals(expected.getTime(), out.getTime());
107 expected.set(1970, 0, 1, 13, 11, 22);
108 }
109
110 public void testParsesBasicTime() {
111 final Calendar expected = Calendar.getInstance();
112 expected.clear();
113 expected.set(1970, 0, 1, 13, 11, 22);
114 Calendar out = (Calendar)converter.fromString("181122Z");
115 assertEquals(expected.getTime(), out.getTime());
116 expected.set(Calendar.MILLISECOND, 300);
117 out = (Calendar)converter.fromString("181122.300Z");
118 assertEquals(expected.getTime(), out.getTime());
119 }
120
121 public void testParsesBasicTTime() {
122 final Calendar expected = Calendar.getInstance();
123 expected.clear();
124 expected.set(1970, 0, 1, 13, 11, 22);
125 Calendar out = (Calendar)converter.fromString("T181122Z");
126 assertEquals(expected.getTime(), out.getTime());
127 expected.set(Calendar.MILLISECOND, 300);
128 out = (Calendar)converter.fromString("T181122.300Z");
129 assertEquals(expected.getTime(), out.getTime());
130 }
131
132 public void testParsesBasicWeekDateTime() {
133 final Calendar expected = Calendar.getInstance();
134 expected.clear();
135 expected.set(2017, 4, 8, 13, 11, 22);
136 Calendar out = (Calendar)converter.fromString("2017W191T181122Z");
137 assertEquals(expected.getTime(), out.getTime());
138 expected.set(Calendar.MILLISECOND, 300);
139 out = (Calendar)converter.fromString("2017W191T181122.300Z");
140 assertEquals(expected.getTime(), out.getTime());
141 }
142
143 public void testParsesBasicDate() {
144 final Calendar expected = Calendar.getInstance();
145 expected.clear();
146 expected.set(2017, 3, 21);
147 final Calendar out = (Calendar)converter.fromString("20170421");
148 assertEquals(expected.getTime(), out.getTime());
149 }
150
151 public void testParsesBasicOrdinalDate() {
152 final Calendar expected = Calendar.getInstance();
153 expected.clear();
154 expected.set(2017, 3, 21);
155 final Calendar out = (Calendar)converter.fromString("2017111");
156 assertEquals(expected.getTime(), out.getTime());
157 }
158
159 public void testParsesBasicWeekDate() {
160 final Calendar expected = Calendar.getInstance();
161 expected.clear();
162 expected.set(2017, 3, 21);
163 final Calendar out = (Calendar)converter.fromString("2017W165");
164 assertEquals(expected.getTime(), out.getTime());
165 }
166
167 public void testParsesStandardDateTime() {
168 final Calendar expected = Calendar.getInstance();
169 expected.clear();
170 expected.set(2017, 4, 7, 19, 11, 22);
171 Calendar out = (Calendar)converter.fromString("2017-05-08T00:11:22Z");
172 assertEquals(expected.getTime(), out.getTime());
173 expected.set(Calendar.MILLISECOND, 300);
174 out = (Calendar)converter.fromString("2017-05-08T00:11:22.300Z");
175 assertEquals(expected.getTime(), out.getTime());
176 }
177
178 public void testParsesStandardOrdinalDateTime() {
179 final Calendar expected = Calendar.getInstance();
180 expected.clear();
181 expected.set(2017, 3, 20, 19, 11, 22);
182 Calendar out = (Calendar)converter.fromString("2017-111T00:11:22Z");
183 assertEquals(expected.getTime(), out.getTime());
184 expected.set(Calendar.MILLISECOND, 300);
185 out = (Calendar)converter.fromString("2017-111T00:11:22.300Z");
186 assertEquals(expected.getTime(), out.getTime());
187 }
188
189 public void testParsesStandardTime() {
190 final Calendar expected = Calendar.getInstance();
191 expected.clear();
192 expected.set(1970, 0, 1, 13, 11, 22);
193 Calendar out = (Calendar)converter.fromString("18:11:22Z");
194 assertEquals(expected.getTime(), out.getTime());
195 expected.set(Calendar.MILLISECOND, 300);
196 out = (Calendar)converter.fromString("18:11:22.300Z");
197 assertEquals(expected.getTime(), out.getTime());
198 }
199
200 public void testParsesStandardTTime() {
201 final Calendar expected = Calendar.getInstance();
202 expected.clear();
203 expected.set(1970, 0, 1, 13, 11, 22);
204 Calendar out = (Calendar)converter.fromString("T18:11:22Z");
205 assertEquals(expected.getTime(), out.getTime());
206 expected.set(Calendar.MILLISECOND, 300);
207 out = (Calendar)converter.fromString("T18:11:22.300Z");
208 assertEquals(expected.getTime(), out.getTime());
209 }
210
211 public void testParsesStandardWeekDateTime() {
212 final Calendar expected = Calendar.getInstance();
213 expected.clear();
214 expected.set(2017, 4, 8, 13, 11, 22);
215 Calendar out = (Calendar)converter.fromString("2017-W19-1T18:11:22Z");
216 assertEquals(expected.getTime(), out.getTime());
217 expected.set(Calendar.MILLISECOND, 300);
218 out = (Calendar)converter.fromString("2017-W19-1T18:11:22.300Z");
219 assertEquals(expected.getTime(), out.getTime());
220 }
221
222 public void testParsesStandardDate() {
223 final Calendar expected = Calendar.getInstance();
224 expected.clear();
225 expected.set(2017, 3, 21);
226 final Calendar out = (Calendar)converter.fromString("2017-04-21");
227 assertEquals(expected.getTime(), out.getTime());
228 }
229
230 public void testParsesStandardOrdinalDate() {
231 final Calendar expected = Calendar.getInstance();
232 expected.clear();
233 expected.set(2017, 3, 21);
234 final Calendar out = (Calendar)converter.fromString("2017-111");
235 assertEquals(expected.getTime(), out.getTime());
236 }
237
238 public void testParsesStandardWeekDate() {
239 final Calendar expected = Calendar.getInstance();
240 expected.clear();
241 expected.set(2017, 3, 21);
242 final Calendar out = (Calendar)converter.fromString("2017-W16-5");
243 assertEquals(expected.getTime(), out.getTime());
244
245 }
246
247 public void testParsesStandardDateTimeFragment() {
248 final Calendar expected = Calendar.getInstance();
249 expected.clear();
250 expected.set(2017, 3, 21);
251 expected.set(Calendar.HOUR, 11);
252 Calendar out = (Calendar)converter.fromString("2017-04-21T11");
253 assertEquals(expected.getTime(), out.getTime());
254 expected.set(Calendar.MINUTE, 22);
255 out = (Calendar)converter.fromString("2017-04-21T11:22");
256 assertEquals(expected.getTime(), out.getTime());
257 expected.set(Calendar.SECOND, 33);
258 out = (Calendar)converter.fromString("2017-04-21T11:22:33");
259 assertEquals(expected.getTime(), out.getTime());
260 expected.set(Calendar.MILLISECOND, 44);
261 out = (Calendar)converter.fromString("2017-04-21T11:22:33.044");
262 assertEquals(expected.getTime(), out.getTime());
263 out = (Calendar)converter.fromString("2017-04-21T11:22:33.044777888");
264 assertEquals(expected.getTime(), out.getTime());
265 }
266
267 public void testParsesStandardTimeFragment() {
268 final Calendar expected = Calendar.getInstance();
269 expected.clear();
270 expected.set(Calendar.HOUR, 11);
271 Calendar out = (Calendar)converter.fromString("11");
272 assertEquals(expected.getTime(), out.getTime());
273 expected.set(Calendar.MINUTE, 22);
274 out = (Calendar)converter.fromString("11:22");
275 assertEquals(expected.getTime(), out.getTime());
276 expected.set(Calendar.SECOND, 33);
277 out = (Calendar)converter.fromString("11:22:33");
278 assertEquals(expected.getTime(), out.getTime());
279 expected.set(Calendar.MILLISECOND, 44);
280 out = (Calendar)converter.fromString("11:22:33.044");
281 assertEquals(expected.getTime(), out.getTime());
282 out = (Calendar)converter.fromString("11:22:33.044777888");
283 assertEquals(expected.getTime(), out.getTime());
284 }
285
286 public void testParsesStandardDateFragment() {
287 final Calendar expected = Calendar.getInstance();
288 expected.clear();
289 expected.set(Calendar.YEAR, 2017);
290 Calendar out = (Calendar)converter.fromString("2017");
291 assertEquals(expected.getTime(), out.getTime());
292 if (JVM.is18()) { // Java 8 passes, Joda-Time fails
293 expected.set(Calendar.MONTH, 3);
294 out = (Calendar)converter.fromString("2017-04");
295 assertEquals(expected.getTime(), out.getTime());
296 }
297 }
298
299 public void testParsesStandardWeekDateFragment() {
300 final Calendar expected = Calendar.getInstance();
301 expected.clear();
302 if (!JVM.is18()) { // TODO: Java 8 fails here, Joda-Time passes
303 expected.set(2017, 3, 17);
304 final Calendar out = (Calendar)converter.fromString("2017-W16");
305 assertEquals(expected.getTime(), out.getTime());
306 }
307 }
308
79309 public void testCalendarWithExplicitTimeZone() {
80 Calendar timeInMoscow = Calendar.getInstance();
310 final Calendar timeInMoscow = Calendar.getInstance();
81311 timeInMoscow.set(2010, 6, 3, 10, 20, 36);
82312 timeInMoscow.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
83
84 String converterXML = converter.toString(timeInMoscow);
85 Calendar out = (Calendar) converter.fromString(converterXML);
313
314 final String converterXML = converter.toString(timeInMoscow);
315 final Calendar out = (Calendar)converter.fromString(converterXML);
86316 assertEquals(timeInMoscow.getTimeInMillis(), out.getTimeInMillis());
87
317
88318 out.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
89 assertEquals(timeInMoscow, out);
319 assertEquals(timeInMoscow.getTime(), out.getTime());
90320 }
91321
92322 public void testIsThreadSafe() throws InterruptedException {
97327 final int numberOfThreads = 20;
98328
99329 // spawn some concurrent threads, that hammer the converter
100 Runnable runnable = new Runnable() {
330 final Runnable runnable = new Runnable() {
101331 public void run() {
102332 for (int i = 0; i < numberOfCallsPerThread; i++) {
103333 try {
104334 converter.fromString("1993-02-14T13:10:30");
105335 results.add("PASS");
106 } catch (ConversionException e) {
336 } catch (final ConversionException e) {
107337 results.add("FAIL");
108338 } finally {
109339 synchronized (monitor) {
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007 XStream Committers.
2 * Copyright (C) 2006, 2007, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
4040 super.tearDown();
4141 }
4242
43 private XStream createXStream() {
44 XStream xs = new XStream();
45 XStream.setupDefaultSecurity(xs);
46 return xs;
47 }
48
4349 public void testISO8601SqlTimestamp() {
44 XStream xs = new XStream();
50 XStream xs = createXStream();
4551 xs.registerConverter(converter);
4652
4753 long currentTime = System.currentTimeMillis();
5864 }
5965
6066 public void testISO8601SqlTimestampWith1Milli() {
61 XStream xs = new XStream();
67 XStream xs = createXStream();
6268 xs.registerConverter(converter);
6369
6470 long currentTime = (System.currentTimeMillis() / 1000 * 1000) + 1;
7581 }
7682
7783 public void testISO8601SqlTimestampWithNanos() {
78 XStream xs = new XStream();
84 XStream xs = createXStream();
7985 xs.registerConverter(converter);
8086
8187 Timestamp ts1 = new Timestamp(System.currentTimeMillis());
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2013, 2014, 2015, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1717 import com.thoughtworks.acceptance.objects.StandardObject;
1818 import com.thoughtworks.xstream.XStream;
1919
20
2120 public class JavaBeanConverterTest extends TestCase {
21
22 private XStream createXStream() {
23 XStream xstream = new XStream();
24 XStream.setupDefaultSecurity(xstream);
25 xstream.allowTypesByWildcard(new String[] {getClass().getName()+"$*"});
26 return xstream;
27 }
2228
2329 // Different JDK versions deliver properties in different order - so sort them!
2430 static class StringComparator implements Comparator {
171177 public void testSerializesAllPrimitiveFieldsInACustomObject() {
172178 World world = new World();
173179
174 XStream xstream = new XStream();
180 XStream xstream = createXStream();
175181 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper(), new BeanProvider(
176182 new StringComparator())), XStream.PRIORITY_LOW);
177183 xstream.alias("world", World.class);
204210 World world = new World();
205211 world.setAString(null);
206212
207 XStream xstream = new XStream();
213 XStream xstream = createXStream();
208214 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper(), new BeanProvider(
209215 new StringComparator())), XStream.PRIORITY_LOW);
210216 xstream.alias("world", World.class);
285291 + " <trans>transient</trans>\n"
286292 + "</types>";
287293
288 XStream xstream = new XStream();
294 XStream xstream = createXStream();
289295 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper(), new BeanProvider(
290296 new StringComparator())), -20);
291297 xstream.alias("types", TypesOfFields.class);
320326 + " </member>\n"
321327 + "</bean>";
322328
323 XStream xstream = new XStream();
329 XStream xstream = createXStream();
324330 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()), XStream.PRIORITY_LOW);
325331 xstream.alias("bean", SimpleBean.class);
326332
332338 TypesOfFields fields = new TypesOfFields();
333339 String expected = "<types/>";
334340
335 XStream xstream = new XStream();
341 XStream xstream = createXStream();
336342 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()), XStream.PRIORITY_LOW);
337343 xstream.alias("types", TypesOfFields.class);
338344 xstream.omitField(TypesOfFields.class, "trans");
351357 + " <foo>bar</foo>\n"
352358 + "</types>";
353359
354 XStream xstream = new XStream();
360 XStream xstream = createXStream();
355361 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()), XStream.PRIORITY_LOW);
356362 xstream.alias("types", TypesOfFields.class);
357363 xstream.omitField(TypesOfFields.class, "foo");
360366 TypesOfFields unmarshalledFields = (TypesOfFields)xstream.fromXML(xml);
361367 assertEquals(fields, unmarshalledFields);
362368 }
369
370 public void testIgnoresUnknownFieldsMatchingPattern() {
371 TypesOfFields fields = new TypesOfFields();
372 fields.setNormal("foo");
373 String xml = ""
374 + "<types>\n"
375 + " <normal>foo</normal>\n"
376 + " <foo>bar</foo>\n"
377 + "</types>";
378
379 XStream xstream = createXStream();
380 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()), XStream.PRIORITY_LOW);
381 xstream.alias("types", TypesOfFields.class);
382 xstream.ignoreUnknownElements("fo.*");
383
384 TypesOfFields unmarshalledFields = (TypesOfFields)xstream.fromXML(xml);
385 assertEquals(fields, unmarshalledFields);
386 }
363387
364388 public static class UnsafeBean {
365389 public String getUnsafe() {
374398 UnsafeBean bean = new UnsafeBean();
375399 String expected = "<unsafeBean/>";
376400
377 XStream xstream = new XStream();
401 XStream xstream = createXStream();
378402 xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()), XStream.PRIORITY_LOW);
379403 xstream.alias("unsafeBean", UnsafeBean.class);
380404 xstream.omitField(UnsafeBean.class, "unsafe");
427451 }
428452
429453 public void testDoesNotSerializeOmittedInheritedFields() {
430 XStream xstream = new XStream();
454 XStream xstream = createXStream();
431455 xstream.registerConverter(
432456 new JavaBeanConverter(xstream.getMapper()), XStream.PRIORITY_LOW);
433457 xstream.omitField(Person.class, "lastName");
443467 }
444468
445469 public void testUseAliasInheritedFields() {
446 XStream xstream = new XStream();
470 XStream xstream = createXStream();
447471 xstream.registerConverter(
448472 new JavaBeanConverter(xstream.getMapper(), new BeanProvider(
449473 new StringComparator())), XStream.PRIORITY_LOW);
462486 }
463487
464488 public void testFailsFastIfPropertyIsDefinedTwice() {
465 XStream xstream = new XStream();
489 XStream xstream = createXStream();
466490 xstream.registerConverter(
467491 new JavaBeanConverter(xstream.getMapper()), XStream.PRIORITY_LOW);
468492 String input = ""
481505 assertEquals("normal", expected.get("property"));
482506 }
483507 }
508
509 public void testCanConvertDoesNotThrowException() {
510 JavaBeanConverter converter = new JavaBeanConverter(null);
511 assertTrue(converter.canConvert(SimpleBean.class));
512 assertFalse(converter.canConvert(null));
513 assertFalse(converter.canConvert(long.class));
514 assertFalse(converter.canConvert(Object[].class));
515 }
484516 }
00 /*
11 * Copyright (C) 2004, 2005, 2006 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2008, 2010, 2013 XStream Committers.
2 * Copyright (C) 2006, 2007, 2008, 2010, 2013, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
4545 public void testSerializesAllPrimitiveFieldsInACustomObject() {
4646 World world = new World();
4747
48 XStream xstream = new XStream(new XppDriver());
48 XStream xstream = createXStream();
4949 xstream.alias("world", World.class);
5050
5151 String expected =
7070 assertEquals(expected, xstream.toXML(world));
7171 }
7272
73 private XStream createXStream() {
74 XStream xstream = new XStream(new XppDriver());
75 XStream.setupDefaultSecurity(xstream);
76 return xstream;
77 }
78
7379 public static class TypesOfFields extends StandardObject {
7480 String normal = "normal";
7581 transient String trans = "transient";
8389 " <normal>normal</normal>\n" +
8490 "</types>";
8591
86 XStream xstream = new XStream(new XppDriver());
92 XStream xstream = createXStream();
8793 xstream.alias("types", TypesOfFields.class);
8894
8995 String xml = xstream.toXML(fields);
9298 }
9399
94100 public void testCanBeOverloadedToDeserializeTransientFields() {
95 XStream xstream = new XStream(new XppDriver());
101 XStream xstream = createXStream();
102 xstream.allowTypesByWildcard(new String[] {getClass().getName()+"$*"});
96103 xstream.alias("types", TypesOfFields.class);
97104 xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream
98105 .getReflectionProvider()) {
117124 }
118125
119126 public void testCustomConverterCanBeInstantiatedAndRegisteredWithDesiredPriority() {
120 XStream xstream = new XStream(new XppDriver());
127 XStream xstream = createXStream();
121128 // using default mapper instead of XStream#buildMapper()
122129 Mapper mapper = new DefaultMapper(new ClassLoaderReference(new CompositeClassLoader()));
123130 // AttributeMapper required by ReflectionConverter
00 /*
1 * Copyright (C) 2007, 2014 XStream Committers.
1 * Copyright (C) 2007, 2014, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
2626 */
2727 public class SerializableConverterTest extends TestCase {
2828
29 private XStream createXStream() {
30 XStream xstream = new XStream();
31 XStream.setupDefaultSecurity(xstream);
32 xstream.allowTypesByWildcard(new String[] {getClass().getName()+"$*"});
33 return xstream;
34 }
35
2936 static class SimpleType extends StandardObject {
3037 private String one;
3138 private String two;
5764 }
5865
5966 public void testCanOmitFieldAtSerialization() {
60 XStream xstream = new XStream();
67 XStream xstream = createXStream();
6168 xstream.alias("simple", SimpleType.class);
6269 xstream.omitField(SimpleType.class, "two");
6370
7986 }
8087
8188 public void testCanOmitFieldAtDeserialization() {
82 XStream xstream = new XStream();
89 XStream xstream = createXStream();
8390 xstream.alias("simple", SimpleType.class);
8491 xstream.omitField(SimpleType.class, "two");
8592 xstream.omitField(SimpleType.class, "x");
123130 }
124131
125132 public void testCanOmitInheritedFieldAtSerialization() {
126 XStream xstream = new XStream();
133 XStream xstream = createXStream();
127134 xstream.alias("extended", ExtendedType.class);
128135 xstream.alias("simple", SimpleType.class);
129136 xstream.omitField(SimpleType.class, "two");
152159 }
153160
154161 public void testCanOmitInheritedFieldAtDeserialization() {
155 XStream xstream = new XStream();
162 XStream xstream = createXStream();
156163 xstream.alias("extended", ExtendedType.class);
157164 xstream.alias("simple", SimpleType.class);
158165 xstream.omitField(SimpleType.class, "two");
224231 }
225232
226233 public void testCanOmitNamedFieldAtSerialization() {
227 XStream xstream = new XStream();
234 XStream xstream = createXStream();
228235 xstream.alias("simple", SimpleNamedFieldsType.class);
229236 xstream.omitField(SimpleNamedFieldsType.class, "s2");
230237
246253 }
247254
248255 public void testCanOmitNamedFieldAtDeserialization() {
249 XStream xstream = new XStream();
256 XStream xstream = createXStream();
250257 xstream.alias("simple", SimpleNamedFieldsType.class);
251258 xstream.omitField(SimpleNamedFieldsType.class, "s2");
252259 xstream.omitField(SimpleNamedFieldsType.class, "x");
270277 }
271278
272279 public void testCanAliasField() {
273 XStream xstream = new XStream();
280 XStream xstream = createXStream();
274281 xstream.alias("simple", SimpleType.class);
275282 xstream.aliasField("s2", SimpleType.class, "two");
276283
295302 }
296303
297304 public void testCanAliasNamedField() {
298 XStream xstream = new XStream();
305 XStream xstream = createXStream();
299306 xstream.alias("simple", SimpleNamedFieldsType.class);
300307 xstream.aliasField("two", SimpleNamedFieldsType.class, "s2");
301308
324331 }
325332
326333 public void testCanHandleFieldsDeclaredWithSerializableInterface() {
327 XStream xstream = new XStream();
334 XStream xstream = createXStream();
328335 xstream.alias("sertype", SerializableType.class);
329336 xstream.useAttributeFor(SerializableType.class, "serializable");
330337
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2011, 2013 XStream Committers.
2 * Copyright (C) 2006, 2007, 2011, 2013, 2016, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
66 * style license a copy of which has been included with this distribution in
77 * the LICENSE.txt file.
8 *
8 *
99 * Created on 30. April 2005 by Joe Walnes
1010 */
1111 package com.thoughtworks.xstream.io;
4040 import junit.framework.TestCase;
4141 import junit.framework.TestSuite;
4242
43
4344 public class DriverEndToEndTestSuite extends TestSuite {
4445
4546 public static Test suite() {
5455 addDriverTest(new DomDriver());
5556 addDriverTest(new JDomDriver());
5657 if (JVM.is15()) {
57 Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.xml.JDom2Driver");
58 final Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.xml.JDom2Driver");
5859 try {
5960 addDriverTest((HierarchicalStreamDriver)driverType.newInstance());
60 } catch (InstantiationException e) {
61 } catch (final InstantiationException e) {
6162 throw new AssertionFailedError("Cannot instantiate " + driverType.getName());
62 } catch (IllegalAccessException e) {
63 } catch (final IllegalAccessException e) {
6364 throw new AssertionFailedError("Cannot access default constructor of " + driverType.getName());
6465 }
6566 }
6768 addDriverTest(new KXml2Driver());
6869 addDriverTest(new StaxDriver());
6970 if (JVM.is16()) {
70 Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.xml.StandardStaxDriver");
71 final Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.xml.StandardStaxDriver");
7172 try {
7273 addDriverTest((HierarchicalStreamDriver)driverType.newInstance());
73 } catch (InstantiationException e) {
74 } catch (final InstantiationException e) {
7475 throw new AssertionFailedError("Cannot instantiate " + driverType.getName());
75 } catch (IllegalAccessException e) {
76 } catch (final IllegalAccessException e) {
7677 throw new AssertionFailedError("Cannot access default constructor of " + driverType.getName());
7778 }
7879 }
8384 addDriverTest(new XppDomDriver());
8485 addDriverTest(new XppDriver());
8586 if (JVM.is14()) {
86 Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver");
87 final Class driverType = JVM.loadClassForName("com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver");
8788 try {
8889 addDriverTest((HierarchicalStreamDriver)driverType.newInstance());
89 } catch (InstantiationException e) {
90 } catch (final InstantiationException e) {
9091 throw new AssertionFailedError("Cannot instantiate " + driverType.getName());
91 } catch (IllegalAccessException e) {
92 } catch (final IllegalAccessException e) {
9293 throw new AssertionFailedError("Cannot access default constructor of " + driverType.getName());
9394 }
9495 }
9596 }
9697
97 private void test(HierarchicalStreamDriver driver) {
98 XStream xstream = new XStream(driver);
98 private void testObject(final HierarchicalStreamDriver driver) {
99 final XStream xstream = new XStream(driver);
100 xstream.setupDefaultSecurity(xstream);
101 xstream.allowTypes(new Class[] { SampleLists.class });
99102 xstream.registerConverter(new CollectionConverter(xstream.getMapper()) {
100103
101 public Object unmarshal(HierarchicalStreamReader reader,
102 UnmarshallingContext context) {
103 ExtendedHierarchicalStreamReader exReader = (ExtendedHierarchicalStreamReader)reader;
104 public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
105 final ExtendedHierarchicalStreamReader exReader = (ExtendedHierarchicalStreamReader)reader;
104106 if (exReader.peekNextChild() == null) {
105107 return new ArrayList();
106108 }
107109 return super.unmarshal(reader, context);
108110 }
109
111
110112 });
111113
112 SampleLists in = new SampleLists();
114 final SampleLists in = new SampleLists();
113115 in.good.add("one");
114116 in.good.add("two");
115117 in.good.add("three");
116118 in.bad.add(Boolean.TRUE);
117119 in.bad.add(Boolean.FALSE);
118 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
120 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
119121 xstream.toXML(in, buffer);
120 Object out = xstream.fromXML(new ByteArrayInputStream(buffer.toByteArray()));
122 final Object out = xstream.fromXML(new ByteArrayInputStream(buffer.toByteArray()));
121123
122124 Assert.assertEquals(in, out);
123125 }
124126
127 private void testStream(final HierarchicalStreamDriver driver) {
128 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
129 final HierarchicalStreamWriter writer = driver.createWriter(buffer);
130 writer.startNode("root");
131 writer.startNode("child1");
132 writer.startNode("baby");
133 writer.endNode();
134 writer.endNode();
135 writer.startNode("child2");
136 writer.addAttribute("A", "a");
137 writer.setValue("v");
138 writer.endNode();
139 writer.endNode();
140 writer.close();
141
142 final HierarchicalStreamReader reader = driver.createReader(new ByteArrayInputStream(buffer.toByteArray()));
143 Assert.assertEquals("root", reader.getNodeName());
144 Assert.assertTrue(reader.hasMoreChildren());
145 reader.moveDown();
146 Assert.assertEquals("child1", reader.getNodeName());
147 Assert.assertEquals(0, reader.getAttributeCount());
148 Assert.assertNull(reader.getAttribute("foo"));
149 Assert.assertTrue(reader.hasMoreChildren());
150 reader.moveUp();
151 Assert.assertTrue(reader.hasMoreChildren());
152 reader.moveDown();
153 Assert.assertEquals("child2", reader.getNodeName());
154 Assert.assertEquals(1, reader.getAttributeCount());
155 Assert.assertEquals("a", reader.getAttribute("A"));
156 Assert.assertNull(reader.getAttribute("foo"));
157 //Assert.assertNull(reader.getAttribute(1));
158 Assert.assertFalse(reader.hasMoreChildren());
159 reader.moveUp();
160 Assert.assertFalse(reader.hasMoreChildren());
161 reader.close();
162 }
163
125164 private void addDriverTest(final HierarchicalStreamDriver driver) {
126 String testName = getShortName(driver);
127 addTest(new TestCase(testName) {
165 final String testName = getShortName(driver);
166 addTest(new TestCase(testName + "_Object") {
128167 protected void runTest() throws Throwable {
129 test(driver);
168 testObject(driver);
169 }
170 });
171 addTest(new TestCase(testName + "_Stream") {
172 protected void runTest() throws Throwable {
173 testStream(driver);
130174 }
131175 });
132176 }
133177
134 private String getShortName(HierarchicalStreamDriver driver) {
178 private String getShortName(final HierarchicalStreamDriver driver) {
135179 String result = driver.getClass().getName();
136180 result = result.substring(result.lastIndexOf('.') + 1);
137181 return result;
138182 }
139
140183 }
00 /*
1 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2013 XStream Committers.
1 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2013, 2016, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
5757 super.setUp();
5858 TimeZoneChanger.change("UTC");
5959 xstream = new XStream(new JettisonMappedXmlDriver());
60 XStream.setupDefaultSecurity(xstream);
61 xstream.allowTypesByWildcard(new String[]{
62 getClass().getName() + "$*", "com.thoughtworks.acceptance.objects.*"});
6063 xstream.alias("category", Category.class);
6164 xstream.alias("product", Product.class);
6265 }
9093 Configuration config = new Configuration();
9194 setTypeConverter.invoke(config, new Object[]{typeConverter});
9295 xstream = new XStream(new JettisonMappedXmlDriver(config));
96 XStream.setupDefaultSecurity(xstream);
97 xstream.allowTypesByWildcard(new String[]{"com.thoughtworks.acceptance.objects.*"});
9398 xstream.alias("product", Product.class);
9499 Product product = new Product("Banana", "123", 23.00);
95100 String result = xstream.toXML(product);
236241 xstream.alias("topic", Topic.class);
237242 String json = xstream.toXML(topic1);
238243 assertEquals(
239 "{'topic':{'id':4711,'description':'JSON','createdOn':{'@class':'sql-timestamp','$':'1970-01-01 00:00:01.0'}}}"
244 "{'topic':{'id':4711,'description':'JSON','createdOn':{'@class':'sql-timestamp','$':'1970-01-01 00:00:01'}}}"
240245 .replace('\'', '"'), json);
241246 Topic topic2 = (Topic)xstream.fromXML(json);
242247 assertEquals(json, xstream.toXML(topic2));
00 /*
1 * Copyright (C) 2013 XStream Committers.
1 * Copyright (C) 2013, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
3030 protected void setUp() throws Exception {
3131 super.setUp();
3232 xstream = new XStream();
33 XStream.setupDefaultSecurity(xstream);
34 xstream.allowTypesByWildcard(new String[] {"com.thoughtworks.acceptance.someobjects.*"});
3335 xstream.alias("x", X.class);
3436 }
3537
00 /*
11 * Copyright (C) 2004 Joe Walnes.
2 * Copyright (C) 2006, 2007 XStream Committers.
2 * Copyright (C) 2006, 2007, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
3131 protected void setUp() throws Exception {
3232 super.setUp();
3333 xstream = new XStream();
34 XStream.setupDefaultSecurity(xstream);
35 xstream.allowTypesByWildcard(new String[] {"com.thoughtworks.acceptance.someobjects.*"});
3436 xstream.alias("x", X.class);
3537 }
3638
00 /*
1 * Copyright (C) 2006, 2007 XStream Committers.
1 * Copyright (C) 2006, 2007, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
5050 System.setProperty(XMLOutputFactory.class.getName(), XMLOutputFactoryBase.class.getName());
5151 final MyStaxDriver driver = new MyStaxDriver();
5252 xstream = new XStream(driver);
53 XStream.setupDefaultSecurity(xstream);
5354 assertBothWays("Hi", "<?xml version='1.0' encoding='utf-8'?><string>Hi</string>");
5455 assertTrue(driver.createStaxReaderCalled);
5556 assertTrue(driver.createStaxWriterCalled);
00 /*
11 * Copyright (C) 2005 Joe Walnes.
2 * Copyright (C) 2006, 2007, 2011, 2013 XStream Committers.
2 * Copyright (C) 2006, 2007, 2011, 2013, 2016 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1919 import com.thoughtworks.acceptance.objects.SampleMaps;
2020 import com.thoughtworks.acceptance.objects.Software;
2121 import com.thoughtworks.xstream.core.ClassLoaderReference;
22 import com.thoughtworks.xstream.core.JVM;
2223
2324 import junit.framework.TestCase;
2425
2526 public class ImplicitCollectionMapperTest extends TestCase {
2627
2728 private ImplicitCollectionMapper implicitCollections = new ImplicitCollectionMapper(
28 new DefaultMapper(new ClassLoaderReference(null)));
29 new DefaultMapper(new ClassLoaderReference(null)), JVM.newReflectionProvider());
2930
3031 public void testAllowsFieldsToBeMarkedAsImplicitCollectionsToBeAdded() {
3132 implicitCollections.add(SampleLists.class, "good", null);
00 /*
1 * Copyright (C) 2008, 2009 XStream Committers.
1 * Copyright (C) 2008, 2009, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
1515 import java.util.HashMap;
1616 import java.util.Iterator;
1717 import java.util.Map;
18
19 import com.thoughtworks.xstream.XStream;
20 import com.thoughtworks.xstream.io.xml.DomDriver;
1821
1922 import junit.framework.TestCase;
2023
5558 dir.delete();
5659 }
5760
61 private XStream createXStream() {
62 XStream xstream = new XStream(new DomDriver());
63 XStream.setupDefaultSecurity(xstream);
64 return xstream;
65 }
66
5867 public void testConcatenatesXmlExtensionWhileGettingAFilename() {
59 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
68 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
6069 assertEquals("string@guilherme.xml", strategy.getName("guilherme"));
6170 }
6271
6372 public void testConcatenatesXmlExtensionWhileExtractingAKey() {
64 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
73 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
6574 assertEquals("guilherme", strategy.extractKey("string@guilherme.xml"));
6675 }
6776
6877 public void testEscapesNonAcceptableCharacterWhileExtractingAKey() {
69 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
78 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
7079 assertEquals("../guilherme", strategy.extractKey("string@..%2Fguilherme.xml"));
7180 }
7281
7382 public void testEscapesNonAcceptableCharacterWhileGettingAFilename() {
74 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
83 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
7584 assertEquals("string@..%2Fguilherme.xml", strategy.getName("../guilherme"));
7685 }
7786
7887 public void testEscapesUTF8NonAcceptableCharacterWhileGettingAFilename() {
79 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
88 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
8089 assertEquals("string@\u5377guilherme.xml", strategy.getName("\u5377guilherme"));
8190 }
8291
8392 public void testEscapesUTF8NonAcceptableCharacterWhileExtractingAKey() {
84 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
93 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
8594 assertEquals("\u5377guilherme", strategy.extractKey("string@\u5377guilherme.xml"));
8695 }
8796
8897 public void testEscapesPercentageWhileGettingAFilename() {
89 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
98 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
9099 assertEquals("string@%25guilherme.xml", strategy.getName("%guilherme"));
91100 }
92101
93102 public void testEscapesPercentageWhileExtractingAKey() {
94 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
103 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
95104 assertEquals("%guilherme", strategy.extractKey("string@%25guilherme.xml"));
96105 }
97106
98107 public void testEscapesNullKeyWhileGettingAFileName() {
99 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
108 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
100109 assertEquals("null@null.xml", strategy.getName(null));
101110 }
102111
103112 public void testRestoresTypeOfKey() throws MalformedURLException {
104 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
113 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
105114 assertEquals(new URL("http://xstream.codehaus.org"), strategy
106115 .extractKey("url@http%3A%2F%2Fxstream.codehaus.org.xml"));
107116 }
108117
109118 public void testEscapesNullKeyWhileExtractingKey() {
110 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
119 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
111120 assertNull(strategy.extractKey("null@null.xml"));
112121 }
113122
114123 public void testWritesASingleFile() {
115 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
124 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
116125 strategy.put("guilherme", "aCuteString");
117126 File file = new File(baseDir, "string@guilherme.xml");
118127 assertTrue(file.isFile());
119128 }
120129
121130 public void testWritesTwoFiles() {
122 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
131 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
123132 strategy.put("guilherme", "aCuteString");
124133 strategy.put("silveira", "anotherCuteString");
125134 assertTrue(new File(baseDir, "string@guilherme.xml").isFile());
127136 }
128137
129138 public void testRemovesAWrittenFile() {
130 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
139 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
131140 strategy.put("guilherme", "aCuteString");
132141 assertTrue(new File(baseDir, "string@guilherme.xml").isFile());
133142 String aCuteString = (String)strategy.remove("guilherme");
136145 }
137146
138147 public void testRemovesAnInvalidFile() {
139 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
148 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
140149 String aCuteString = (String)strategy.remove("guilherme");
141150 assertNull(aCuteString);
142151 }
143152
144153 public void testHasZeroLength() {
145 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
154 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
146155 assertEquals(0, strategy.size());
147156 }
148157
149158 public void testHasOneItem() {
150 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
159 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
151160 strategy.put("guilherme", "aCuteString");
152161 assertEquals(1, strategy.size());
153162 }
154163
155164 public void testHasTwoItems() {
156 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
165 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
157166 strategy.put("guilherme", "aCuteString");
158167 strategy.put("silveira", "anotherCuteString");
159168 assertEquals(2, strategy.size());
160169 }
161170
162171 public void testIsNotEmpty() {
163 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
172 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
164173 strategy.put("guilherme", "aCuteString");
165174 assertEquals("Map should not be empty", 1, strategy.size());
166175 }
167176
168177 public void testDoesNotContainKey() {
169 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
178 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
170179 assertFalse(strategy.containsKey("guilherme"));
171180 }
172181
173182 public void testContainsKey() {
174 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
183 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
175184 strategy.put("guilherme", "aCuteString");
176185 assertTrue(strategy.containsKey("guilherme"));
177186 }
178187
179188 public void testGetsAFile() {
180 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
189 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
181190 strategy.put("guilherme", "aCuteString");
182191 assertTrue(new File(baseDir, "string@guilherme.xml").isFile());
183192 String aCuteString = (String)strategy.get("guilherme");
185194 }
186195
187196 public void testGetsAnInvalidFile() {
188 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
197 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
189198 String aCuteString = (String)strategy.get("guilherme");
190199 assertNull(aCuteString);
191200 }
192201
193202 public void testRewritesASingleFile() {
194 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
203 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
195204 strategy.put("guilherme", "aCuteString");
196205 File file = new File(baseDir, "string@guilherme.xml");
197206 assertTrue(file.isFile());
200209 }
201210
202211 public void testIsEmpty() {
203 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
212 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
204213 assertEquals("Map should be empty", 0, strategy.size());
205214 }
206215
208217 Map original = new HashMap();
209218 original.put("guilherme", "aCuteString");
210219 original.put("silveira", "anotherCuteString");
211 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
220 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
212221 strategy.put("guilherme", "aCuteString");
213222 strategy.put("silveira", "anotherCuteString");
214223 for (Iterator iter = original.keySet().iterator(); iter.hasNext();) {
217226 }
218227
219228 public void testIteratesOverEntryAndChecksItsKeyWithAnotherInstance() {
220 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
229 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
221230 strategy.put("guilherme", "aCuteString");
222231 strategy.put("silveira", "anotherCuteString");
223232 FilePersistenceStrategy built = new FilePersistenceStrategy(baseDir);
228237 }
229238
230239 public void testRemovesAnItemThroughIteration() {
231 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
240 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
232241 strategy.put("guilherme", "aCuteString");
233242 strategy.put("silveira", "anotherCuteString");
234243 for (Iterator iter = strategy.iterator(); iter.hasNext();) {
241250 }
242251
243252 public void testRewritesAFile() {
244 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
253 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
245254 strategy.put("guilherme", "aCuteString");
246255 strategy.put("guilherme", "anotherCuteString");
247256 assertEquals("anotherCuteString", strategy.get("guilherme"));
248257 }
249258
250259 public void testPutReturnsTheOldValueWhenRewritingAFile() {
251 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir);
260 FilePersistenceStrategy strategy = new FilePersistenceStrategy(baseDir, createXStream());
252261 strategy.put("guilherme", "aCuteString");
253262 assertEquals("aCuteString", strategy.put("guilherme", "anotherCuteString"));
254263 }
00 /*
11 * Copyright (C) 2006 Joe Walnes.
2 * Copyright (C) 2007, 2008, 2009 XStream Committers.
2 * Copyright (C) 2007, 2008, 2009, 2017 XStream Committers.
33 * All rights reserved.
44 *
55 * The software in this package is published under the terms of the BSD
1414 import java.util.HashMap;
1515 import java.util.Iterator;
1616 import java.util.Map;
17
18 import com.thoughtworks.xstream.XStream;
19 import com.thoughtworks.xstream.io.xml.DomDriver;
1720
1821 import junit.framework.TestCase;
1922
5356 dir.delete();
5457 }
5558
59 private XStream createXStream() {
60 XStream xstream = new XStream(new DomDriver());
61 XStream.setupDefaultSecurity(xstream);
62 return xstream;
63 }
64
5665 public void testConcatenatesXmlExtensionWhileGettingAFilename() {
57 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
66 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
5867 assertEquals("guilherme.xml", strategy.getName("guilherme"));
5968 }
6069
6170 public void testConcatenatesXmlExtensionWhileExtractingAKey() {
62 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
71 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
6372 assertEquals("guilherme", strategy.extractKey("guilherme.xml"));
6473 }
6574
6675 public void testEscapesNonAcceptableCharacterWhileExtractingAKey() {
67 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
76 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
6877 assertEquals("../guilherme", strategy.extractKey("_2e__2e__2f_guilherme.xml"));
6978 }
7079
7180 public void testEscapesNonAcceptableCharacterWhileGettingAFilename() {
72 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
81 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
7382 assertEquals("_2e__2e__2f_guilherme.xml", strategy.getName("../guilherme"));
7483 }
7584
7685 public void testEscapesUTF8NonAcceptableCharacterWhileGettingAFilename() {
77 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
86 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
7887 assertEquals("_5377_guilherme.xml", strategy.getName("\u5377guilherme"));
7988 }
8089
8190 public void testEscapesUTF8NonAcceptableCharacterWhileExtractingAKey() {
82 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
91 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
8392 assertEquals("\u5377guilherme", strategy.extractKey("_5377_guilherme.xml"));
8493 }
8594
8695 public void testEscapesUnderlineWhileGettingAFilename() {
87 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
96 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
8897 assertEquals("__guilherme.xml", strategy.getName("_guilherme"));
8998 }
9099
91100 public void testEscapesUnderlineWhileExtractingAKey() {
92 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
101 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
93102 assertEquals("_guilherme", strategy.extractKey("__guilherme.xml"));
94103 }
95104
96105 public void testEscapesNullKeyWhileGettingAFileName() {
97 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
106 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
98107 assertEquals("_0_.xml", strategy.getName(null));
99108 }
100109
101110 public void testEscapesNullKeyWhileExtractingKey() {
102 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
111 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
103112 assertNull(strategy.extractKey("_0_.xml"));
104113 }
105114
106115 public void testWritesASingleFile() {
107 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
116 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
108117 strategy.put("guilherme", "aCuteString");
109118 File file = new File(baseDir, "guilherme.xml");
110119 assertTrue(file.exists());
111120 }
112121
113122 public void testWritesTwoFiles() {
114 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
123 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
115124 strategy.put("guilherme", "aCuteString");
116125 strategy.put("silveira", "anotherCuteString");
117126 assertTrue(new File(baseDir, "guilherme.xml").exists());
119128 }
120129
121130 public void testRemovesAWrittenFile() {
122 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
131 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
123132 strategy.put("guilherme", "aCuteString");
124133 assertTrue(new File(baseDir, "guilherme.xml").exists());
125134 String aCuteString = (String)strategy.remove("guilherme");
128137 }
129138
130139 public void testRemovesAnInvalidFile() {
131 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
140 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
132141 String aCuteString = (String)strategy.remove("guilherme");
133142 assertNull(aCuteString);
134143 }
135144
136145 public void testHasZeroLength() {
137 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
146 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
138147 assertEquals(0, strategy.size());
139148 }
140149
141150 public void testHasOneItem() {
142 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
151 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
143152 strategy.put("guilherme", "aCuteString");
144153 assertEquals(1, strategy.size());
145154 }
146155
147156 public void testHasTwoItems() {
148 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
157 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
149158 strategy.put("guilherme", "aCuteString");
150159 strategy.put("silveira", "anotherCuteString");
151160 assertEquals(2, strategy.size());
152161 }
153162
154163 public void testIsNotEmpty() {
155 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
164 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
156165 strategy.put("guilherme", "aCuteString");
157166 assertEquals("Map should not be empty", 1, strategy.size());
158167 }
159168
160169 public void testDoesNotContainKey() {
161 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
170 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
162171 assertFalse(strategy.containsKey("guilherme"));
163172 }
164173
165174 public void testContainsKey() {
166 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
175 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
167176 strategy.put("guilherme", "aCuteString");
168177 assertTrue(strategy.containsKey("guilherme"));
169178 }
170179
171180 public void testGetsAFile() {
172 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
181 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
173182 strategy.put("guilherme", "aCuteString");
174183 assertTrue(new File(baseDir, "guilherme.xml").exists());
175184 String aCuteString = (String)strategy.get("guilherme");
177186 }
178187
179188 public void testGetsAnInvalidFile() {
180 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
189 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
181190 String aCuteString = (String)strategy.get("guilherme");
182191 assertNull(aCuteString);
183192 }
184193
185194 public void testRewritesASingleFile() {
186 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
195 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
187196 strategy.put("guilherme", "aCuteString");
188197 File file = new File(baseDir, "guilherme.xml");
189198 assertTrue(file.exists());
192201 }
193202
194203 public void testIsEmpty() {
195 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
204 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
196205 assertEquals("Map should be empty", 0, strategy.size());
197206 }
198207
200209 Map original = new HashMap();
201210 original.put("guilherme", "aCuteString");
202211 original.put("silveira", "anotherCuteString");
203 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
212 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
204213 strategy.put("guilherme", "aCuteString");
205214 strategy.put("silveira", "anotherCuteString");
206215 for (Iterator iter = original.keySet().iterator(); iter.hasNext();) {
210219
211220 // actually an acceptance test?
212221 public void testIteratesOverEntryAndChecksItsKeyWithAnotherInstance() {
213 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
222 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
214223 strategy.put("guilherme", "aCuteString");
215224 strategy.put("silveira", "anotherCuteString");
216225 FileStreamStrategy built = new FileStreamStrategy(baseDir);
221230 }
222231
223232 public void testRemovesAnItemThroughIteration() {
224 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
233 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
225234 strategy.put("guilherme", "aCuteString");
226235 strategy.put("silveira", "anotherCuteString");
227236 for (Iterator iter = strategy.iterator(); iter.hasNext();) {
234243 }
235244
236245 public void testRewritesAFile() {
237 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
246 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
238247 strategy.put("guilherme", "aCuteString");
239248 strategy.put("guilherme", "anotherCuteString");
240249 assertEquals("anotherCuteString", strategy.get("guilherme"));
241250 }
242251
243252 public void testPutReturnsTheOldValueWhenRewritingAFile() {
244 FileStreamStrategy strategy = new FileStreamStrategy(baseDir);
253 FileStreamStrategy strategy = new FileStreamStrategy(baseDir, createXStream());
245254 strategy.put("guilherme", "aCuteString");
246255 assertEquals("aCuteString", strategy.put("guilherme", "anotherCuteString"));
247256 }
248
249257 }
00 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
11 <!--
22 Copyright (C) 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2009, 2011, 2012, 2013 XStream committers.
3 Copyright (C) 2006, 2007, 2009, 2011, 2012, 2013, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
1313 <parent>
1414 <groupId>com.thoughtworks.xstream</groupId>
1515 <artifactId>xstream-parent</artifactId>
16 <version>1.4.9</version>
16 <version>1.4.10</version>
1717 </parent>
1818 <artifactId>xstream-benchmark</artifactId>
1919 <packaging>jar</packaging>
2222
2323 <profiles>
2424 <profile>
25 <id>jdk18-ge</id>
25 <id>jdk18</id>
2626 <activation>
27 <jdk>[1.8,)</jdk>
27 <jdk>1.8</jdk>
2828 </activation>
2929 <build>
3030 <plugins>
1313 <parent>
1414 <groupId>com.thoughtworks.xstream</groupId>
1515 <artifactId>xstream-parent</artifactId>
16 <version>1.4.9</version>
16 <version>1.4.10</version>
1717 </parent>
1818 <artifactId>xstream-distribution</artifactId>
1919 <packaging>pom</packaging>
4747
4848 <profiles>
4949 <profile>
50 <id>jdk18-ge</id>
50 <id>jdk18</id>
5151 <activation>
52 <jdk>[1.8,)</jdk>
52 <jdk>1.8</jdk>
5353 </activation>
5454 <build>
5555 <plugins>
0 <html>
1 <!--
2 Copyright (C) 2017 XStream committers.
3 All rights reserved.
4
5 The software in this package is published under the terms of the BSD
6 style license a copy of which has been included with this distribution in
7 the LICENSE.txt file.
8
9 Created on 25. April 2017 by Joerg Schaible
10 -->
11 <head>
12 <title>CVE-2013-7285</title>
13 </head>
14 <body>
15
16 <h2 id="vulnerability">Vulnerability</h2>
17
18 <p>CVE-2013-7285: XStream can be used for Remote Code Execution.</p>
19
20 <h2 id="affected_versions">Affected Versions</h2>
21
22 <p>All versions until and including version 1.4.6 are affected, but a <a href="#workaround">workaround</a> exist.</p>
23
24 <h2 id="description">Description</h2>
25
26 <p>The processed stream at unmarshalling time contains type information to recreate the formerly written objects.
27 XStream creates therefore new instances based on these type information. An attacker can manipulate the processed
28 input stream and replace or inject objects, that can execute arbitrary shell commands.</p>
29
30 <h2 id="reproduction">Steps to Reproduce</h2>
31
32 <p>Create a simple interface e.g. named <em>Contact</em> and an implementation class. Use XStream to marshal such
33 an object to XML. Replace the XML with following snippet and unmarshal it again with XStream:</p>
34 <div class="Source XML"><pre>&lt;contact&gt;
35 &lt;dynamic-proxy&gt;
36 &lt;interface&gt;org.company.model.Contact&lt;/interface&gt;
37 &lt;handler class='java.beans.EventHandler'&gt;
38 &lt;target class='java.lang.ProcessBuilder'&gt;
39 &lt;command&gt;
40 &lt;string&gt;calc.exe&lt;/string&gt;
41 &lt;/command&gt;
42 &lt;/target&gt;
43 &lt;action&gt;start&lt;/action&gt;
44 &lt;handler&gt;
45 &lt;/dynamic-proxy&gt;
46 &lt;/contact&gt;
47 </pre></div>
48 <div class="Source Java"><pre>XStream xstream = new XStream();
49 Contact contact = (Contact)xstream.fromXML(xml);
50 </pre></div>
51
52 <p>Then as soon as the code calls any method on the Contact instance, the payload gets executed, e.g.
53 contact.getFirstName().</p>
54
55 <p>Note, this example uses XML, but the attack can be performed for any supported format. e.g. JSON.</p>
56
57 <h2 id="impact">Impact</h2>
58
59 <p>The vulnerability may allow a remote attacker to run arbitrary shell commands only by manipulating the processed
60 input stream.</p>
61
62 <h2 id="workaround">Workaround</h2>
63 <p>Users can register an own converter for dynamic proxies, the <em>java.beans.EventHandler</em> type or for the
64 <em>java.lang.ProcessBuilder</em> type, that also protects against an attack for this special case:</p>
65 <div class="Source Java"><pre>xstream.registerConverter(new Converter() {
66 public boolean canConvert(Class type) {
67 return type != null &amp;&amp; (type == java.beans.EventHandler || type == java.lang.ProcessBuilder || Proxy.isProxy(type));
68 }
69
70 public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
71 throw new ConversionException("Unsupported type due to security reasons.");
72 }
73
74 public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
75 throw new ConversionException("Unsupported type due to security reasons.");
76 }
77 }, XStream.PRIORITY_LOW);
78 </pre></div>
79
80 </body>
81 </html>
0 <html>
1 <!--
2 Copyright (C) 2017 XStream committers.
3 All rights reserved.
4
5 The software in this package is published under the terms of the BSD
6 style license a copy of which has been included with this distribution in
7 the LICENSE.txt file.
8
9 Created on 3. May 2017 by Joerg Schaible
10 -->
11 <head>
12 <title>CVE-2016-3674</title>
13 </head>
14 <body>
15
16 <h2 id="vulnerability">Vulnerability</h2>
17
18 <p>CVE-2016-3674: XML External Entity (XXE) Vulnerability in XStream.</p>
19
20 <h2 id="affected_versions">Affected Versions</h2>
21
22 <p>XStream is not vulnerable, if the default XML Pull Parser is used (Xpp3 or kXML2), since these parser types do
23 not process XML entities at all.</p>
24
25 <p>All versions until and including version 1.4.8 are affected, if they use explicitly one of the following parsers:</p>
26 <ul>
27 <li>DOM4J</li>
28 <li>DOM</li>
29 <li>JDOM</li>
30 <li>JDOM2</li>
31 <li>StAX implementation</li>
32 <li>XOM</li>
33 </ul>
34
35 <p>XStream's HierarchicalStreamDriver implementations will now explicitly turn off the processing of external
36 entities, but the setting is not respected by all parser implementations. XStream stays therefore vulnerable in
37 future, if one of the following parser implementations is explicitly used:</p>
38 <ul>
39 <li>DOM implementation from Java 5 runtime and below</li>
40 <li>StAX implementation from Java 6 runtime and below</li>
41 <li>StAX implementation from BEA (old reference implementation)</li>
42 <li>XOM</li>
43 </ul>
44
45 <h2 id="description">Description</h2>
46
47 <p>XStream supports a lot of different XML parsers. Some of those can also process external entities which was
48 enabled by default. An attacker could therefore provide manipulated XML as input to access data on the file
49 system, see <a href="https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing">XXE Vulnerability</a>.</p>
50
51 <h2 id="reproduction">Steps to Reproduce</h2>
52
53 <p>An attacker might use external general or parameter entities:</p>
54 <div class="Source XML"><pre>&lt;?xml version=&quot;1.0&quot;&gt;
55 &lt;!DOCTYPE root [
56 &lt;!ELEMENT string (#PCDATA)&gt;
57 &lt;!ENTITY content SYSTEM &quot;file:/etc/passwd&quot;&gt;
58 ]&gt;&lt;string&gt;&amp;content;&lt;/string&gt;
59 </pre></div>
60 <div class="Source XML"><pre>&lt;?xml version=&quot;1.0&quot;&gt;
61 &lt;!DOCTYPE root [
62 &lt;!ELEMENT string (#PCDATA)&gt;
63 &lt;!ENTITY content SYSTEM &quot;file:/etc/passwd&quot;&gt;
64 %content;
65 ]&gt;&lt;string&gt;test&lt;/string&gt;
66 </pre></div>
67 <p>Use one of the XML documents above, initialize XStream with a vulnerable parser and unmarshal the XML:</p>
68 <div class="Source Java"><pre>XStream xstream = new XStream();
69 String s = (String)xstream.fromXML(xml);
70 </pre></div>
71
72 <h2 id="impact">Impact</h2>
73
74 <p>The vulnerability may allow a remote attacker to retrieve the content of arbitrary files with known locations in
75 a local file system if the Java process has read access.</p>
76
77 <h2 id="workarounds">Workaround</h2>
78
79 <p>Use one of the XML Pull Parser implementations.</p>
80
81 </body>
82 </html>
0 <html>
1 <!--
2 Copyright (C) 2017 XStream committers.
3 All rights reserved.
4
5 The software in this package is published under the terms of the BSD
6 style license a copy of which has been included with this distribution in
7 the LICENSE.txt file.
8
9 Created on 25. April 2017 by Joerg Schaible
10 -->
11 <head>
12 <title>CVE-2017-7957</title>
13 </head>
14 <body>
15
16 <h2 id="vulnerability">Vulnerability</h2>
17
18 <p>CVE-2017-7957: XStream can cause a Denial of Service when unmarshalling void.</p>
19
20 <h2 id="affected_versions">Affected Versions</h2>
21
22 <p>All versions until and including version 1.4.9 are affected, but <a href="#workarounds">workarounds</a> exist.</p>
23
24 <h2 id="description">Description</h2>
25
26 <p>The processed stream at unmarshalling time contains type information to recreate the formerly written objects.
27 XStream creates therefore new instances based on these type information. The crash occurs if this information
28 advises XStream to create an instance of the primitive type <em>void</em>. This situation can only happen if an
29 attacker was able to manipulate the incoming data, since such an instance does not exist and cannot be marshalled
30 therefore in first place.</p>
31
32 <h2 id="reproduction">Steps to Reproduce</h2>
33
34 <p>The simplest way to demonstrate the problem is with this snippet:</p>
35 <div class="Source Java"><pre>XStream xstream = new XStream();
36 xstream.fromXML("&lt;void/&gt;");
37 </pre></div>
38
39 <p>If XStream is configured to read JSON, the equivalent line is:</p>
40 <div class="Source Java"><pre>xstream.fromXML("{'void':null}");
41 </pre></div>
42
43 <p>However, the problematic type information can be injected at any position in
44 the provided stream, in XML just by adding a class attribute:</p>
45 <div class="Source Java"><pre>xstream.fromXML("&lt;string class='void'&gt;Hello, world!&lt;/string&gt;");
46 </pre></div>
47
48 <h2 id="impact">Impact</h2>
49
50 <p>The vulnerability may allow a remote attacker to cause a crash on the target system resulting in a denial of
51 service only by manipulating the processed input stream.</p>
52
53 <h2 id="workarounds">Workarounds</h2>
54 <p>XStream contains since version 1.4.7 a <a href="security.html">security framework</a> to prevent an attack
55 described in CVE-2013-7285. This framework can also be used to suppress the current vulnerability by setting:</p>
56 <div class="Source Java"><pre>xstream.denyTypes(void.class, Void.class);
57 </pre></div>
58
59 <p>Users of older XStream releases can register an own converter for the <em>void</em> type, that also protects
60 against this attack:</p>
61 <div class="Source Java"><pre>xstream.registerConverter(new Converter() {
62 public boolean canConvert(Class type) {
63 return Void.class == type || void.class == type;
64 }
65
66 public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
67 throw new ConversionException("Type void cannot have an instance");
68 }
69
70 public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
71 throw new ConversionException("Type void cannot have an instance");
72 }
73 }, XStream.PRIORITY_VERY_HIGH);
74 </pre></div>
75
76 </body>
77 </html>
00 <html>
11 <!--
22 Copyright (C) 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2011 XStream committers.
3 Copyright (C) 2006, 2007, 2011, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
3737 public class Tutorial {
3838
3939 public static void main(String[] args) {
40 XStream stream = new XStream();
40 XStream xstream = new XStream();
4141 RendezvousMessage msg = new RendezvousMessage(15);
42 System.out.println(stream.toXML(msg));
42 System.out.println(xstream.toXML(msg));
4343 }
4444
4545 }
7373 this type:</p>
7474 <div class="Source Java"><pre>
7575 public static void main(String[] args) {
76 XStream stream = new XStream();
76 XStream xstream = new XStream();
7777 xstream.processAnnotations(RendezvousMessage.class);
7878 RendezvousMessage msg = new RendezvousMessage(15);
79 System.out.println(stream.toXML(msg));
79 System.out.println(xstream.toXML(msg));
8080 }
8181 </pre></div>
8282 <p>Note that we have called the processAnnotations method of XStream. This method registers all aliases annotations in
112112 </pre></div>
113113 <div class="Source Java"><pre>
114114 public static void main(String[] args) {
115 XStream stream = new XStream();
115 XStream xstream = new XStream();
116116 xstream.processAnnotations(RendezvousMessage.class);
117117 RendezvousMessage msg = new RendezvousMessage(15, "firstPart","secondPart");
118 System.out.println(stream.toXML(msg));
118 System.out.println(xstream.toXML(msg));
119119 }
120120 </pre></div>
121121 <p>The resulting XML shows the collection name before its elements:</p>
481481 public class Tutorial {
482482
483483 public static void main(String[] args) {
484 XStream stream = new XStream();
484 XStream xstream = new XStream();
485485 xstream.autodetectAnnotations(true);
486486 RendezvousMessage msg = new RendezvousMessage(15);
487 System.out.println(stream.toXML(msg));
487 System.out.println(xstream.toXML(msg));
488488 }
489489
490490 }
00 <html>
11 <!--
2 Copyright (C) 2015, 2016 XStream committers.
2 Copyright (C) 2015, 2016, 2017 XStream committers.
33 All rights reserved.
44
55 The software in this package is published under the terms of the BSD
3434 measurement options, see online help. The maximum deviation for each benchmark is recorded in the reference files
3535 of the distributed ZIP file. The benchmark is executed on Linux 4.1.12 Gentoo 64-bit system with an Intel Core i7
3636 CPU 920 of 2.67 GHz. Note again, that these values are no replacement for real profiler results and they may
37 vary from run to run (see reference files) due to this machine's background processes on a single CPU. However, it
38 can give you some idea of what you can expect using different parser technologies.</p>
37 vary from run to run (see reference files) due to this machine's background processes. However, it can give you some
38 idea of what you can expect using different parser technologies.</p>
3939
4040 <h2 id="parser">Parser Benchmark</h2>
4141
5050 <th>Nested</th>
5151 </tr>
5252 <tr>
53 <th>W3C DOM (Oracle JDK 1.8.0_66)</th>
54 <td>10037380.795</td>
55 <td>54234293.351</td>
56 <td>1917332.056</td>
53 <th>W3C DOM (Oracle JDK 1.8.0_131)</th>
54 <td>9781342.261</td>
55 <td>52632217.909</td>
56 <td>5103544.581</td>
5757 </tr>
5858 <tr>
5959 <th>JDOM (1.1.3)</th>
60 <td>6368317.636</td>
61 <td>7910979.223</td>
62 <td>3862796.027</td>
60 <td>6303281.491</td>
61 <td>7066427.706</td>
62 <td>14168656.571</td>
6363 </tr>
6464 <tr>
6565 <th>JDOM 2 (2.0.5)</th>
66 <td>5767640.105</td>
67 <td>10570210.653</td>
68 <td>2980906.727</td>
66 <td>5912161.208</td>
67 <td>9159926.646</td>
68 <td>10786607.592</td>
6969 </tr>
7070 <tr>
7171 <th>DOM4J (1.6.1)</th>
72 <td>7816280.084</td>
73 <td>92998322.952</td>
74 <td>2108075.646</td>
72 <td>7737425.182</td>
73 <td>93587705.473</td>
74 <td>5832065.181</td>
7575 </tr>
7676 <tr>
7777 <th>XOM (1.1)</th>
78 <td>7950778.533</td>
79 <td>38704485.310</td>
80 <td>2471019.743</td>
78 <td>8086930.673</td>
79 <td>36550127.033</td>
80 <td>7799715.857</td>
8181 </tr>
8282 <tr>
8383 <th>StAX (BEA 1.2.0)</th>
84 <td>3108517.699</td>
85 <td>1310406.961</td>
86 <td>669111.164</td>
84 <td>2658801.705</td>
85 <td>716108.170</td>
86 <td>579754.753</td>
8787 </tr>
8888 <tr>
8989 <th>StAX (Woodstox 3.2.7)</th>
90 <td>1884858.525</td>
91 <td>1240767.393</td>
92 <td>650470.623</td>
93 </tr>
94 <tr>
95 <th>StAX (Oracle JDK 1.8.0_66)</th>
96 <td>7366387.272</td>
97 <td>1334398.501</td>
98 <td>688229.709</td>
90 <td>1888835.931</td>
91 <td>622817.191</td>
92 <td>645986.465</td>
93 </tr>
94 <tr>
95 <th>StAX (Oracle JDK 1.8.0_131)</th>
96 <td>7314997.951</td>
97 <td>727323.621</td>
98 <td>594349.622</td>
9999 </tr>
100100 <tr>
101101 <th>XPP (Xpp3 min 1.1.4c)</th>
102 <td>2109341.076</td>
103 <td>1309607.210</td>
104 <td>3301732.767</td>
102 <td>2084516.475</td>
103 <td>693019.370</td>
104 <td>12426115.039</td>
105105 </tr>
106106 <tr>
107107 <th>XPP (kXML2 min 2.3.0)</th>
108 <td>3391204.266</td>
109 <td>1514514.680</td>
110 <td>8105934.241</td>
111 </tr>
112 <tr>
113 <th>Binary (XStream 1.4.9)</th>
114 <td>1144243.750</td>
115 <td>1062031.901</td>
116 <td>496839.565</td>
108 <td>3539743.111</td>
109 <td>837861.515</td>
110 <td>34291308.328</td>
111 </tr>
112 <tr>
113 <th>Binary (XStream 1.4.10)</th>
114 <td>1149384.865</td>
115 <td>438657.801</td>
116 <td>290646.503</td>
117117 </tr>
118118 <tr>
119119 <th>Jettison (1.2)</th>
120 <td>3002547.220</td>
121 <td>1159238.555</td>
122 <td>682182.733</td>
120 <td>2983598.441</td>
121 <td>564172.475</td>
122 <td>632427.902</td>
123123 </tr>
124124 </table>
125125
129129 <dt>Array</dt>
130130 <dd>A single element with 1.000 child elements.</dd>
131131 <dt>Nested</dt>
132 <dd>Nested elements in 500 levels.</dd>
132 <dd>Nested elements in 1000 levels (since version 1.4.10).</dd>
133133 </dl>
134134
135135 <h2 id="converterType">Converter Type Benchmark</h2>
145145 </tr>
146146 <tr>
147147 <th>Custom</th>
148 <td>11276718.384</td>
148 <td>9827295.423</td>
149149 </tr>
150150 <tr>
151151 <th>Java Bean</th>
152 <td>28878706.293</td>
152 <td>18939434.561</td>
153153 </tr>
154154 <tr>
155155 <th>Reflection</th>
156 <td>40085786.696</td>
156 <td>19450925.166</td>
157157 </tr>
158158 </table>
159159
179179 </tr>
180180 <tr>
181181 <th>No Cache</th>
182 <td>19626160.696</td>
182 <td>9755034.512</td>
183183 </tr>
184184 <tr>
185185 <th>Intern</th>
186 <td>23060982.052</td>
186 <td>12650471.288</td>
187187 </tr>
188188 <tr>
189189 <th>ConcurrentMap (length limit)</th>
190 <td>21796001.29</td>
190 <td>12072029.228</td>
191191 </tr>
192192 <tr>
193193 <th>ConcurrentMap (unlimited)</th>
194 <td>21378299.003</td>
194 <td>11431423.547</td>
195195 </tr>
196196 <tr>
197197 <th>Sync'd WeakCache (length limit)</th>
198 <td>21838410.801</td>
198 <td>12748751.700</td>
199199 </tr>
200200 <tr>
201201 <th>Sync'd WeakCache (unlimited)</th>
202 <td>22011251.691</td>
202 <td>11178461.611</td>
203203 </tr>
204204 </table>
205205
240240 </tr>
241241 <tr>
242242 <th>No Coding</th>
243 <td>7299475.975</td>
243 <td>4057270.642</td>
244244 </tr>
245245 <tr>
246246 <th>Dollar Coding</th>
247 <td>7767196.902</td>
247 <td>4635671.256</td>
248248 </tr>
249249 <tr>
250250 <th>Escaped Underscore Coding</th>
251 <td>9894393.289</td>
251 <td>5974244.102</td>
252252 </tr>
253253 <tr>
254254 <th>Cached Escaped Underscore Coding</th>
255 <td>7867671.962</td>
255 <td>4531410.494</td>
256256 </tr>
257257 <tr>
258258 <th>Xml Friendly Coding</th>
259 <td>8635501.208</td>
259 <td>4953594.706</td>
260260 </tr>
261261 </table>
262262
00 <html>
11 <!--
22 Copyright (C) 2005, 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
99
1010 Created on 29. January 2005 by Joe Walnes
1111 -->
12 <head>
13 <title>Change History</title>
14 </head>
15 <body>
16
17 <p>Changes are split into three categories:</p>
18
19 <ul>
20 <li><b>Major changes</b>: The major new features that all users should know about.</li>
21 <li><b>Minor changes</b>: Any smaller changes, including bugfixes.</li>
22 <li><b>API changes</b>: Any changes to the API that could impact existing users.</li>
23 </ul>
24
25 <p>Full details can be found in GitHub's
26 <a href="https://github.com/x-stream/xstream/issues?q=is%3Aissue+is%3Aclosed">Issues</a>, filter for the
27 appropriate milestone.
12 <head>
13 <title>Change History</title>
14 </head>
15 <body>
16
17 <p>Changes are split into three categories:</p>
18
19 <ul>
20 <li><b>Major changes</b>: The major new features that all users should know about.</li>
21 <li><b>Minor changes</b>: Any smaller changes, including bugfixes.</li>
22 <li><b>API changes</b>: Any changes to the API that could impact existing users.</li>
23 </ul>
24
25 <p>
26 Full details can be found in GitHub's <a href="https://github.com/x-stream/xstream/issues?q=is%3Aissue+is%3Aclosed">Issues</a>,
27 filter for the appropriate milestone.
2828 </p>
29
30 <!--
31 <h1 id="upcoming-1.4.x">Upcoming 1.4.x maintenance release</h1>
32
33 <p>Not yet released.</p>
34 -->
35
36 <h1 id="1.4.9">1.4.9</h1>
37
38 <p>Released March 15, 2016.</p>
39
40 <h2>Major changes</h2>
41
42 <ul>
43 <li>GHI:#25: Fix <a href="https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing">XXE
44 vulnerability</a>: Fixed affected drivers were Dom4JDriver, DomDriver, JDomDriver, JDom2Driver, SjsxpDriver,
45 StandardStaxDriver and WstxDriver. Still vulnerable are BEAStaxDriver and XomDriver. Processing of (external)
46 entities has been disabled. See <a href="faq.html#Security_XXEVulnerability">FAQ</a> for more information.</li>
47 <li>Benchmark module has been deprecated in favor of <a href="http://openjdk.java.net/projects/code-tools/jmh/">
48 JMH (Java Microbenchmarking Harness)</a>.</li>
49 <li>GHI:#33 and GHPR:#38: Add converter for java.nio.file.Path (by Aaron Jonson).</li>
50 </ul>
51
52 <h2>Minor changes</h2>
53
54 <ul>
55 <li>GHI:#35: AnnotationMapper dropped silently constructor arguments for converters if they were equal.</li>
56 <li>Fix: Possible concurrency problem with XomDriver.</li>
57 <li>JIRA:XSTR-773, GHPR:#3: Minimize memory footprint by not keeping internal references to instances of
58 immutable types.</li>
59 <li>Drop automatic reference support at deserialization time for immutable types before version 1.4 (primitive
60 types and their boxed counterpart, java.lang.Class, java.lang.String, java.math.BigDecimal,
61 java.math.BigInteger, java.io.File, java.net.URL, and java.awt.font.TextAttribute).</li>
62 <li>Fix: Implicit collection declaration is erroneously inherited or propagated to hidden field of same name.</li>
63 <li>XStreamConverter annotation supports null values as arguments for converter instantiation.</li>
64 <li>GHI:#5: Support null values for JavaBean properties.</li>
65 <li>GHI:#36: Fix NamedMapConverter, does not use SingleValueConverter of value if value is text of entry element.</li>
66 <li>GHI:#13: Own converter for javax.activation.ActivationDataFlavor, because ExternalizableConverter cannot handle
67 a type that violates the Java specification.</li>
68 <li>GHPR:#18: Minimize synchronized block in FieldDictionary.</li>
69 <li>JIRA:XSTR-769: Synthetic fields with references to outer class use compiler dependent names.</li>
70 <li>JIRA:XSTR-771: UUID is an immutable type by default.</li>
71 <li>GHPR:#23: Constructor of AbstractXppDriver swallows causing exception.</li>
72 <li>GHI:#28: Fix functionality of ClassAliaslingMapper.itemTypeAsAttributes(Class).</li>
73 <li>GHI:#37: Historical Java 1.3 support suppresses causing exception of a thrown InvocationTargetException.</li>
74 <li>GHI:#41: Cannot instantiate ToAttributedValueConverter with null value for valueFieldName using
75 XStreamConverter annotation.</li>
76 <li>Fix example code in description of security framework.</li>
77 <li>Clean-up usage of exceptions.</li>
78 </ul>
79
80 <h2>API changes</h2>
81
82 <ul>
83 <li>Added c.t.x.XStream.addImmutableType(Class, boolean) and deprecated c.t.x.XStream.addImmutableType(Class).</li>
84 <li>Added c.t.x.mapper.Mapper.isReferenceable(Class).</li>
85 <li>Added c.t.x.mapper.ImmutableTypesMapper.addImmutableType(Class, boolean) and deprecated
86 c.t.x.mapper.ImmutableTypesMapper.addImmutableType(Class).</li>
87 <li>Added c.t.x.io.xml.Dom4JDriver.createReader().</li>
88 <li>Added c.t.x.io.xml.DomDriver.createDocumentBuilderFactory().</li>
89 <li>Added c.t.x.io.xml.JDomDriver.createBuilder().</li>
90 <li>Added c.t.x.io.xml.JDom2Driver.createBuilder().</li>
91 <li>Added c.t.x.io.xml.XomDriver.createBuilder().</li>
92 <li>Added constructor c.t.x.converter.extended.ToAttributedValueConverter.ToAttributedValueConverter(Class,
93 Mapper, ReflectionProvider, ConverterLookup).</li>
94 <li>Added abstract c.t.x.converter.ErrorWritingException as common base for c.t.x.converter.ConversionException
95 and c.t.x.converter.reflection.ObjectAccessException.</li>
96 <li>Deprecated c.t.x.io.xml.XomDriver(Builder), c.t.x.io.xml.XomDriver(Builder, NameCoder) and c.t.x.io.xml.XomDriver.getBuilder().</li>
97 <li>Deprecated c.t.x.mapper.ClassAliaslingMapper.itemTypeAsAttributes(Class) and
98 c.t.x.mapper.ClassAliaslingMapper.aliasIsAttribute(String). Methods never called, left-over from old refactoring.</li>
99 </ul>
100
101 <h1 id="1.4.8">1.4.8</h1>
102
103 <p>Released February 18, 2015.</p>
104
105 <h2>Major changes</h2>
106
107 <ul>
108 <li>Support for serializable lambda expressions and handling of non-serializable ones.</li>
109 </ul>
110
111 <h2>Minor changes</h2>
112
113 <ul>
114 <li>Detect Java 9 runtime.</li>
115 <li>JIRA:XSTR-767: Deserialization of referenced lambda expressions fail.</li>
116 <li>JIRA:XSTR-762: Private method readResolve() called on base classes.</li>
117 <li>JIRA:XSTR-761: Support ignored serialPersistentField at deserialization time.</li>
118 <li>JIRA:XSTR-755: ExternalizableConverter does not respect writeReplace and readResolve.</li>
119 <li>JIRA:XSTR-757: Deserialized TreeSet does not honor remove(Object) return value contract.</li>
120 <li>JIRA:XSTR-759: Support deserialization of <a href="http://www.w3.org/TR/NOTE-datetime">W3C datetime format</a>
121 in DateConverter with Java 7 runtime.</li>
122 <li>Fix: DateConverter ignores provided locale.</li>
123 <li>JIRA:XSTR-768: ISO8601GregorianCalendarConverter may set invalid time zone for Joda-Time.</li>
124 <li>Fix: WeakCache.entrySet().iterator().next.setValue(value) returns the reference instead of the old value.</li>
125 <li>Fix: SqlTimestampConverter throws IllegalArgumentException instead of ConversionException on fromString().</li>
126 <li>Fix: CGLIBEnhancedConverter does not initialize transient members of parent after deserialization.</li>
127 <li>JIRA:XSTR-763: Set scope of org.json:json to test instead declaring the dependency as optional.</li>
128 </ul>
129
130 <h2>API changes</h2>
131
132 <ul>
133 <li>Added c.t.x.util.JVM.is19().</li>
134 <li>Added c.t.x.converter.reflection.LambdaConverter and c.t.x.mapper.LambdaMapper.</li>
135 <li>Declare c.t.x.XStream.ignoreUnknownElements(Pattern) as public.</li>
136 <li>c.t.x.converters.reflection.AbstractReflectionConverter.readResolve() is protected now.</li>
137 <li>c.t.x.mapper.AbstractAttributeAliasingMapper.readResolve() is protected now.</li>
138 <li>Deprecated c.t.x.converters.extended.StackTraceElementFactory, it is an internal helper class.</li>
139 <li>Deprecated c.t.x.converters.reflection.SerializationMethodInvoker, it is an internal helper class.</li>
140 <li>Deprecated c.t.x.io.AttributeNameIterator, it is an internal helper class.</li>
141 <li>Deprecated c.t.x.XStream.useXStream11XmlFriendlyMapper(), corresponding
142 c.t.x.mapper.XStream11XmlFriendlyMapper has been deprecated long ago.</li>
143 <li>Deprecated c.t.x.converter.basic.BooleanConverter.shouldConvert(Class,Object), undetected remainder of
144 ancient XStream version.</li>
145 </ul>
146
147 <h1 id="1.4.7">1.4.7</h1>
148
149 <p>Released February 8, 2014.</p>
150
151 <p class="highlight">This maintenance release addresses mainly the security vulnerability CVE-2013-7285, an
152 arbitrary execution of commands when unmarshalling.</p>
153
154 <h2>Major changes</h2>
155
156 <ul>
157 <li>Add <a href="security.html#framework">security framework</a> to limit handled types while unmarshalling.</li>
158 <li>java.bean.EventHandler no longer handled automatically because of severe security vulnerability.</li>
159 <li>JIRA:XSTR-751: New SunLimitedUnsafeReflectionProvider that uses undocumented features only to allocate new
160 instances as required on Dalvik.</li>
161 <li>Fix instantiation of AnnotationMapper that requires ConverterLookup and ConverterRegistry to be the same
162 instance.</li>
163 </ul>
164
165 <h2>Minor changes</h2>
166
167 <ul>
168 <li>XSTR-749: NPE if ReflectionConverter.canConvert(type) is called with null as argument.</li>
169 <li>XSTR-753: NPE if SerializationConverter.canConvert(type) is called with an interface type as argument that
170 extends Serializable.</li>
171 <li>Add constructor to ReflectionConverter taking an additional type to create an instance that is
172 dedicated to a specific type only.</li>
173 <li>The ConverterLookup used by default cannot be casted to a ConverterRegistry anymore.</li>
174 </ul>
175
176 <h2>API changes</h2>
177
178 <ul>
179 <li>Added package c.t.x.security with interface TypePermission, all its implementations and
180 ForbiddenClassException.</li>
181 <li>Added c.t.x.mapper.SecurityMapper handling the new type permissions.</li>
182 <li>Added methods addPermission, denyPermission, allowTypesXXX and denyTypesXXX to c.t.x.XStream to setup
183 security at unmarshalling time.</li>
184 <li>Added c.t.x.converters.reflection.SunLimitedUnsafeReflectionProvider.</li>
185 <li>Deprecated c.t.x.converters.reflection.Sun14ReflectionProvider in favor of new
186 c.t.x.converters.reflection.SunUnsafeReflectionProvider.</li>
187 <li>Added c.t.x.converters.reflection.ReflectionConverter(Mapper,ReflectionProvider,Class).</li>
188 </ul>
189
190 <h1 id="1.4.6">1.4.6</h1>
191
192 <p>Released December 12, 2013.</p>
193
194 <h2>Major changes</h2>
195
196 <ul>
197 <li>JIRA:XSTR-566 and JIRA:XSTR-200: Better compatibility with GAE and environments with active SecurityManager (i.e. in an
198 Applet). XStream converters try now to ensure already in the canConvert methods that they can handle the requested type in
199 practice and not only theoretically. Additionally the implementations even better take care, that the initialization of a
200 converter will not break the setup of XStream itself. Following modifications have been done for these topics:
201 <ul>
202 <li>ReflectionConverter, SerializationConverter and LookAndFieldConverter will check if they can access the fields by
203 reflection for a requested type.</li>
204 <li>SerializationConverter and ExternalizableConverter will check if they can create an instance of a derived
205 OutputObjectStream first.</li>
206 <li>BeanProvider does no longer use reflection to locate default constructor.</li>
207 <li>AbstractAttributedCharacterIteratorAttributeConverter (and therefore TextAttributeConverter) will check first if it
208 can access the possible constants of the type by reflection.</li>
209 <li>NoClassDefFoundError raised in GAE accessing the fields of restricted types by reflection will be handled.</li>
210 <li>StackTraceElementConverter uses constructor for StackTraceElement instances in Java 5 and GEA.</li>
211 </ul>
212 </li>
213 <li>JIRA:XSTR-739 and JIRA:XSTR-746: OrderRetainingMap fails if HashMap.putAll(Map) of Java Runtime is not
214 implemented calling put for every element within the map.</li>
215 <li>New NamedArrayConverter to define names of inner elements.</li>
216 </ul>
217
218 <h2>Minor changes</h2>
219
220 <ul>
221 <li>JIRA:XSTR-747: All constructors of StaxDriver derived classes take erroneously a XmlFriendlyNameCoder
222 instead of a plain NameCoder.</li>
223 </ul>
224
225 <h2>API changes</h2>
226
227 <ul>
228 <li>Added c.t.x.converters.extended.NamedArrayConverter for free element names in arrays.</li>
229 <li>Added constructors to c.t.x.io.xml.StandardStaxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>
230 <li>Deprecated constructors of c.t.x.io.xml.StandardStaxDriver taking a XmlFriendlyNameCoder.</li>
231 <li>Added constructors to c.t.x.io.xml.BEAStaxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>
232 <li>Deprecated constructors of c.t.x.io.xml.BEAStaxDriver taking a XmlFriendlyNameCoder.</li>
233 <li>Added constructors to c.t.x.io.xml.WstxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>
234 <li>Deprecated constructors of c.t.x.io.xml.WstxDriver taking a XmlFriendlyNameCoder.</li>
235 <li>Added method canAccess to c.t.x.converter.reflection.AbstractReflectionConverter.</li>
236 <li>Added static method canCreateDerivedObjectOutputStream to c.t.x.core.JVM.</li>
237 <li>Deprecated unused member c.t.x.converter.javabean.BeanProvider.NO_PARAMS.</li>
238 <li>Deprecated unused method c.t.x.converter.javabean.BeanProvider.getDefaultConstrutor(Class).</li>
239 </ul>
240
241
242 <h1 id="1.4.5">1.4.5</h1>
243
244 <p>Released September 18, 2013.</p>
245
246 <h2>Major changes</h2>
247
248 <ul>
249 <li>JIRA:XSTR-732: Use a referencing implementation for the ClassLoader to support environments where no new
250 ClassLoader can be instantiated due to security restrictions.</li>
251 <li>JIRA:XSTR-691: Allow unknown XML elements to be ignored using new method XStream.ignoreUnknownElements.</li>
252 <li>JIRA:XSTR-728: XStream creates invalid JSON with JsonHierarchicalStreamDriver for custom converters since
253 XStream 1.4.</li>
254 <li>JIRA:XSTR-300: New EnumToStringConverter to support custom string representations of Enum values.</li>
255 <li>JIRA:XSTR-292 and JIRA:XSTR-405: New NamedMapConverter and NamedCollectionConverter to define names of
256 inner elements.</li>
257 <li>JIRA:XSTR-726: New annotation XStreamAliasType to support declarative definition of XStream.aliasType().</li>
258 <li>JIRA:XSTR-735: Support for JDOM2 with JDom2Driver, JDom2Reader and JDom2Writer.</li>
259 <li>Optimized XML structure for java.awt.Font.</li>
260 <li>Fix: ToAttributedValueConverter silently appends fields without attribute support to the value producing mixed-mode XML.</li>
261 <li>JIRA:XSTR-566 and JIRA:XSTR-249: Better compatibility with Google AppEngine and J2ME, setup no longer fails for unavailable converters.</li>
262 </ul>
263
264 <h2>Minor changes</h2>
265
266 <ul>
267 <li>Fix missing manifest information.</li>
268 <li>JIRA:XSTR-729: Add OSGi information to manifests.</li>
269 <li>JIRA:XSTR-723: XStream will now detect a working enhanced mode dynamically instead using lists of known
270 vendors. This allows enhanced support for JamVM if it is bundled with OpenJDK. It will currently fail on a
271 runtime based on GNU Classpath (at least up to version 0.98).</li>
272 <li>JIRA:XSTR-541: JavaScript compatibility problem with 64-bit integers in JSON.</li>
273 <li>JIRA:XSTR-719: Support replacement of default converter in any case.</li>
274 <li>JIRA:XSTR-725: processAnnotation performance improvement in concurrent situation.</li>
275 <li>JIRA:XSTR-721: EnumConverter is more lenient while parsing constants.</li>
276 <li>New constructors for CollectionConverter and MapConverter to allow registration for an individual type.</li>
277 <li>JIRA:XSTR-724: Cache class name lookup failures.</li>
278 <li>Current IBM JDK for Java 1.4.2 no longer has a reverse field ordering.</li>
279 <li>LongConverter supports now positive hex and octal numbers over Long.MAX_VALUE within 64 bit.</li>
280 <li>Fix: Sun14RefectionProvider ignores a provided FieldDictionary.</li>
281 <li>JIRA:XSTR-457: Do not write 'defined-in' attribute if not needed.</li>
282 <li>JettisonMappedXmlDriver provides better support to overwrite its create methods.</li>
283 <li>JIRA:XSTR-685: StAX based drivers (StaxDriver and JettisonMappedXmlDriver) are not closing internal input
284 stream reading from file or URL.</li>
285 <li>JIRA:XSTR-736: XStream.unmarshal may throw NPE if version info of manifest is missing.</li>
286 <li>JIRA:XSTR-733: Implicit elements that match multiple defined implicit collections will be assigned to the
287 map with the nearest matching element type.</li>
288 <li>JIRA:XSTR-740: ISO8601GregorianCalendarConverter creates Calendar instance with wrong Locale in Java 7 if
289 the Locale for the LocaleCategory.FORMAT is different to the global default Locale.</li>
290 <li>JIRA:XSTR-578: Implement support for aliasing in JavaClasConverter, JavaFieldConverter and
291 JavaMethodConverter. While it is not possible to enable this in general, new constructors have been added to
292 these converters and an example in the acceptance tests (AliasTest).</li>
293 <li>JIRA:XSTR-742: Register CompositeClassLoader in Java 7 as parallel capable.</li>
294 <li>JIRA:XSTR-743: Support proxy collections of Hibernate Envers.</li>
295 <li>Fix NPE in AttributeMapper.shouldLookForSingleValueConverter if parameters fieldName and definedIn are null.</li>
296 <li>Implicit type argument can be omitted when registering converters with @XStreamConverter annotation.</li>
297 </ul>
298
299 <h2>API changes</h2>
300
301 <ul>
302 <li>Added c.t.x.converters.extended.NamedCollectionConverter for free element names in collections.</li>
303 <li>Added c.t.x.converters.extended.NamedMapConverter for free element names in maps.</li>
304 <li>Added c.t.x.io.xml.StandardStaxDriver to use the StAX implementation delivered with the Java 6 runtime.</li>
305 <li>Deprecated c.t.x.io.xml.SjsxpStaxDriver to select the internal StAX implementation of Oracle.</li>
306 <li>Added static methods getStaxInputFactory and getStaxOutputFactory to c.t.x.core.JVM as returning the
307 implementations of javax.xml.stream.XMLInputFactory (resp. javax.xml.stream.XMLOutputFactory) delivered with
308 the Java Runtime since Java 6.</li>
309 <li>Added c.t.x.core.ClassLoaderReference.</li>
310 <li>Added constructors taking an additional Class argument for c.t.x.converters.collections.CollectionConverter
311 and c.t.x.converters.collections.MapConverter.</li>
312 <li>Added constructors taking a ClassLoaderReference instead of a ClassLoader and deprecated the ones taking the ClassLoader:
313 <ul>
314 <li>c.t.x.XStream</li>
315 <li>c.t.x.converters.extended.DynamicProxyConverter</li>
316 <li>c.t.x.converters.extended.JavaClassConverter</li>
317 <li>c.t.x.converters.extended.JavaFieldConverter</li>
318 <li>c.t.x.converters.extended.JavaMethodConverter</li>
319 <li>c.t.x.converters.reflection.CGLIBEnhancedConverter</li>
320 <li>c.t.x.converters.reflection.ExternalizableConverter</li>
321 <li>c.t.x.converters.reflection.SerializableConverter</li>
322 <li>c.t.x.mapper.AnnotationMapper</li>
323 <li>c.t.x.mapper.DefaultMapper</li>
324 </ul>
325 </li>
326 <li>Added static methods newReflectionProvider, isAWTAvailable, isSQLAvailable and isSwingAvailable to
327 c.t.x.core.JVM as replacement for the deprecated non-static methods.</li>
328 <li>Deprecated c.t.x.core.JVM() and all non-static methods.</li>
329 <li>Added method useImplicitType to c.t.x.annotations.XStreamConverter.</li>
330 <li>JIRA:XSTR-722: Added
331 c.t.x.converters.reflection.ReflectionProvider.getFieldOrNull(Class, String).</li>
332 <li>Deprecated
333 c.t.x.converters.reflection.ReflectionProvider.fieldDefinedInClass(Class, String) in
334 favor of new c.t.x.converters.reflection.ReflectionProvider.getFieldOrNull(Class,
335 String).</li>
336 <li>Deprecated constructor c.t.x.converters.extended.RegexPatternConverter(Converter)
337 in favor of c.t.x.converters.extended.RegexPatternConverter().</li>
338 <li>Deprecated default constructor of c.t.x.converters.extended.FontConverter in favor of
339 c.t.x.converters.extended.FontConverter(Mapper).</li>
340 <li>Deprecated constructor c.t.x.converters.extended.ThrowableConverter(Converter)
341 in favor of c.t.x.converters.extended.ThrowableConverter(ConverterLookup).</li>
342 <li>Deprecated class c.t.x.converters.reflection.SelfStreamingInstanceChecker and moved
343 original implementation into c.t.x.core.util, since it is internal.</li>
344 <li>Deprecated interface c.t.x.mapper.AnnotationConfiguration.</li>
345 </ul>
346
347 <h1 id="1.4.4">1.4.4</h1>
348
349 <p>Released January 19, 2013.</p>
350
351 <h2>Minor changes</h2>
352
353 <ul>
354 <li>JIRA:XSTR-709: Locks up on Mac with Apple JVM due to unwanted initialization of AWT.</li>
355 <li>JIRA:XSTR-711: DateConverter cannot handle dates in different era.</li>
356 <li>JIRA:XSTR-741: ToAttributedValueConverter fails to write enums as attributes.</li>
357 <li>JIRA:XSTR-712: HibernateMapper throws NPE if a collection contains null.</li>
358 <li>DateConverter supports now localized formats.</li>
359 <li>JIRA:XSTR-710: JsonWriter does not write BigInteger and BigDecimal as number values.</li>
360 <li>JIRA:XSTR-708: SqlTimestampConverter does not ignore timezone.</li>
361 <li>JIRA:XSTR-707: Creation of XmllPullParser with the XmlPullParserFactory may fail in OSGi environment.</li>
362 <li>JIRA:XSTR-705: Unnecessary synchronization accessing the field cache decreases performance.</li>
363 <li>JIRA:XSTR-714: Fields not found when XStream12FieldKeySorter used.</li>
364 </ul>
365
366 <h2>API changes</h2>
367
368 <ul>
369 <li>Deprecated method c.t.x.core.util.JVM.is14(), c.t.x.core.util.JVM.is15() and c.t.x.core.util.JVM.is16().</li>
370 </ul>
371
372 <h1 id="1.4.3">1.4.3</h1>
373
374 <p>Released July 17, 2012.</p>
375
376 <h2>Major changes</h2>
377
378 <ul>
379 <li>Support java.util.concurrent.ConcurrentHashMap with the MapConverter. This will also avoid a bug in JRockit
380 JDK reported in JIRA:XSTR-608.</li>
381 <li>JIRA:XSTR-699: Support for Hibernate 4 with XStream's Hibernate module as default for Java 6 or higher.</li>
382 </ul>
383
384 <h2>Minor changes</h2>
385
386 <ul>
387 <li>JVM.loadClass will now also initialize the loaded class and ignore any occurring LinkageError.</li>
388 <li>JIRA:XSTR-596: SubjectConverter will be no longer registered if initialization of javax.security.auth.Subject fails.</li>
389 <li>JIRA:XSTR-683: Inheritance of implicit collections, arrays or maps is dependent on declaration sequence.</li>
390 <li>Inherited implicit collections, arrays or maps can be overwritten with own definition in subtype.</li>
391 <li>JIRA:XSTR-688: Cannot omit XML elements from derived fields.</li>
392 <li>JIRA:XSTR-696: Ill-formed JSON generated, because JSON writer is fed with type of declaring field instead of
393 the real object's type.</li>
394 <li>JIRA:XSTR-685: Deserialization from file or URL keeps stream open.</li>
395 <li>JIRA:XSTR-684: XML 1.0 character validation fails for characters from 0x10 to 0x1f.</li>
396 <li>JavaBeanConverter supports now instantiation for a specific type and can therefore be used in
397 @XStreamConverter annotation.</li>
398 <li>SerializableConverter is broken if the serialized type is the default implementation.</li>
399 <li>Method marshalUnserializableParent of SerializableConverter is protected now to skip the default mechanism
400 in a derived converter that uses the default constructor to create the original type (as an alternative for
401 JIRA:XSTR-695).</li>
402 <li>FieldDictionary may call sort of FieldKeySorter implementation with wrong type as key.</li>
403 <li>Sometimes DependencyInjectionFactory tries to instantiate objects with mismatching constructor arguments.</li>
404 <li>HSQLDB has to be a test dependency only for XStream's Hibernate module.</li>
405 </ul>
406
407 <h1 id="1.4.2">1.4.2</h1>
408
409 <p>Released November 3, 2011.</p>
410
411 <h2>Major changes</h2>
412
413 <ul>
414 <li>XStream libraries can be used now directly in Android, therefore support of Java 1.4.2 has been stopped with the delivery.
415 Anyone who needs a version for Java 1.4.2 can build it easily from source, this build is still supported and part of CI.</li>
416 <li>JIRA:XSTR-675: New extended HierarchicalStreamReader interface with peekNextChild method. All XStream
417 readers implement the new interface (by Nikita Levyankov).</li>
418 <li>JIRA:XSTR-673: Collections.EMPTY_LIST, Collections.EMPTY_SET and Collections.EMPTY_MAP supported with own
419 alias and defined as immutable.</li>
420 <li>JIRA:XSTR-631: Collections.singletonList(), Collections.singletonSet() and Collections.singletonMap()
421 supported with own alias and own converters.</li>
422 <li>JIRA:XSTR-406 + JIRA:XSTR-663: Support additional parameters for XStreamConverter annotation (e.g. to declare a
423 ToAttributedValueConverter).</li>
424 </ul>
425
426 <h2>Minor changes</h2>
427
428 <ul>
429 <li>WstxDriver did not trigger Woodstox, but BEA StAX implementation.</li>
430 <li>JIRA:XSTR-260: PrettyPrintWriter does not handle tab and new line characters in attributes.</li>
431 <li>JIRA:XSTR-667: Cannot serialize empty list with JsonHierarchicalStreamDriver.</li>
432 <li>JIRA:XSTR-661: TreeMarshaller.CircularReference is not a ConversionException.</li>
433 <li>JIRA:XSTR-562: StAX: Namespace attribute is not written in non-repairing mode for second sibling.</li>
434 <li>JIRA:XSTR-664: ClassCastException in HibernatePersistentSortedSetConverter and
435 HibernatePersistentSortedMapConverter.</li>
436 <li>JIRA:XSTR-674: Recreate binary compatibility with 1.3.x series for method
437 CustomObjectInputStream.getInstance(...).</li>
438 <li>JIRA:XSTR-671: CannotResolveClassException should accept cause.</li>
439 <li>JIRA:XSTR-672: Collections.EMPTY_LIST, Collections.EMPTY_SET and Collections.EMPTY_MAP used for in implicit
440 collection should not throw ReferencedImplicitElementException.</li>
441 <li>JIRA:XSTR-676: Introduce MissingFieldException thrown at deserialization time indicating a missing field or
442 property (by Nikita Levyankov).</li>
443 <li>Add length limit for cached strings in StringConverter, 38 characters by default.</li>
444 <li>The JsonHierarchicalStreamDriver and the JsonWriter did not support the inherited NameCoder instance.</li>
445 <li>Add BinaryStreamDriver.</li>
446 <li>NPE in XppDomComparator.</li>
447 <li>Dom4JXmlWriter fails to flush the underlying writer.</li>
448 <li>Known control characters are not encoded with JsonWriter as proposed at json.org.</li>
449 <li>Detect duplicate property processing in JavaBeanConverter and throw DuplicatePropertyException instead of
450 clobbering silently.</li>
451 <li>Allow access to Mapper and JavaBeanProvider in derived instances of JavaBeanConverter.</li>
452 <li>DependencyInjectionFactory failed to create instance when a matching constructor was found, but a default
453 constructor was also present.</li>
454 </ul>
455
456 <h2>API changes</h2>
457
458 <ul>
459 <li>Added interface c.t.x.io.ExtendedHierarchicalStreamReader extending c.t.x.io.HierarchicalStreamReader. All
460 implementations of c.t.x.io.HierarchicalStreamReader will implement also the extended interface.</li>
461 <li>Added c.t.x.converters.reflection.MissingFieldException derived from
462 c.t.x.converters.reflection.ObjectAccessException and used instead when the unmarshalling process should write
463 a field or property that is missing and does not exist.</li>
464 <li>Added methods c.t.x.io.path.PathTracker.peekElement(), c.t.x.io.path.PathTracker.peekElement(int), and
465 c.t.x.io.path.PathTracker.depth().</li>
466 <li>Deprecated method c.t.x.core.ReferencingMarshallingContext.currentPath(). Wrong approach.</li>
467 </ul>
468
469 <h1 id="1.4.1">1.4.1</h1>
470
471 <p>Released August 11, 2011.</p>
472
473 <h2>Major changes</h2>
474
475 <ul>
476 <li>JIRA:XSTR-659: Use again Xpp3 as default parser, now with additional XmlPullParser API as regular
477 dependency for the XPP factory. Only standard kXML2 package contains the XPP factory, but not the minimal kXML2
478 version.</li>
479 </ul>
480
481 <h2>Minor changes</h2>
482
483 <ul>
484 <li>Add utility class c.t.x.io.xml.xppdom.XppFactory and a path tracking comparator for XppDom.</li>
485 </ul>
486
487 <h1 id="1.4">1.4</h1>
488
489 <p>Released August 6, 2011.</p>
490
491 <h2>Major changes</h2>
492
493 <ul>
494 <li>Java 7 is detected and supported.</li>
495 <li>JIRA:XSTR-542: The XppDriver uses now the official XmlPullParser API to locate an available parser using
496 the XmlPullParserFactory. This allows the usage of XPP technology with XStream in Android.</li>
497 <li>Additional explicit XPP drivers for the Xpp3 and kXML2 implementations.</li>
498 <li>Additional explicit XPP DOM drivers for the Xpp3 and kXML2 implementations.</li>
499 <li>kXML2 is now the preferred parser implementation, Xpp3 is optional.</li>
500 <li>Additional explicit StAX drivers for Woodstox, BEA StAX and SJSXP of the JDK 6 implementations.</li>
501 <li>JDK 1.3 is no longer officially supported.</li>
502 <li>JIRA:XSTR-377+JIRA:XSTR-226: New artifact xstream-hibernate with converters and mapper to process Hibernate
503 object graphs (by Costin Leau, Konstantin Pribluda and in special Jaime Metcher).</li>
504 <li>New NameCoder interface and implementations to support a generic name translation between names from the
505 object graph and a target format. The new XmlFriendlyNameCoder replaces the XmlFriendlyReplacer used for XML
506 only.</li>
507 <li>JIRA:XSTR-553: Support annotations in Android.</li>
508 <li>JIRA:XSTR-556: DateConverter uses format with 3-letter time zones that are ambiguous. Therefore it will now
509 always use UTC to write dates. Unmarshalled dates are not affected as long as they contain a time zone.</li>
510 <li>The type java.lang.reflect.Field is now handled by an own converter, that can still read the old format.</li>
511 <li>JIRA:XSTR-490: Provide path in Converter for contexts that track the path.</li>
512 <li>JIRA:XSTR-592+JIRA:XSTR-579: OmitField respected at deserialization time even for existing fields.</li>
513 <li>JIRA:XSTR-593: Direct support for java.net.URI instances (by Carlos Roman).</li>
514 <li>JIRA:XSTR-615+JIRA:XSTR-580: Dynamic proxies cannot be referenced recursively.</li>
515 <li>JIRA:XSTR-547: Wrong class loader used for Serializable types deserialized with an ObjectInputStream.</li>
516 <li>JIRA:XSTR-341: Support of implicit arrays.</li>
517 <li>JIRA:XSTR-306+JIRA:XSTR-406: Support of implicit maps.</li>
518 <li>JIRA:XSTR-344: New ToAttributedValueConverter to allow conversion of an element with string body and
519 attributes.</li>
520 <li>JIRA:XSTR-573: SortedSet added with TreeSet as the default implementation.</li>
521 <li>JIRA:XSTR-576: TreeMap and TreeSet no longer add an element without comparator (by Jason Greanya),
522 solves also invalid format with JSON for such objects (JIRA:XSTR-640).</li>
523 </ul>
524
525 <h2>Minor changes</h2>
526
527 <ul>
528 <li>JIRA:XSTR-612: Improve extensibility of c.t.x.javabean.* package by reintroducing a PropertyDictionary with
529 the additional interface PropertySorter.</li>
530 <li>JIRA:XSTR-591: EnumSingleValueConverter did use toString() instead of name() to create the String
531 representation of an enum value.</li>
532 <li>JIRA:XSTR-618: Add Oracle as vendor used for recent JRockit versions and former Sun JDK.</li>
533 <li>JIRA:XSTR-656: DomReader and Dom4JReader do not escape attribute names retrieving their values.</li>
534 <li>JIRA:XSTR-604: StringConverter's cache may cause an OutOfMemoryException.</li>
535 <li>JIRA:XSTR-577: Skip UTF-8 BOM in XmlHeaderAwareReader.</li>
536 <li>The XppReader no longer uses a BufferedReader.</li>
537 <li>JIRA:XSTR-543: Better deserialization support of the defined-in system attribute in combination with field
538 aliases.</li>
539 <li>JIRA:XSTR-551: Deprecated XStream.InitializationException still thrown instead of InitializationException.</li>
540 <li>JIRA:XSTR-655: JsonWriter generates invalid JSON for Externalizable types.</li>
541 <li>JIRA:XSTR-540: Support Jettison-based configuration of JettisonMappedXmlDriver (by Doug Daniels).</li>
542 <li>JIRA:XSTR-633: JettisonMappedXmlDriver escaped property names according escape rules for XML tag names.</li>
543 <li>JIRA:XSTR-625: Optionally ignore XStream's hints for Jettison to generate JSON arrays (by Dejan Bosanac).</li>
544 <li>JIRA:XSTR-605: Upgrade to Jettison 1.2 (for Java 5 or higher).</li>
545 <li>New JsonWriter.EXPLICIT_MODE generating JSON that enforces property sequence.</li>
546 <li>JIRA:XSTR-552: Improve performance of ReflectionProvider (by Keith Kowalczykowski).</li>
547 <li>JIRA:XSTR-559: Improve performance of Sun14ReflectionProvider (by Keith Kowalczykowski).</li>
548 <li>JIRA:XSTR-564: Improve performance of AnnotationMapper (by Keith Kowalczykowski).</li>
549 <li>JIRA:XSTR-563: Use ReferenceQueue for cleaning-up WeakReferences in ObjectIdDictionary (by Keith
550 Kowalczykowski).</li>
551 <li>JIRA:XSTR-646: Cache of Sun14ReflectionProvider consumes more PermGen space than necessary.</li>
552 <li>JIRA:XSTR-636: Ineffective cache in FieldDictionary using WeakHashMap with WeakReference values.</li>
553 <li>Ineffective cache for SerializationMethodInvoker (related to JIRA:XSTR-636).</li>
554 <li>Introduction of Caching interface implemented by all types in XStream that create local caches that may
555 have to be flushed manually.</li>
556 <li>Avoid excessive creation of AbstractPullReader.Event objects by using a pool.</li>
557 <li>Possibility to generate XPath expressions that select always a single node instead of a node list.</li>
558 <li>Cannot reference replaced object using ID references.</li>
559 <li>Implicit collection functionality will no longer use custom collection converters that may write tags that are not
560 recognized at deserialization time again.</li>
561 <li>JIRA:XSTR-654: Unmarshal fails when an implicit collection is defined and an element is named equal to the field.</li>
562 <li>JIRA:XSTR-574: AbstractReferenceUnmarshaller cannot handle null values for references.</li>
563 <li>Improve exception output in case of a missing field.</li>
564 <li>JIRA:XSTR-555: StAX driver tests do not honor repairing mode.</li>
565 <li>JIRA:XSTR-570: The @XStreamConverter provides now also the current type as possible constructor argument.</li>
566 <li>JIRA:XSTR-629: Deserialization of Externalizable with non-accessible default constructor fails.</li>
567 <li>JIRA:XSTR-571: Cannot serialize synchronized RandomAccessList types.</li>
568 <li>JIRA:XSTR-583: BinaryDriver fails to handle Strings with more than 64K bytes.</li>
569 <li>JIRA:XSTR-639: Cannot omit field at deserialization if the field has a class attribute.</li>
570 <li>JIRA:XSTR-599: EncodedByteArrayConverter should implement SingleValueConverter.</li>
571 <li>JIRA:XSTR-584: Race condition in XmlFriendlyReplacer.</li>
572 <li>JIRA:XSTR-623: XmlFriendlyReplacer may write illegal name characters (by Michael Schnell).</li>
573 <li>The ConversionException hides information if its ErrorWriter contains the added key already.</li>
574 <li>JIRA:XSTR-598: Attribute &quot;defined-in&quot; was wrongly evaluated for other attributes.</li>
575 <li>JIRA:XSTR-650: Possible NullPointerException at initialization on platforms like Android that do not
576 support all types of the JDK.</li>
577 <li>JIRA:XSTR-652: Initialization of XStream fails if DurationConverter constructor throws a
578 javax.xml.datatype.DatatypeConfigurationException. Converter will no longer handle Duration types if no
579 instance of the internal DatatypeFactory can be created.</li>
580 <li>Constructor DocumentWriter(Element) forgets the provided element.</li>
581 <li>JIRA:XSTR-597: Optimize AbstractReflectionConverter.</li>
582 <li>Introduce Caching interface to flush the internal cache of specific components.</li>
583 <li>Support JIRA:XSTR-407 also for IBM JRE 1.6 and greater.</li>
584 <li>java.nio.charset.Charset's converter was added as immutable type instead of the type itself.</li>
585 <li>java.util.Currency added as immutable type.</li>
586 <li>Fix selection of same parameter types in DependencyInjectionFactory.</li>
587 <li>Deprecation of c.t.x.javabean.PropertyDictionary has been countermanded.</li>
588 </ul>
589
590 <h2>API changes</h2>
591
592 <ul>
593 <li>Any deprecated stuff of the 1.2.x releases has been removed.</li>
594 <li>Deprecated constructors of c.t.x.converters.reflection.SerializableConverter, c.t.x.converters.reflection.ExternalizableConverter
595 and c.t.x.converters.reflection.CGLIBEnhancedConverter; new versions take an additional argument for class loader (as a result
596 for JIRA:XSTR-547).</li>
597 <li>Deprecated constructors of c.t.x.io.xml.XppReader, new versions take an additional argument for the XmlPullParser.</li>
598 <li>Deprecated c.t.x.io.xml.XppReader.createParser(), the XPP parser is now created by the driver.</li>
599 <li>Package c.t.x.io.xml.xppdom is now part of the official API.</li>
600 <li>c.t.x.io.xml.xppdom.Xpp3Dom and c.t.x.io.xmlxpp.dom.Xpp3DomBuilder have been deprecated. Functionality is
601 merged in c.t.x.io.xml.xppdom.XppDom.</li>
602 <li>Deprecated c.t.x.mapper.XStream11XmlFriendlyMapper and c.t.x.mapper.AbstractXmlFriendlyMapper.</li>
603 <li>Added interface c.t.x.core.ReferencingMarshallingContext which is implemented by all referencing marshallers.</li>
604 <li>Added interface c.t.x.io.naming.NameCoder and implementations.</li>
605 <li>Deprecated c.t.x.io.xml.XmlFriendlyReplacer, c.t.x.io.xml.XmlFriendlyReader and c.t.x.io.xml.XmlFriendlyWriter.</li>
606 <li>Deprecated c.t.x.io.xml.AbstractXmlDriver, c.t.x.io.xml.AbstractXmlReader and c.t.x.io.xml.AbstractXmlWriter, added
607 c.t.x.io.AbstractDriver, c.t.x.io.AbstractReader and c.t.x.io.AbstractWriter instead.</li>
608 <li>Deprecated all constructors of Driver, Reader and Writer implementations that take a XmlFriendlyReplacer as argument,
609 added constructors taking a NameCoder instead.</li>
610 <li>Added interface com.thoughtworks.xstream.converters.ErrorReporter to allow other types to report
611 also errors (apart from a HierarchicalStreamReader). Any converter and the parent object of the currently deserialized
612 element may provide additional error information now.</li>
613 </ul>
614
615 <h1 id="1.3.1">1.3.1</h1>
616
617 <p>Released December 6, 2008.</p>
618
619 <p class="highlight">CGLIB support must be explicitly activated now. The decision has been made due to possible problems using an own
620 classloader and because of ongoing complaints about occurring exceptions in the CGLIBEnhancedConverter at XStream initialization although
621 they are caused by incompatible ASM versions on the user's classpath (JIRA:XSTR-469, JIRA:XSTR-513 and JIRA:XSTR-518).</p>
622
623 <p class="highlight">XStream uses some attributes on its own. Until now it was possible to use XStream.aliasAttribute to define a different
624 name. This does still work but is deprecated for system attributes. Use the new call XStream.aliasSystemAttribute for such an alias.</p>
625
626 <h2>Major changes</h2>
627
628 <ul>
629 <li>JIRA:XSTR-515: CGLIB support is no longer activated automatically and has to be
630 <a href="faq.html#Serialization_CGLIB">explicitly turned on</a>.</li>
631 <li>JIRA:XSTR-448: Separated system attributes and user defined attributes for aliases.</li>
632 <li>JIRA:XSTR-55: Ability to alias a package name.</li>
633 <li>JIRA:XSTR-434: New JsonWriter instead of JsonHierarchicalStreamWriter with mode to strip root node of generated JSON (by Paul Hammant).</li>
634 <li>Support for Diablo JDK on FreeBSD (by Reto Bachmann-Gm&uuml;r).</li>
635 <li>JIRA:XSTR-495: New PersistenceStrategy instead of StreamStrategy (based on the code and comments by Alexander Radzin).</li>
636 </ul>
637
638 <h2>Minor changes</h2>
639
640 <ul>
641 <li>Support special Jettison functionality for JSON to detect collections or arrays with one element introduced with Jettison 1.0.</li>
642 <li>JIRA:XSTR-493: Using attributes for fields with XML-unfriendly names results in NPE at deserialization.</li>
643 <li>JIRA:XSTR-497: Unsafe operation with WeakHashMap can raise a NPE in Sun14ReflectionProvider.</li>
644 <li>JIRA:XSTR-423: Support of CGLIB enhanced proxies with multiple callbacks if the proxy uses a factory (CGLIB default).</li>
645 <li>JIRA:XSTR-536: XStream silently ignores unknown elements.</li>
646 <li>JIRA:XSTR-503: Omitted properties in JavaBeans are requested at serialization (by Kevin Conaway).</li>
647 <li>Fix possible memory leak in ObjectIdMap for JVMs that provide real distinct identity hash codes (happened on amd64 system).</li>
648 <li>JIRA:XSTR-480: Aliasing of array types.</li>
649 <li>JIRA:XSTR-515: The SubjectConverter and DurationConverter are only registered if the converted class is part of the JDK,
650 otherwise they must be registered now explicitly.</li>
651 <li>JIRA:XSTR-504: XmlHeaderAwareReader fails with improper sized PushbackInputStream.</li>
652 <li>JIRA:XSTR-489: @XStreamConverter supports now also SingleValueConverter implementations.</li>
653 <li>JIRA:XSTR-481: @XStreamConverter and @XStreamAsAttribute can be used together (as a result of JIRA:XSTR-489).</li>
654 <li>JIRA:XSTR-519: New annotation @XStreamInclude to force annotation detection of included types (by Seven Sparling).</li>
655 <li>JIRA:XSTR-469: Support custom converters for enum types.</li>
656 <li>JIRA:XSTR-502: ClassNotFoundException even if writeReplace returns proper object.</li>
657 <li>JIRA:XSTR-529: NullPointerException for null elements in implicit lists.</li>
658 <li>JIRA:XSTR-517: Miscellaneous performance improvements (by Tatu Saloranta).</li>
659 <li>JIRA:XSTR-525: JsonHierarchicalStreamDriver writes invalid JSON in case of system attribute.</li>
660 <li>JIRA:XSTR-535: Mode to allow plain values as result for JSON without root node.</li>
661 <li>JIRA:XSTR-531: Possibility to omit system attributes.</li>
662 <li>JIRA:XSTR-508: Fix marshalling error for nested serializable objects with own writeReplace/readResolve methods.</li>
663 <li>JIRA:XSTR-507: Advanced ReferenceByIdMarshaller uses id of the current object if available.</li>
664 <li>JIRA:XSTR-485: Check reference for valid object when deserializing.</li>
665 <li>Fix classloader problem, Xpp3 parser cannot be loaded within a web application.</li>
666 <li>Dependencies have been updated to latest versions of JDOM, Jettison, Joda Time, and Woodstox. Note for Maven
667 builds that the <em>groupId</em> of JDOM has changed.</li>
668 <li>Fix possible IndexOutOfBoundsException creating returning the message for a ConversionException.</li>
669 <li>JIRA:XSTR-495: StreamStrategy cannot handle key with value <em>null</em>.</li>
670 </ul>
671
672 <h2>API changes</h2>
673
674 <ul>
675 <li>Deprecated c.t.x.io.json.JsonHierarchicalStreamWriter in favour of c.t.x.io.json.JsonWriter.</li>
676 <li>c.t.x.mapper.EnumMapper no longer derives from the c.t.x.mapper.AttributeMapper as it has been before version 1.3. Therefore the new
677 constructor has been deprecated in favour of the old one.</li>
678 <li>c.t.x.mapper.Mapper.getConverterFromAttribute(Class, String) has been deprecated in favour of
679 c.t.x.mapper.Mapper.getConverterFromAttribute(Class, String, Class) taking the type as third argument that should be handled by the
680 converter.</li>
681 <li>c.t.x.core.ReferenceByIdMarshaller.IdGenerator.next() has now the current object as argument.</li>
682 <li>New c.t.x.persistence.PersistenceStrategy and c.t.x.persistence.FilePersistenceStrategy.</li>
683 <li>Deprecated c.t.x.persistence.StreamStrategy and c.t.x.persistence.FileStreamStrategy.</li>
684 </ul>
685
686 <h1 id="1.3">1.3</h1>
687
688 <p>Released February 27, 2008.</p>
689
690 <h2>Major changes</h2>
691
692 <ul>
693 <li>ReflectionConverter writes now the fields of the parent classes first.</li>
694 <li>Support for Converter definition at field level.</li>
695 <li>Refactoring of Annotation support, invent auto-detection mode.</li>
696 <li>Annotated converters are no longer detected automatically, all annotations are now handled in the same way.</li>
697 <li>JIRA:XSTR-334: XStream will deserialize directly from a file or URL. Some parser take advantage of these objects to
698 define a SystemId used to resolve further references in XML, schema or DTD. Appropriate createReader methods have been
699 added to c.t.x.io.HierarchicalStreamDriver.</li>
700 <li>JIRA:XSTR-261: All c.t.x.io.HierarchicalStreamDriver implementations respect now the encoding of an XML header
701 if read from an InputStream.</li>
702 <li>DomDriver does no longer use explicitly UTF-8 by default, DomReader will therefore respect the encoding defined
703 in the XML header or use native encoding</li>
704 <li>JIRA:XSTR-415: JavaBeanConverter uses now BeanIntrospection (by Hinse ter Schuur).</li>
705 <li>JIRA:XSTR-424: DateConverter uses now by default SimpleDateFormat instances in non-lenient mode.</li>
706 <li>JIRA:XSTR-386: SingleValueConverter that utilizes PropertyEditor implementations (by Jukka Lindstr&ouml;m).</li>
707 <li>JIRA:XSTR-427: Converter for javax.xml.datatype.Duration (by John Kristian).</li>
708 <li>JIRA:XSTR-305: Field alias inheritance (by David Blevins).</li>
709 <li>XStream failed to initialize in environments without AWT or SQL classes.</li>
710 <li>JIRA:XSTR-420: XPath of references are not XmlFriendly encoded.</li>
711 <li>JIRA:XSTR-473: String &quot;\0&quot; serialized as invalid XML, support compliant behaviour according XML version.</li>
712 <li>JIRA:XSTR-431: Direct support of enhanced mode for SAP JVM (thanks to Norbert Kuck by SAP).</li>
713 <li>JIRA:XSTR-437: Static cache in annotation processing causes failing OSGi bundles.</li>
714 <li>JIRA:XSTR-279+JIRA:XSTR-335: Annotations are not inherited from parent class.</li>
715 <li>Fix StringConverter using a WeakHashMap with strong references in its value.</li>
716 <li>JIRA:XSTR-403: Attributes are no longer written with JSONHierarchicalStreamDriver if current object is a collection.</li>
717 <li>JIRA:XSTR-456: New LookAndFeelConverter handling LookAndFeel implementations with reflection.</li>
718 <li>JIRA:XSTR-462: CachingMapper keeps direct class references.</li>
719 <li>JIRA:XSTR-411: JsonHierarchicalStreamDriver does not escape characters according RFC 4627.</li>
720 <li>JsonHierarchicalStreamDriver writes wrong brackets around complex Java types with a single value.</li>
721 <li>JsonHierarchicalStreamDriver writes attribute names with a leading '@'.</li>
722 <li>JsonHierarchicalStreamDriver supports Map implementations.</li>
723 </ul>
724
725 <h2>Minor changes</h2>
726
727 <ul>
728 <li>Added converter for java.lang.StringBuilder instances.</li>
729 <li>Added converter for java.util.UUID instances.</li>
730 <li>JIRA:XSTR-430: Fields written as attributes could not be omitted.</li>
731 <li>JIRA:XSTR-407: Comparator might access uninitialized elements for TreeSet and TreeMap. A deserialized
732 Comparator is no longer called, the converters expect the elements now in a sorted order.</li>
733 <li>JIRA:XSTR-404, @XStreamImplicit() for ArrayList&lt;ArrayList&lt;Type&gt;&gt; throws ClassCastException.</li>
734 <li>@XStreamContainedType() for ArrayList&lt;ArrayList&lt;Type&gt;&gt; throws ClassCastException.</li>
735 <li>XStreamer did not persist a FieldKeySorter instance.</li>
736 <li>JIRA:XSTR-241: JavaBeanConverter now supports customized BeanProvider.</li>
737 <li>JIRA:XSTR-280: JavaBeanConverter now supports aliasField and omitField (by Hinse ter Schuur).</li>
738 <li>JIRA:XSTR-280: SerializationConverter now supports aliasField and omitField.</li>
739 <li>JIRA:XSTR-429: XmlFriendlyReplacer support for SaxWriter and TraxSource (by Adrian Wilkens).</li>
740 <li>JIRA:XSTR-421: Characters cannot be written as attribute.</li>
741 <li>JIRA:XSTR-426: java.swt.KeyStroke not properly serialized because of a character undefined in unicode.</li>
742 <li>JIRA:XSTR-352: Strings with arbitrary ISO control characters are not properly serialized.</li>
743 <li>JIRA:XSTR-428: An attribute named like a transient field did abort deserialization of following fields.</li>
744 <li>JIRA:XSTR-443: XStream.createObjectOutputStream does not use the given driver to create the HierarchicalStreamWriter.</li>
745 <li>JIRA:XSTR-440: Implicit collections can be declared for fields that are not of Collection type.</li>
746 <li>JIRA:XSTR-446: Handle all primitives and their boxed counterpart for JsonHierarchicalStreamDriver.</li>
747 <li>JIRA:XSTR-447: Fix deserialization of Array class types in JDK 6 (see JDK bug 6500212).</li>
748 <li>JIRA:XSTR-450: @XStreamAlias is ignored if attributes should be used for the field type.</li>
749 <li>JIRA:XSTR-418: Inherited @XStreamAlias is ignored if field should be rendered as attribute.</li>
750 <li>JIRA:XSTR-393: Annotation processing is not consistent.</li>
751 <li>JIRA:XSTR-412: @XStreamImplicit throws NPE for untyped collections.</li>
752 <li>JIRA:XSTR-463: Cannot provide own default Mapper chain.</li>
753 <li>JIRA:XSTR-464: Cannot provide a ClassLoader that is used in all cases.</li>
754 <li>JIRA:XSTR-394: Allow enums as attributes.</li>
755 <li>JIRA:XSTR-413: Support @XStreamAsAttribute for enums.</li>
756 <li>JIRA:XSTR-478: Cannot specify default implementation for polymorphic enum.</li>
757 <li>JIRA:XSTR-419: Treat enums as immutable types.</li>
758 <li>Update annotation tutorial, explain limitations of auto-detection mode.</li>
759 <li>Added copyright notices to all files.</li>
760 <li>StaxWriter.flush did close Stax' XMLStreamWriter instead of flushing it.</li>
761 <li>JIRA:XSTR-471: XStream POMs do no longer declare a repository at all.</li>
762 <li>Calendar object could not be rendered with JSONHierarchicalStreamDriver.</li>
763 <li>JIRA:XSTR-476: Properties can be sorted by key.</li>
764 <li>XStream.createObjectInputStream and XStream.createObjectOutputStream
765 overloaded to support a binary InputStream or OutputStream.</li>
766 <li>JIRA:XSTR-470: Allow transient fields to be optionally deserialized.</li>
767 </ul>
768
769 <h2>API changes</h2>
770
771 <ul>
772 <li>c.t.x.annotation.Annotations, c.t.x.annotation.AnnotationReflectionConverter and c.t.x.annotation.AnnotationProvider deprecated.
773 Functionality is integrated in new c.t.x.mapper.AnnotationMapper and accessible with new methods c.t.x.XStream.processAnnotations().</li>
774 <li>New auto-detection mode for annotations, that can be turned on with c.t.x.XStream.autodetectAnnotations()</li>
775 <li>c.t.x.annotation.@XStreamContainedType deprecated, the behaviour is now always active and the annotation therefore superfluous.</li>
776 <li>Due to JIRA:XSTR-421 null characters are no longer written as tag with an attribute (&lt;char null=&quot;true&quot;/&gt;),
777 but as empty tag. The old representation is still supported at deserialization.</li>
778 <li>Characters that are not defined in unicode or ISO control characters (expect TAB and LF) are written as numerical entity now.</li>
779 <li>XPath references are now also XML-friendly encoded to match the path exactly. Unencoded references will normally work anyway,
780 but in special cases the exact behaviour of XStream 1.2.x might be necessary. See acceptance tests for XStream 1.2.x compatibility.</li>
781 <li>c.t.x.core.BaseException deprecated in favour of c.t.x.XStreamException as base exception for all exceptions XStream throws.</li>
782 <li>c.t.x.XStream.InitializerException deprecated in favour of c.t.x.InitializerException.</li>
783 <li>New methods get() and keys() in interface c.t.x.converter.ErrorWriter.</li>
784 <li>c.t.x.mapper.XmlFriendlyMapper deprecated, technology is replaced since version 1.2 by c.t.x.io.xml.XmlFriendlyReplacer as part of the
785 different XmlWriter implementations.</li>
786 <li>c.t.x.mapper.Mapper.aliasForAttribute() and c.t.x.mapper.Mapper.attributeForAlias() deprecated, since it provided in reality the combined
787 functionality of c.t.x.mapper.Mapper.serializedMember()/realMember() and c.t.x.mapper.Mapper.getConverterFromItemType().</li>
788 <li>c.t.x.XStream(ReflectionProvider, Mapper, HierarchicalStreamDriver) deprecated, in favour of
789 c.t.x.XStream(ReflectionProvider, HierarchicalStreamDriver, Mapper, ClassLoader).</li>
790 <li>New interface c.t.x.converter.ConverterRegistry to express explicit functionality managing the converters.</li>
791 <li>c.t.x.core.DefaultConverterLookup no longer uses a c.t.x.mapper.Mapper. Therefore the old constructor has been deprecated in favour
792 of a default constructor.</li>
793 <li>Overloaded methods of c.t.x.mapper.Mapper.getConverterFromItemType and c.t.x.mapper.Mapper.getConverterFromAttribute have been
794 deprecated. Only one version has been kept, the implementation can handle all cases now at once and therefore multiple calls to the mapper chain
795 are avoided.</li>
796 <li>c.t.x.mapper.EnumMapper derives now from the c.t.x.mapper.AttributeMapper to support enums as attributes. Therefore the old constructor
797 has been deprecated in favour of one taking an additional c.t.x.converters.ConverterLookup that has to be passed to the new parent.</li>
798 </ul>
799
800 <p class="highlight">Note, to support a representation of null values in some way, it is absolutely necessary that each converter can handle a null
801 value in its marshalling methods. If you have implemented your own custom converters, try to handle such a case also to prevent incompatibilities
802 in case XStream will provide such values with its next major version.</p>
803
804 <h1 id="1.2.2">Version 1.2.2</h1>
805
806 <p>Released May 24, 2007.</p>
807
808 <p class="hightlight">Note, that next version of XStream will behave slightly different by default. XStream emits
809 all fields in declaration order like Java serialization. But in contrast to Java it will omit the fields of parent
810 classes last while Java serialization emits them first. This makes it difficult to match a given XML schema that
811 defined inherited types or leads sometimes to obscure initialization problems. However, XStream itself will not be
812 affected by the changed order of elements in the XML, any deserialization of current XML representations will work
813 fine. Anyway we will provide with XStream 1.3 a FieldKeySorter implementation that mimics the old behaviour. In
814 the meanwhile you can enforce the new field sorting by installing the NaturalFieldKeySorter.</p>
815
816 <h2>Major changes</h2>
817
818 <ul>
819 <li>JIRA:XSTR-391, Support for writing (and reading) JSON by the new JettisonMappedXmlDriver (by Dejan Bosanac).</li>
820 <li>New FieldKeySorter interface allows a custom sort order of the XML elements.</li>
821 <li>JIRA:XSTR-68 and JIRA:XSTR-210, OmitField is now respected at deserialization to ignore removed fields.</li>
822 </ul>
823
824 <h2>Minor changes</h2>
825
826 <ul>
827 <li>JIRA:XSTR-387, Fix aliasing of inherited fields.</li>
828 <li>JIRA:XSTR-395, Fix StringConverter allocating PermGen space.</li>
829 <li>JIRA:XSTR-368, @XStreamConverter converters should be cached inside the AnnotationReflectionConverter.</li>
830 <li>JIRA:XSTR-392, @XStreamOmitField can be used to omit fields from the resulting XML (contributed by Chung-Onn Cheong).</li>
831 <li>JIRA:XSTR-371, Fix JSONWriter that omits a closing bracket for for fields with null value.</li>
832 <li>JIRA:XSTR-398, DomDriver ignores given XmlFriendlyReplacer.</li>
833 <li>JIRA:XSTR-370, Buildable with JDK 6, fix FontConverter for JDK 6.</li>
834 <li>JIRA:XSTR-382, Support hex and octal number values.</li>
835 <li>DateConverter did not respect change in TimeZone after first usage.</li>
836 <li>JIRA:XSTR-375, Support for aliasing native types.</li>
837 <li>JIRA:XSTR-243 again, XML elements for transient fields are now ignored completely at deserialization.</li>
838 <li>Release unused object references to keep memory print low.</li>
839 <li>Support for AWT and SQL is now optional: XStream now works on embedded virtual machines lacking such APIs (by Nicolas Gros d'Aillon).</li>
840 <li>Support raw bytes read from the ObjectInputStream.</li>
841 <li>JIRA:XSTR-373, Support for Hitachi JVM (tested by Yuji Yamano).</li>
842 <li>JIRA:XSTR-378 and JIRA:XSTR-379, Fix TextAttributeConverter and EnumSetConverter failing on Apache Harmony.</li>
843 <li>JIRA:XSTR-363, Support of native field order i.e. fields are processed in declaration order base classes first.</li>
844 <li>JIRA:XSTR-320, Static field in child may hide non-static field in parent.</li>
845 </ul>
846
847 <h2>API changes</h2>
848
849 <ul>
850 <li>JIRA:XSTR-365, Multiple implicit collections with annotations. Deprecated @XStreamImclicitCollection in favour of @XStreamImplicit
851 declared at field level.</li>
852 </ul>
853
854 <h1 id="1.2.1">Version 1.2.1</h1>
855
856 <p>Released November 11, 2006.</p>
857
858 <h2>Major changes</h2>
859
860 <ul>
861 <li>Introduced DocumentWriter interface and generalized functionality for all writer implementations
862 creating a DOM structure (DOM4J, DOM, JDom, Xom, Xpp3Dom).</li>
863 <li>Refactored build system to use Maven 2. Ant still supported on XStream Core.</li>
864 <li>Created separate XStream Benchmark module</li>
865 </ul>
866
867 <h2>Minor changes</h2>
868
869 <ul>
870 <li>JIRA:XSTR-346, XStream.getClassMapper() does not return a ClassMapper for the current Mapper.</li>
871 <li>Fix problem with fields containing a double underscore.</li>
872 <li>JIRA:XSTR-345, Dom4JWriter adds up attributes.</li>
873 <li>JIRA:XSTR-336, XStream fails to reference an implicit element.</li>
874 <li>JIRA:XSTR-337, Annotation cycle bug.</li>
875 <li>Fix packaging error for the resulting jar building with Maven2.</li>
876 <li>JIRA:XSTR-339, NPE for attribute null values.</li>
877 <li>JIRA:XSTR-338, NPE in JSON writer for converters using non-extended HierarchicalStreamWriter.</li>
878 <li>JIRA:XSTR-357, Fix escaping of values in JSON writer.</li>
879 <li>JIRA:XSTR-356, Fix unmarshaling error for fields containing proxies.</li>
880 <li>JIRA:XSTR-349, Fix backward compatibility of Dom4jWriter.</li>
881 <li>JIRA:XSTR-309, More versatile boolean conversion options (contributed by David Blevins).</li>
882 <li>Add XStream.getReflectionProvider() to retrieve ReflectionProvider in use.</li>
883 <li>JIRA:XSTR-358, @XStreamConverter annotation does not call converter constructor.</li>
884 <li>Website generated using <a href="http://xsite.codehaus.org">XSite</a></li>
885 </ul>
886
887 <h2>API changes</h2>
888
889 <ul>
890 <li>Deprecate JDomWriter.getResult() in favour of DocumentWriter.getTopLevelNodes().</li>
891 <li>Deprecate ThreadSafeSimpleDateFormat, since this is an internal helper and not part of XStream API.</li>
892 </ul>
893
894 <h1 id="1.2">Version 1.2</h1>
895
896 <p>Released August 18, 2006.</p>
897
898 <h2>Major changes</h2>
899
900 <ul>
901 <li>JIRA:XSTR-269, Using attributes for fields (contributed by Paul Hammant and Ian Cartwright).</li>
902 <li>Aliasing of arbitrary attributes.</li>
903 <li>JIRA:XSTR-50, XStream can now serialize another XStream instance.</li>
904 <li>JIRA:XSTR-227, XStream has now the XStreamer, that serializes an object together with its XStream instance.</li>
905 <li>JIRA:XSTR-278, AnnotationConverter for fields (contributed by Guilherme Silveira).</li>
906 <li>JIRA:XSTR-256, PureJavaReflectionProvider supports now final fields starting with JDK 1.5</li>
907 <li>JIRA:XSTR-258, Any Collection type can now be declared implicit, the default implementation will be respected for unmarshaling.</li>
908 <li>JIRA:XSTR-88, XStream can now write all references as absolute XPath expression.</li>
909 <li>JIRA:XSTR-62 and JIRA:XSTR-211, New SingeValueConverter allows light weight converters if the value can be represented by a unique string.</li>
910 <li>Aliasing of classes of a specific type.</li>
911 <li>JIRA:XSTR-239, Support for certain types of proxies generated with the CGLIB Enhancer.</li>
912 <li>JIRA:XSTR-90 and JIRA:XSTR-311, Support for BEA JRockit starting with R25.1.0 (contributed by Henrik St&aring;hl of BEA).</li>
913 </ul>
914
915 <h2>Technology preview</h2>
916
917 <ul>
918 <li>Experimental binary reader and writer.</li>
919 <li>Experimental HierarichicalStreamCopier allows streams to be copied from one format to another without the overhead of serialization.</li>
920 <li>Experimental JSON support allows streams to be copied from one format to another without the overhead of serialization (contributed by Paul Hammant).</li>
921 </ul>
922
923 <h2>Minor changes</h2>
924
925 <ul>
926 <li>JIRA:XSTR-266, XStream fails to serialize elements of a unserializable class, that is a base class of a derived class</li>
927 <li>JIRA:XSTR-236, Priority constants for converter registration are now public</li>
928 <li>JIRA:XSTR-215, XStream writes now fields in declaration order even for JVMs reporting them in reverse order like IBM JDK.</li>
929 <li>JIRA:XSTR-276 and JIRA:XSTR-283, XStream does no longer attempt to create references to implicit element.</li>
930 <li>JIRA:XSTR-244, Closing a Writer can now be done twice, but any write attempt will later on fail.</li>
931 <li>JIRA:XSTR-243, Transient fields were unmarshalled from XML.</li>
932 <li>JIRA:XSTR-250, Providing a mapper to the XStream constructor will no longer result in a NPE.</li>
933 <li>JIRA:XSTR-281, After registering a new converter, the internal converter cache is now cleared.</li>
934 <li>JIRA:XSTR-284, XStream checks the object returned by a converter for compatibility.</li>
935 <li>XStream no longer fails serializing a Throwable without cause when no references shall be written.</li>
936 <li>Converter for java.awt.font.TextAttribute.</li>
937 <li>Converter for java.nio.charset.Charset.</li>
938 <li>JIRA:XSTR-286, XStream detects impossible self serialization and throws now an appropriate ConversionException.</li>
939 <li>JIRA:XSTR-291, XomDriver implementation added.</li>
940 <li>JIRA:XSTR-299, Fix for implicit collections with items using the same name as the field name of the underlying collection.</li>
941 <li>JIRA:XSTR-245, Broken XML with custom serialization in certain cases (patch contributed by Cyrille Le Clerc).</li>
942 <li>JIRA:XSTR-304, Bad handling of repairing namespace flag for StaxDriver (patch contributed by John Kristian).</li>
943 </ul>
944
945 <h2>API changes</h2>
946
947 <ul>
948 <li>JIRA:XSTR-252, Refactored support for XML friendly character mapping.</li>
949 <li>JIRA:XSTR-69, Refactored ReflectionConverter allows simpler subclassing.</li>
950 <li>Unmarshalling context has now an overloaded version of the method convertAnother to provide the Converter directly.</li>
951 <li>Deprecate ClassMapper for Mapper. All methods with a ClassMapper parameter have now a duplicate taking only a Mapper. The variant with the ClassMapper is deprecated.</li>
952 <li>Deprecate c.t.x.alias.CannotResolveClassException for c.t.x.mapper.CannotResolveClassException.</li>
953 <li>Deprecate NameMapper (was not used within XStream anymore anyway).</li>
954 <li>Deprecate constructor of DefaultMapper taking an alternative name for the class attribute. Use the aliasAttribute method.</li>
955 <li>Deprecate attributeForImplementationClass, attributeForClassDefiningField, attributeForReadResolveField, and attributeForEnumType in favour of the generalized aliasForAttribute in the Mapper interface.</li>
956 <li>Removed all deprecated stuff from 1.1.x and 1.0.x</li>
957 <li>JIRA:XSTR-211, A lot of existing (basic) Converters have been refactored to use the new SingleValueConverter interface.</li>
958 <li>Dom4JWriter uses now a DocumentFactory and a XMLWriter as constructor arguments.</li>
959 </ul>
960
961 <h1 id="1.1.3">Version 1.1.3</h1>
962
963 <p>Released January 13, 2006.</p>
964
965 <h2>Major changes</h2>
966
967 <ul>
968 <li>Added XStream.toXML(OutputStream) and XStream.fromXML(InputStream).</li>
969 <li>Ability to prevent fields from being serialized by calling XStream.omitField() or by implementing Mapper.shouldSerializeMember().</li>
970 <li>Added Converter for Enum, EnumMap and EnumSet</li>
971 <li>JIRA:XSTR-186, Added BeanConverter (contributed by Andrea Aime)</li>
972 <li>JIRA:XSTR-246, Added ISO8601SqlTimestampConverter (contributed by Cheong, Chung-Onn)</li>
973 <li>Added ISO8601GregorianCaledarConverter</li>
974 <li>JIRA:XSTR-215, Fixed support for IBM JVM (contributed by Gabor Liptak)</li>
975 <li>Enhanced mode support for Blackdown JDK</li>
976 <li>JIRA:XSTR-265, support for javax.security.auth.Subject</li>
977 <li>JIRA:XSTR-233, support for Integer[] arrays</li>
978 </ul>
979
980 <h2>Minor changes</h2>
981
982 <ul>
983 <li>Remove unnecessary PrintWriter wrapper in default writers (pointed out by Mathieu Champlon)</li>
984 <li>Bugfix: EnumSet converter can now deal with empty sets (contributed by Baba Buehler)</li>
985 <li>Update ISO8601DateConverter to use Joda 1.0</li>
986 <li>JIRA:XSTR-242, GregorianCalenderConverter saves now the timezone</li>
987 <li>JIRA:XSTR-247, ISO8601DateConverter now independent on timezone</li>
988 <li>JIRA:XSTR-263, Circular references with Externalizable objects fail</li>
989 </ul>
990
991 <h2>API changes</h2>
992
993 <ul>
994 <li>None.</li>
995 </ul>
996
997 <h1 id="1.1.2">Version 1.1.2</h1>
998
999 <p>Released April 30, 2005. Most popular feature requests implemented. Java 5 Enum support. Serialization of JavaBeans
1000 using accessors. Aliasing of fields. StAX integration, with namespaces. Improved support on JDK 1.3 and IBM JDK. </p>
1001
1002 <h2>Major changes</h2>
1003
1004 <ul>
1005 <li>JIRA:XSTR-186, Option to serialize JavaBeans using public accessors, rather than private fields (contributed by Andrea Aime).</li>
29
30 <h1 id="1.4.10">1.4.10</h1>
31
32 <p>Released May 23, 2017.</p>
33
34 <p class="highlight">This maintenance release addresses also the security vulnerability <a href="CVE-2017-7957.html">
35 CVE-2017-7957</a>, used for a Denial of Service attack by crashing the Java runtime.</p>
36
37 <h2>Major changes</h2>
38
39 <ul>
40 <li>Fix PrimitiveTypePermission to reject type <em>void</em> to prevent CVE-2017-7957 with an initialized
41 security framework.</li>
42 <li>Improve performance by minimizing call stack of mapper chain.</li>
43 <li>GHPR:#82, JIRA:XSTR-774: Add converters for types of java.time, java.time.chrono, and java.time.temporal
44 packages (converters for LocalDate, LocalDateTime, LocalTime, OffsetDateTime, and ZonedDateTime by Matej Cimbora).</li>
45 <li>GHI:#29: JavaBeanConverter does not respect ignored unknown elements.</li>
46 <li>Add XStream.setupDefaultSecurity to initialize security framework with defaults of XStream 1.5.x.</li>
47 <li>Emit error warning if security framework has not been initialized and the XStream instance is vulnerable to
48 known exploits.</li>
49 </ul>
50
51 <h2>Stream Compatibility</h2>
52
53 <ul>
54 <li>The alias <em>duration</em> for type <em>javax.xml.datatype.Duration</em> has changed to <em>xml-duration</em>
55 due to the support of the classes in the java.time package. <em>duration</em> is now used for type <em>java.time.Duration</em>.
56 Simply register the alias <em>duration</em> again for type <em>javax.xml.datatype.Duration</em> if backward
57 compatibility is required for this type.
58 </li>
59 <li>All types of the java.time packages that have been written with previous versions of XStream can still be
60 deserialized.</li>
61 </ul>
62
63 <h2>Minor changes</h2>
64
65 <ul>
66 <li>GHI:#54: Fix BeanProvider.canInstantiate(Class), method may not throw exception.</li>
67 <li>GHI:#76 and GHPR:#77: Missing support for cascaded writeReplace calls.</li>
68 <li>GHI:#61: Regression in 1.4.9: Performance drop in ImplicitCollectionMapper.</li>
69 <li>GHI:#52: PathConverter fails for file paths with spaces.</li>
70 <li>PathConverter uses always forward slashes as path separator.</li>
71 <li>GHI:#53: SqlTimestampConverter cannot parse values without fraction.</li>
72 <li>GHI:#45: Support different time zones for SqlTimestampConverter.</li>
73 <li>GHI:#67 and GHPR:#68: Allow usage of DataHolder for createObjectInputStream and createObjectOutputStream.</li>
74 <li>GHI:#75: Use java.time.* package instead of Joda-Time.</li>
75 <li>Dom4JXmlWriter does not flush writer at endDocument().</li>
76 <li>Path is an immutable type.</li>
77 <li>GHPR:#65: Protect converter lookup against runtime errors.</li>
78 <li>Current Java 9 implementation reports itself as version 9 now.</li>
79 </ul>
80
81 <h2>API changes</h2>
82
83 <ul>
84 <li>Added c.t.x.util.JVM.is9().</li>
85 <li>Added c.t.x.XStream.setupDefaultSecurity(XStream).</li>
86 <li>Added c.t.x.XStream.createObjectInputStream(HierarchicalStreamReader, DataHolder) and
87 c.t.x.XStream.createObjectOutputStream(HierarchicalStreamWriter, String, DataHolder).</li>
88 <li>Added c.t.x.converters.javabean.PropertyDictionary.propertyDescriptorOrNull(Class, String).</li>
89 <li>Added method c.t.x.mapper.Mapper.IsIgnoredElement(String)</li>
90 <li>Added c.t.x.mapper.ElementIgnoringMapper.</li>
91 <li>Deprecated method c.t.x.mapper.FieldAliasingMapper.addFieldsToIgnore(Pattern).</li>
92 <li>Deprecated method c.t.x.mapper.FieldAliasingMapper.omitField(Class, String).</li>
93 <li>Deprecated method c.t.x.core.util.JVM.is17().</li>
94 <li>Deprecated method c.t.x.core.util.JVM.is19().</li>
95 </ul>
96
97 <h1 id="1.4.9">1.4.9</h1>
98
99 <p>Released March 15, 2016.</p>
100
101 <p class="highlight">This maintenance release addresses also the security vulnerability <a href="CVE-2016-3674.html">
102 CVE-2016-3674</a>, known as XXE vulnerability that can be used to expose arbitrary data from the file system
103 when unmarshalling.</p>
104
105 <h2>Major changes</h2>
106
107 <ul>
108 <li>GHI:#25: Fix <a href="https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing">XXE
109 vulnerability (CVE-2016-3674)</a>: Fixed affected drivers were Dom4JDriver, DomDriver, JDomDriver, JDom2Driver,
110 SjsxpDriver, StandardStaxDriver and WstxDriver. Still vulnerable are BEAStaxDriver and XomDriver. Processing of
111 (external) entities has been disabled. See <a href="faq.html#Security_XXEVulnerability">FAQ</a> for more information.
112 </li>
113 <li>Benchmark module has been deprecated in favor of <a href="http://openjdk.java.net/projects/code-tools/jmh/">
114 JMH (Java Microbenchmarking Harness)</a>.
115 </li>
116 <li>GHI:#33 and GHPR:#38: Add converter for java.nio.file.Path (by Aaron Jonson).</li>
117 </ul>
118
119 <h2>Minor changes</h2>
120
121 <ul>
122 <li>GHI:#35: AnnotationMapper dropped silently constructor arguments for converters if they were equal.</li>
123 <li>Fix: Possible concurrency problem with XomDriver.</li>
124 <li>JIRA:XSTR-773, GHPR:#3: Minimize memory footprint by not keeping internal references to instances of
125 immutable types.</li>
126 <li>Drop automatic reference support at deserialization time for immutable types before version 1.4 (primitive
127 types and their boxed counterpart, java.lang.Class, java.lang.String, java.math.BigDecimal, java.math.BigInteger,
128 java.io.File, java.net.URL, and java.awt.font.TextAttribute).</li>
129 <li>Fix: Implicit collection declaration is erroneously inherited or propagated to hidden field of same name.</li>
130 <li>XStreamConverter annotation supports null values as arguments for converter instantiation.</li>
131 <li>GHI:#5: Support null values for JavaBean properties.</li>
132 <li>GHI:#36: Fix NamedMapConverter, does not use SingleValueConverter of value if value is text of entry element.</li>
133 <li>GHI:#13: Own converter for javax.activation.ActivationDataFlavor, because ExternalizableConverter cannot
134 handle a type that violates the Java specification.</li>
135 <li>GHPR:#18: Minimize synchronized block in FieldDictionary.</li>
136 <li>JIRA:XSTR-769: Synthetic fields with references to outer class use compiler dependent names.</li>
137 <li>JIRA:XSTR-771: UUID is an immutable type by default.</li>
138 <li>GHPR:#23: Constructor of AbstractXppDriver swallows causing exception.</li>
139 <li>GHI:#28: Fix functionality of ClassAliaslingMapper.itemTypeAsAttributes(Class).</li>
140 <li>GHI:#37: Historical Java 1.3 support suppresses causing exception of a thrown InvocationTargetException.</li>
141 <li>GHI:#41: Cannot instantiate ToAttributedValueConverter with null value for valueFieldName using
142 XStreamConverter annotation.</li>
143 <li>Fix example code in description of security framework.</li>
144 <li>Clean-up usage of exceptions.</li>
145 </ul>
146
147 <h2>API changes</h2>
148
149 <ul>
150 <li>Added c.t.x.XStream.addImmutableType(Class, boolean) and deprecated c.t.x.XStream.addImmutableType(Class).</li>
151 <li>Added c.t.x.mapper.Mapper.isReferenceable(Class).</li>
152 <li>Added c.t.x.mapper.ImmutableTypesMapper.addImmutableType(Class, boolean) and deprecated
153 c.t.x.mapper.ImmutableTypesMapper.addImmutableType(Class).</li>
154 <li>Added c.t.x.io.xml.Dom4JDriver.createReader().</li>
155 <li>Added c.t.x.io.xml.DomDriver.createDocumentBuilderFactory().</li>
156 <li>Added c.t.x.io.xml.JDomDriver.createBuilder().</li>
157 <li>Added c.t.x.io.xml.JDom2Driver.createBuilder().</li>
158 <li>Added c.t.x.io.xml.XomDriver.createBuilder().</li>
159 <li>Added constructor c.t.x.converter.extended.ToAttributedValueConverter.ToAttributedValueConverter(Class,
160 Mapper, ReflectionProvider, ConverterLookup).</li>
161 <li>Added abstract c.t.x.converter.ErrorWritingException as common base for c.t.x.converter.ConversionException
162 and c.t.x.converter.reflection.ObjectAccessException.</li>
163 <li>Deprecated c.t.x.io.xml.XomDriver(Builder), c.t.x.io.xml.XomDriver(Builder, NameCoder) and
164 c.t.x.io.xml.XomDriver.getBuilder().</li>
165 <li>Deprecated c.t.x.mapper.ClassAliaslingMapper.itemTypeAsAttributes(Class) and
166 c.t.x.mapper.ClassAliaslingMapper.aliasIsAttribute(String). Methods never called, left-over from old refactoring.</li>
167 </ul>
168
169 <h1 id="1.4.8">1.4.8</h1>
170
171 <p>Released February 18, 2015.</p>
172
173 <h2>Major changes</h2>
174
175 <ul>
176 <li>Support for serializable lambda expressions and handling of non-serializable ones.</li>
177 </ul>
178
179 <h2>Minor changes</h2>
180
181 <ul>
182 <li>Detect Java 9 runtime.</li>
183 <li>JIRA:XSTR-767: Deserialization of referenced lambda expressions fail.</li>
184 <li>JIRA:XSTR-762: Private method readResolve() called on base classes.</li>
185 <li>JIRA:XSTR-761: Support ignored serialPersistentField at deserialization time.</li>
186 <li>JIRA:XSTR-755: ExternalizableConverter does not respect writeReplace and readResolve.</li>
187 <li>JIRA:XSTR-757: Deserialized TreeSet does not honor remove(Object) return value contract.</li>
188 <li>JIRA:XSTR-759: Support deserialization of <a href="http://www.w3.org/TR/NOTE-datetime">W3C datetime
189 format</a> in DateConverter with Java 7 runtime.
190 </li>
191 <li>Fix: DateConverter ignores provided locale.</li>
192 <li>JIRA:XSTR-768: ISO8601GregorianCalendarConverter may set invalid time zone for Joda-Time.</li>
193 <li>Fix: WeakCache.entrySet().iterator().next.setValue(value) returns the reference instead of the old value.</li>
194 <li>Fix: SqlTimestampConverter throws IllegalArgumentException instead of ConversionException on fromString().</li>
195 <li>Fix: CGLIBEnhancedConverter does not initialize transient members of parent after deserialization.</li>
196 <li>JIRA:XSTR-763: Set scope of org.json:json to test instead declaring the dependency as optional.</li>
197 </ul>
198
199 <h2>API changes</h2>
200
201 <ul>
202 <li>Added c.t.x.util.JVM.is19().</li>
203 <li>Added c.t.x.converter.reflection.LambdaConverter and c.t.x.mapper.LambdaMapper.</li>
204 <li>Declare c.t.x.XStream.ignoreUnknownElements(Pattern) as public.</li>
205 <li>c.t.x.converters.reflection.AbstractReflectionConverter.readResolve() is protected now.</li>
206 <li>c.t.x.mapper.AbstractAttributeAliasingMapper.readResolve() is protected now.</li>
207 <li>Deprecated c.t.x.converters.extended.StackTraceElementFactory, it is an internal helper class.</li>
208 <li>Deprecated c.t.x.converters.reflection.SerializationMethodInvoker, it is an internal helper class.</li>
209 <li>Deprecated c.t.x.io.AttributeNameIterator, it is an internal helper class.</li>
210 <li>Deprecated c.t.x.XStream.useXStream11XmlFriendlyMapper(), corresponding
211 c.t.x.mapper.XStream11XmlFriendlyMapper has been deprecated long ago.</li>
212 <li>Deprecated c.t.x.converter.basic.BooleanConverter.shouldConvert(Class,Object), undetected remainder of
213 ancient XStream version.</li>
214 </ul>
215
216 <h1 id="1.4.7">1.4.7</h1>
217
218 <p>Released February 8, 2014.</p>
219
220 <p class="highlight">This maintenance release addresses mainly the security vulnerability <a href="CVE-2013-7285.html">
221 CVE-2013-7285</a>, an arbitrary execution of commands when unmarshalling.</p>
222
223 <h2>Major changes</h2>
224
225 <ul>
226 <li>Add <a href="security.html#framework">security framework</a> to limit handled types while unmarshalling.
227 </li>
228 <li>java.bean.EventHandler no longer handled automatically because of severe security vulnerability.</li>
229 <li>JIRA:XSTR-751: New SunLimitedUnsafeReflectionProvider that uses undocumented features only to allocate new
230 instances as required on Dalvik.</li>
231 <li>Fix instantiation of AnnotationMapper that requires ConverterLookup and ConverterRegistry to be the same
232 instance.</li>
233 </ul>
234
235 <h2>Minor changes</h2>
236
237 <ul>
238 <li>XSTR-749: NPE if ReflectionConverter.canConvert(type) is called with null as argument.</li>
239 <li>XSTR-753: NPE if SerializationConverter.canConvert(type) is called with an interface type as argument that
240 extends Serializable.</li>
241 <li>Add constructor to ReflectionConverter taking an additional type to create an instance that is dedicated to a
242 specific type only.</li>
243 <li>The ConverterLookup used by default cannot be casted to a ConverterRegistry anymore.</li>
244 </ul>
245
246 <h2>API changes</h2>
247
248 <ul>
249 <li>Added package c.t.x.security with interface TypePermission, all its implementations and
250 ForbiddenClassException.</li>
251 <li>Added c.t.x.mapper.SecurityMapper handling the new type permissions.</li>
252 <li>Added methods addPermission, denyPermission, allowTypesXXX and denyTypesXXX to c.t.x.XStream to setup
253 security at unmarshalling time.</li>
254 <li>Added c.t.x.converters.reflection.SunLimitedUnsafeReflectionProvider.</li>
255 <li>Deprecated c.t.x.converters.reflection.Sun14ReflectionProvider in favor of new
256 c.t.x.converters.reflection.SunUnsafeReflectionProvider.</li>
257 <li>Added c.t.x.converters.reflection.ReflectionConverter(Mapper,ReflectionProvider,Class).</li>
258 </ul>
259
260 <h1 id="1.4.6">1.4.6</h1>
261
262 <p>Released December 12, 2013.</p>
263
264 <h2>Major changes</h2>
265
266 <ul>
267 <li>JIRA:XSTR-566 and JIRA:XSTR-200: Better compatibility with GAE and environments with active SecurityManager
268 (i.e. in an Applet). XStream converters try now to ensure already in the canConvert methods that they can handle the
269 requested type in practice and not only theoretically. Additionally the implementations even better take care, that
270 the initialization of a converter will not break the setup of XStream itself. Following modifications have been done
271 for these topics:
272 <ul>
273 <li>ReflectionConverter, SerializationConverter and LookAndFieldConverter will check if they can access the
274 fields by reflection for a requested type.</li>
275 <li>SerializationConverter and ExternalizableConverter will check if they can create an instance of a derived
276 OutputObjectStream first.</li>
277 <li>BeanProvider does no longer use reflection to locate default constructor.</li>
278 <li>AbstractAttributedCharacterIteratorAttributeConverter (and therefore TextAttributeConverter) will check
279 first if it can access the possible constants of the type by reflection.</li>
280 <li>NoClassDefFoundError raised in GAE accessing the fields of restricted types by reflection will be handled.</li>
281 <li>StackTraceElementConverter uses constructor for StackTraceElement instances in Java 5 and GEA.</li>
282 </ul>
283 </li>
284 <li>JIRA:XSTR-739 and JIRA:XSTR-746: OrderRetainingMap fails if HashMap.putAll(Map) of Java Runtime is not
285 implemented calling put for every element within the map.</li>
286 <li>New NamedArrayConverter to define names of inner elements.</li>
287 </ul>
288
289 <h2>Minor changes</h2>
290
291 <ul>
292 <li>JIRA:XSTR-747: All constructors of StaxDriver derived classes take erroneously a XmlFriendlyNameCoder instead
293 of a plain NameCoder.</li>
294 </ul>
295
296 <h2>API changes</h2>
297
298 <ul>
299 <li>Added c.t.x.converters.extended.NamedArrayConverter for free element names in arrays.</li>
300 <li>Added constructors to c.t.x.io.xml.StandardStaxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>
301 <li>Deprecated constructors of c.t.x.io.xml.StandardStaxDriver taking a XmlFriendlyNameCoder.</li>
302 <li>Added constructors to c.t.x.io.xml.BEAStaxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>
303 <li>Deprecated constructors of c.t.x.io.xml.BEAStaxDriver taking a XmlFriendlyNameCoder.</li>
304 <li>Added constructors to c.t.x.io.xml.WstxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>
305 <li>Deprecated constructors of c.t.x.io.xml.WstxDriver taking a XmlFriendlyNameCoder.</li>
306 <li>Added method canAccess to c.t.x.converter.reflection.AbstractReflectionConverter.</li>
307 <li>Added static method canCreateDerivedObjectOutputStream to c.t.x.core.JVM.</li>
308 <li>Deprecated unused member c.t.x.converter.javabean.BeanProvider.NO_PARAMS.</li>
309 <li>Deprecated unused method c.t.x.converter.javabean.BeanProvider.getDefaultConstrutor(Class).</li>
310 </ul>
311
312
313 <h1 id="1.4.5">1.4.5</h1>
314
315 <p>Released September 18, 2013.</p>
316
317 <h2>Major changes</h2>
318
319 <ul>
320 <li>JIRA:XSTR-732: Use a referencing implementation for the ClassLoader to support environments where no new
321 ClassLoader can be instantiated due to security restrictions.</li>
322 <li>JIRA:XSTR-691: Allow unknown XML elements to be ignored using new method XStream.ignoreUnknownElements.</li>
323 <li>JIRA:XSTR-728: XStream creates invalid JSON with JsonHierarchicalStreamDriver for custom converters since
324 XStream 1.4.</li>
325 <li>JIRA:XSTR-300: New EnumToStringConverter to support custom string representations of Enum values.</li>
326 <li>JIRA:XSTR-292 and JIRA:XSTR-405: New NamedMapConverter and NamedCollectionConverter to define names of inner
327 elements.</li>
328 <li>JIRA:XSTR-726: New annotation XStreamAliasType to support declarative definition of XStream.aliasType().</li>
329 <li>JIRA:XSTR-735: Support for JDOM2 with JDom2Driver, JDom2Reader and JDom2Writer.</li>
330 <li>Optimized XML structure for java.awt.Font.</li>
331 <li>Fix: ToAttributedValueConverter silently appends fields without attribute support to the value producing
332 mixed-mode XML.</li>
333 <li>JIRA:XSTR-566 and JIRA:XSTR-249: Better compatibility with Google AppEngine and J2ME, setup no longer fails
334 for unavailable converters.</li>
335 </ul>
336
337 <h2>Minor changes</h2>
338
339 <ul>
340 <li>Fix missing manifest information.</li>
341 <li>JIRA:XSTR-729: Add OSGi information to manifests.</li>
342 <li>JIRA:XSTR-723: XStream will now detect a working enhanced mode dynamically instead using lists of known
343 vendors. This allows enhanced support for JamVM if it is bundled with OpenJDK. It will currently fail on a runtime
344 based on GNU Classpath (at least up to version 0.98).</li>
345 <li>JIRA:XSTR-541: JavaScript compatibility problem with 64-bit integers in JSON.</li>
346 <li>JIRA:XSTR-719: Support replacement of default converter in any case.</li>
347 <li>JIRA:XSTR-725: processAnnotation performance improvement in concurrent situation.</li>
348 <li>JIRA:XSTR-721: EnumConverter is more lenient while parsing constants.</li>
349 <li>New constructors for CollectionConverter and MapConverter to allow registration for an individual type.</li>
350 <li>JIRA:XSTR-724: Cache class name lookup failures.</li>
351 <li>Current IBM JDK for Java 1.4.2 no longer has a reverse field ordering.</li>
352 <li>LongConverter supports now positive hex and octal numbers over Long.MAX_VALUE within 64 bit.</li>
353 <li>Fix: Sun14RefectionProvider ignores a provided FieldDictionary.</li>
354 <li>JIRA:XSTR-457: Do not write 'defined-in' attribute if not needed.</li>
355 <li>JettisonMappedXmlDriver provides better support to overwrite its create methods.</li>
356 <li>JIRA:XSTR-685: StAX based drivers (StaxDriver and JettisonMappedXmlDriver) are not closing internal input
357 stream reading from file or URL.</li>
358 <li>JIRA:XSTR-736: XStream.unmarshal may throw NPE if version info of manifest is missing.</li>
359 <li>JIRA:XSTR-733: Implicit elements that match multiple defined implicit collections will be assigned to the map
360 with the nearest matching element type.</li>
361 <li>JIRA:XSTR-740: ISO8601GregorianCalendarConverter creates Calendar instance with wrong Locale in Java 7 if the
362 Locale for the LocaleCategory.FORMAT is different to the global default Locale.</li>
363 <li>JIRA:XSTR-578: Implement support for aliasing in JavaClasConverter, JavaFieldConverter and
364 JavaMethodConverter. While it is not possible to enable this in general, new constructors have been added to these
365 converters and an example in the acceptance tests (AliasTest).</li>
366 <li>JIRA:XSTR-742: Register CompositeClassLoader in Java 7 as parallel capable.</li>
367 <li>JIRA:XSTR-743: Support proxy collections of Hibernate Envers.</li>
368 <li>Fix NPE in AttributeMapper.shouldLookForSingleValueConverter if parameters fieldName and definedIn are null.</li>
369 <li>Implicit type argument can be omitted when registering converters with @XStreamConverter annotation.</li>
370 </ul>
371
372 <h2>API changes</h2>
373
374 <ul>
375 <li>Added c.t.x.converters.extended.NamedCollectionConverter for free element names in collections.</li>
376 <li>Added c.t.x.converters.extended.NamedMapConverter for free element names in maps.</li>
377 <li>Added c.t.x.io.xml.StandardStaxDriver to use the StAX implementation delivered with the Java 6 runtime.</li>
378 <li>Deprecated c.t.x.io.xml.SjsxpStaxDriver to select the internal StAX implementation of Oracle.</li>
379 <li>Added static methods getStaxInputFactory and getStaxOutputFactory to c.t.x.core.JVM as returning the
380 implementations of javax.xml.stream.XMLInputFactory (resp. javax.xml.stream.XMLOutputFactory) delivered with the Java
381 Runtime since Java 6.</li>
382 <li>Added c.t.x.core.ClassLoaderReference.</li>
383 <li>Added constructors taking an additional Class argument for c.t.x.converters.collections.CollectionConverter
384 and c.t.x.converters.collections.MapConverter.</li>
385 <li>Added constructors taking a ClassLoaderReference instead of a ClassLoader and deprecated the ones taking the
386 ClassLoader:
387 <ul>
388 <li>c.t.x.XStream</li>
389 <li>c.t.x.converters.extended.DynamicProxyConverter</li>
390 <li>c.t.x.converters.extended.JavaClassConverter</li>
391 <li>c.t.x.converters.extended.JavaFieldConverter</li>
392 <li>c.t.x.converters.extended.JavaMethodConverter</li>
393 <li>c.t.x.converters.reflection.CGLIBEnhancedConverter</li>
394 <li>c.t.x.converters.reflection.ExternalizableConverter</li>
395 <li>c.t.x.converters.reflection.SerializableConverter</li>
396 <li>c.t.x.mapper.AnnotationMapper</li>
397 <li>c.t.x.mapper.DefaultMapper</li>
398 </ul>
399 </li>
400 <li>Added static methods newReflectionProvider, isAWTAvailable, isSQLAvailable and isSwingAvailable to
401 c.t.x.core.JVM as replacement for the deprecated non-static methods.</li>
402 <li>Deprecated c.t.x.core.JVM() and all non-static methods.</li>
403 <li>Added method useImplicitType to c.t.x.annotations.XStreamConverter.</li>
404 <li>JIRA:XSTR-722: Added c.t.x.converters.reflection.ReflectionProvider.getFieldOrNull(Class, String).</li>
405 <li>Deprecated c.t.x.converters.reflection.ReflectionProvider.fieldDefinedInClass(Class, String) in favor of new
406 c.t.x.converters.reflection.ReflectionProvider.getFieldOrNull(Class, String).</li>
407 <li>Deprecated constructor c.t.x.converters.extended.RegexPatternConverter(Converter) in favor of
408 c.t.x.converters.extended.RegexPatternConverter().</li>
409 <li>Deprecated default constructor of c.t.x.converters.extended.FontConverter in favor of
410 c.t.x.converters.extended.FontConverter(Mapper).</li>
411 <li>Deprecated constructor c.t.x.converters.extended.ThrowableConverter(Converter) in favor of
412 c.t.x.converters.extended.ThrowableConverter(ConverterLookup).</li>
413 <li>Deprecated class c.t.x.converters.reflection.SelfStreamingInstanceChecker and moved original implementation
414 into c.t.x.core.util, since it is internal.</li>
415 <li>Deprecated interface c.t.x.mapper.AnnotationConfiguration.</li>
416 </ul>
417
418 <h1 id="1.4.4">1.4.4</h1>
419
420 <p>Released January 19, 2013.</p>
421
422 <h2>Minor changes</h2>
423
424 <ul>
425 <li>JIRA:XSTR-709: Locks up on Mac with Apple JVM due to unwanted initialization of AWT.</li>
426 <li>JIRA:XSTR-711: DateConverter cannot handle dates in different era.</li>
427 <li>JIRA:XSTR-741: ToAttributedValueConverter fails to write enums as attributes.</li>
428 <li>JIRA:XSTR-712: HibernateMapper throws NPE if a collection contains null.</li>
429 <li>DateConverter supports now localized formats.</li>
430 <li>JIRA:XSTR-710: JsonWriter does not write BigInteger and BigDecimal as number values.</li>
431 <li>JIRA:XSTR-708: SqlTimestampConverter does not ignore timezone.</li>
432 <li>JIRA:XSTR-707: Creation of XmllPullParser with the XmlPullParserFactory may fail in OSGi environment.</li>
433 <li>JIRA:XSTR-705: Unnecessary synchronization accessing the field cache decreases performance.</li>
434 <li>JIRA:XSTR-714: Fields not found when XStream12FieldKeySorter used.</li>
435 </ul>
436
437 <h2>API changes</h2>
438
439 <ul>
440 <li>Deprecated method c.t.x.core.util.JVM.is14(), c.t.x.core.util.JVM.is15() and c.t.x.core.util.JVM.is16().</li>
441 </ul>
442
443 <h1 id="1.4.3">1.4.3</h1>
444
445 <p>Released July 17, 2012.</p>
446
447 <h2>Major changes</h2>
448
449 <ul>
450 <li>Support java.util.concurrent.ConcurrentHashMap with the MapConverter. This will also avoid a bug in JRockit
451 JDK reported in JIRA:XSTR-608.</li>
452 <li>JIRA:XSTR-699: Support for Hibernate 4 with XStream's Hibernate module as default for Java 6 or higher.</li>
453 </ul>
454
455 <h2>Minor changes</h2>
456
457 <ul>
458 <li>JVM.loadClass will now also initialize the loaded class and ignore any occurring LinkageError.</li>
459 <li>JIRA:XSTR-596: SubjectConverter will be no longer registered if initialization of javax.security.auth.Subject
460 fails.</li>
461 <li>JIRA:XSTR-683: Inheritance of implicit collections, arrays or maps is dependent on declaration sequence.</li>
462 <li>Inherited implicit collections, arrays or maps can be overwritten with own definition in subtype.</li>
463 <li>JIRA:XSTR-688: Cannot omit XML elements from derived fields.</li>
464 <li>JIRA:XSTR-696: Ill-formed JSON generated, because JSON writer is fed with type of declaring field instead of
465 the real object's type.</li>
466 <li>JIRA:XSTR-685: Deserialization from file or URL keeps stream open.</li>
467 <li>JIRA:XSTR-684: XML 1.0 character validation fails for characters from 0x10 to 0x1f.</li>
468 <li>JavaBeanConverter supports now instantiation for a specific type and can therefore be used in
469 @XStreamConverter annotation.</li>
470 <li>SerializableConverter is broken if the serialized type is the default implementation.</li>
471 <li>Method marshalUnserializableParent of SerializableConverter is protected now to skip the default mechanism in
472 a derived converter that uses the default constructor to create the original type (as an alternative for
473 JIRA:XSTR-695).</li>
474 <li>FieldDictionary may call sort of FieldKeySorter implementation with wrong type as key.</li>
475 <li>Sometimes DependencyInjectionFactory tries to instantiate objects with mismatching constructor arguments.</li>
476 <li>HSQLDB has to be a test dependency only for XStream's Hibernate module.</li>
477 </ul>
478
479 <h1 id="1.4.2">1.4.2</h1>
480
481 <p>Released November 3, 2011.</p>
482
483 <h2>Major changes</h2>
484
485 <ul>
486 <li>XStream libraries can be used now directly in Android, therefore support of Java 1.4.2 has been stopped with
487 the delivery. Anyone who needs a version for Java 1.4.2 can build it easily from source, this build is still
488 supported and part of CI.</li>
489 <li>JIRA:XSTR-675: New extended HierarchicalStreamReader interface with peekNextChild method. All XStream readers
490 implement the new interface (by Nikita Levyankov).</li>
491 <li>JIRA:XSTR-673: Collections.EMPTY_LIST, Collections.EMPTY_SET and Collections.EMPTY_MAP supported with own
492 alias and defined as immutable.</li>
493 <li>JIRA:XSTR-631: Collections.singletonList(), Collections.singletonSet() and Collections.singletonMap()
494 supported with own alias and own converters.</li>
495 <li>JIRA:XSTR-406 + JIRA:XSTR-663: Support additional parameters for XStreamConverter annotation (e.g. to declare
496 a ToAttributedValueConverter).</li>
497 </ul>
498
499 <h2>Minor changes</h2>
500
501 <ul>
502 <li>WstxDriver did not trigger Woodstox, but BEA StAX implementation.</li>
503 <li>JIRA:XSTR-260: PrettyPrintWriter does not handle tab and new line characters in attributes.</li>
504 <li>JIRA:XSTR-667: Cannot serialize empty list with JsonHierarchicalStreamDriver.</li>
505 <li>JIRA:XSTR-661: TreeMarshaller.CircularReference is not a ConversionException.</li>
506 <li>JIRA:XSTR-562: StAX: Namespace attribute is not written in non-repairing mode for second sibling.</li>
507 <li>JIRA:XSTR-664: ClassCastException in HibernatePersistentSortedSetConverter and
508 HibernatePersistentSortedMapConverter.</li>
509 <li>JIRA:XSTR-674: Recreate binary compatibility with 1.3.x series for method
510 CustomObjectInputStream.getInstance(...).</li>
511 <li>JIRA:XSTR-671: CannotResolveClassException should accept cause.</li>
512 <li>JIRA:XSTR-672: Collections.EMPTY_LIST, Collections.EMPTY_SET and Collections.EMPTY_MAP used for in implicit
513 collection should not throw ReferencedImplicitElementException.</li>
514 <li>JIRA:XSTR-676: Introduce MissingFieldException thrown at deserialization time indicating a missing field or
515 property (by Nikita Levyankov).</li>
516 <li>Add length limit for cached strings in StringConverter, 38 characters by default.</li>
517 <li>The JsonHierarchicalStreamDriver and the JsonWriter did not support the inherited NameCoder instance.</li>
518 <li>Add BinaryStreamDriver.</li>
519 <li>NPE in XppDomComparator.</li>
520 <li>Dom4JXmlWriter fails to flush the underlying writer.</li>
521 <li>Known control characters are not encoded with JsonWriter as proposed at json.org.</li>
522 <li>Detect duplicate property processing in JavaBeanConverter and throw DuplicatePropertyException instead of
523 clobbering silently.</li>
524 <li>Allow access to Mapper and JavaBeanProvider in derived instances of JavaBeanConverter.</li>
525 <li>DependencyInjectionFactory failed to create instance when a matching constructor was found, but a default
526 constructor was also present.</li>
527 </ul>
528
529 <h2>API changes</h2>
530
531 <ul>
532 <li>Added interface c.t.x.io.ExtendedHierarchicalStreamReader extending c.t.x.io.HierarchicalStreamReader. All
533 implementations of c.t.x.io.HierarchicalStreamReader will implement also the extended interface.</li>
534 <li>Added c.t.x.converters.reflection.MissingFieldException derived from
535 c.t.x.converters.reflection.ObjectAccessException and used instead when the unmarshalling process should write a
536 field or property that is missing and does not exist.</li>
537 <li>Added methods c.t.x.io.path.PathTracker.peekElement(), c.t.x.io.path.PathTracker.peekElement(int), and
538 c.t.x.io.path.PathTracker.depth().</li>
539 <li>Deprecated method c.t.x.core.ReferencingMarshallingContext.currentPath(). Wrong approach.</li>
540 </ul>
541
542 <h1 id="1.4.1">1.4.1</h1>
543
544 <p>Released August 11, 2011.</p>
545
546 <h2>Major changes</h2>
547
548 <ul>
549 <li>JIRA:XSTR-659: Use again Xpp3 as default parser, now with additional XmlPullParser API as regular dependency
550 for the XPP factory. Only standard kXML2 package contains the XPP factory, but not the minimal kXML2 version.</li>
551 </ul>
552
553 <h2>Minor changes</h2>
554
555 <ul>
556 <li>Add utility class c.t.x.io.xml.xppdom.XppFactory and a path tracking comparator for XppDom.</li>
557 </ul>
558
559 <h1 id="1.4">1.4</h1>
560
561 <p>Released August 6, 2011.</p>
562
563 <h2>Major changes</h2>
564
565 <ul>
566 <li>Java 7 is detected and supported.</li>
567 <li>JIRA:XSTR-542: The XppDriver uses now the official XmlPullParser API to locate an available parser using the
568 XmlPullParserFactory. This allows the usage of XPP technology with XStream in Android.</li>
569 <li>Additional explicit XPP drivers for the Xpp3 and kXML2 implementations.</li>
570 <li>Additional explicit XPP DOM drivers for the Xpp3 and kXML2 implementations.</li>
571 <li>kXML2 is now the preferred parser implementation, Xpp3 is optional.</li>
572 <li>Additional explicit StAX drivers for Woodstox, BEA StAX and SJSXP of the JDK 6 implementations.</li>
573 <li>JDK 1.3 is no longer officially supported.</li>
574 <li>JIRA:XSTR-377+JIRA:XSTR-226: New artifact xstream-hibernate with converters and mapper to process Hibernate
575 object graphs (by Costin Leau, Konstantin Pribluda and in special Jaime Metcher).</li>
576 <li>New NameCoder interface and implementations to support a generic name translation between names from the
577 object graph and a target format. The new XmlFriendlyNameCoder replaces the XmlFriendlyReplacer used for XML only.</li>
578 <li>JIRA:XSTR-553: Support annotations in Android.</li>
579 <li>JIRA:XSTR-556: DateConverter uses format with 3-letter time zones that are ambiguous. Therefore it will now
580 always use UTC to write dates. Unmarshalled dates are not affected as long as they contain a time zone.</li>
581 <li>The type java.lang.reflect.Field is now handled by an own converter, that can still read the old format.</li>
582 <li>JIRA:XSTR-490: Provide path in Converter for contexts that track the path.</li>
583 <li>JIRA:XSTR-592+JIRA:XSTR-579: OmitField respected at deserialization time even for existing fields.</li>
584 <li>JIRA:XSTR-593: Direct support for java.net.URI instances (by Carlos Roman).</li>
585 <li>JIRA:XSTR-615+JIRA:XSTR-580: Dynamic proxies cannot be referenced recursively.</li>
586 <li>JIRA:XSTR-547: Wrong class loader used for Serializable types deserialized with an ObjectInputStream.</li>
587 <li>JIRA:XSTR-341: Support of implicit arrays.</li>
588 <li>JIRA:XSTR-306+JIRA:XSTR-406: Support of implicit maps.</li>
589 <li>JIRA:XSTR-344: New ToAttributedValueConverter to allow conversion of an element with string body and
590 attributes.</li>
591 <li>JIRA:XSTR-573: SortedSet added with TreeSet as the default implementation.</li>
592 <li>JIRA:XSTR-576: TreeMap and TreeSet no longer add an element without comparator (by Jason Greanya), solves
593 also invalid format with JSON for such objects (JIRA:XSTR-640).</li>
594 </ul>
595
596 <h2>Minor changes</h2>
597
598 <ul>
599 <li>JIRA:XSTR-612: Improve extensibility of c.t.x.javabean.* package by reintroducing a PropertyDictionary with
600 the additional interface PropertySorter.</li>
601 <li>JIRA:XSTR-591: EnumSingleValueConverter did use toString() instead of name() to create the String
602 representation of an enum value.</li>
603 <li>JIRA:XSTR-618: Add Oracle as vendor used for recent JRockit versions and former Sun JDK.</li>
604 <li>JIRA:XSTR-656: DomReader and Dom4JReader do not escape attribute names retrieving their values.</li>
605 <li>JIRA:XSTR-604: StringConverter's cache may cause an OutOfMemoryException.</li>
606 <li>JIRA:XSTR-577: Skip UTF-8 BOM in XmlHeaderAwareReader.</li>
607 <li>The XppReader no longer uses a BufferedReader.</li>
608 <li>JIRA:XSTR-543: Better deserialization support of the defined-in system attribute in combination with field
609 aliases.</li>
610 <li>JIRA:XSTR-551: Deprecated XStream.InitializationException still thrown instead of InitializationException.</li>
611 <li>JIRA:XSTR-655: JsonWriter generates invalid JSON for Externalizable types.</li>
612 <li>JIRA:XSTR-540: Support Jettison-based configuration of JettisonMappedXmlDriver (by Doug Daniels).</li>
613 <li>JIRA:XSTR-633: JettisonMappedXmlDriver escaped property names according escape rules for XML tag names.</li>
614 <li>JIRA:XSTR-625: Optionally ignore XStream's hints for Jettison to generate JSON arrays (by Dejan Bosanac).</li>
615 <li>JIRA:XSTR-605: Upgrade to Jettison 1.2 (for Java 5 or higher).</li>
616 <li>New JsonWriter.EXPLICIT_MODE generating JSON that enforces property sequence.</li>
617 <li>JIRA:XSTR-552: Improve performance of ReflectionProvider (by Keith Kowalczykowski).</li>
618 <li>JIRA:XSTR-559: Improve performance of Sun14ReflectionProvider (by Keith Kowalczykowski).</li>
619 <li>JIRA:XSTR-564: Improve performance of AnnotationMapper (by Keith Kowalczykowski).</li>
620 <li>JIRA:XSTR-563: Use ReferenceQueue for cleaning-up WeakReferences in ObjectIdDictionary (by Keith
621 Kowalczykowski).</li>
622 <li>JIRA:XSTR-646: Cache of Sun14ReflectionProvider consumes more PermGen space than necessary.</li>
623 <li>JIRA:XSTR-636: Ineffective cache in FieldDictionary using WeakHashMap with WeakReference values.</li>
624 <li>Ineffective cache for SerializationMethodInvoker (related to JIRA:XSTR-636).</li>
625 <li>Introduction of Caching interface implemented by all types in XStream that create local caches that may have
626 to be flushed manually.</li>
627 <li>Avoid excessive creation of AbstractPullReader.Event objects by using a pool.</li>
628 <li>Possibility to generate XPath expressions that select always a single node instead of a node list.</li>
629 <li>Cannot reference replaced object using ID references.</li>
630 <li>Implicit collection functionality will no longer use custom collection converters that may write tags that
631 are not recognized at deserialization time again.</li>
632 <li>JIRA:XSTR-654: Unmarshal fails when an implicit collection is defined and an element is named equal to the
633 field.</li>
634 <li>JIRA:XSTR-574: AbstractReferenceUnmarshaller cannot handle null values for references.</li>
635 <li>Improve exception output in case of a missing field.</li>
636 <li>JIRA:XSTR-555: StAX driver tests do not honor repairing mode.</li>
637 <li>JIRA:XSTR-570: The @XStreamConverter provides now also the current type as possible constructor argument.</li>
638 <li>JIRA:XSTR-629: Deserialization of Externalizable with non-accessible default constructor fails.</li>
639 <li>JIRA:XSTR-571: Cannot serialize synchronized RandomAccessList types.</li>
640 <li>JIRA:XSTR-583: BinaryDriver fails to handle Strings with more than 64K bytes.</li>
641 <li>JIRA:XSTR-639: Cannot omit field at deserialization if the field has a class attribute.</li>
642 <li>JIRA:XSTR-599: EncodedByteArrayConverter should implement SingleValueConverter.</li>
643 <li>JIRA:XSTR-584: Race condition in XmlFriendlyReplacer.</li>
644 <li>JIRA:XSTR-623: XmlFriendlyReplacer may write illegal name characters (by Michael Schnell).</li>
645 <li>The ConversionException hides information if its ErrorWriter contains the added key already.</li>
646 <li>JIRA:XSTR-598: Attribute &quot;defined-in&quot; was wrongly evaluated for other attributes.</li>
647 <li>JIRA:XSTR-650: Possible NullPointerException at initialization on platforms like Android that do not support
648 all types of the JDK.</li>
649 <li>JIRA:XSTR-652: Initialization of XStream fails if DurationConverter constructor throws a
650 javax.xml.datatype.DatatypeConfigurationException. Converter will no longer handle Duration types if no instance of
651 the internal DatatypeFactory can be created.</li>
652 <li>Constructor DocumentWriter(Element) forgets the provided element.</li>
653 <li>JIRA:XSTR-597: Optimize AbstractReflectionConverter.</li>
654 <li>Introduce Caching interface to flush the internal cache of specific components.</li>
655 <li>Support JIRA:XSTR-407 also for IBM JRE 1.6 and greater.</li>
656 <li>java.nio.charset.Charset's converter was added as immutable type instead of the type itself.</li>
657 <li>java.util.Currency added as immutable type.</li>
658 <li>Fix selection of same parameter types in DependencyInjectionFactory.</li>
659 <li>Deprecation of c.t.x.javabean.PropertyDictionary has been countermanded.</li>
660 </ul>
661
662 <h2>API changes</h2>
663
664 <ul>
665 <li>Any deprecated stuff of the 1.2.x releases has been removed.</li>
666 <li>Deprecated constructors of c.t.x.converters.reflection.SerializableConverter,
667 c.t.x.converters.reflection.ExternalizableConverter and c.t.x.converters.reflection.CGLIBEnhancedConverter; new
668 versions take an additional argument for class loader (as a result for JIRA:XSTR-547).</li>
669 <li>Deprecated constructors of c.t.x.io.xml.XppReader, new versions take an additional argument for the
670 XmlPullParser.</li>
671 <li>Deprecated c.t.x.io.xml.XppReader.createParser(), the XPP parser is now created by the driver.</li>
672 <li>Package c.t.x.io.xml.xppdom is now part of the official API.</li>
673 <li>c.t.x.io.xml.xppdom.Xpp3Dom and c.t.x.io.xmlxpp.dom.Xpp3DomBuilder have been deprecated. Functionality is
674 merged in c.t.x.io.xml.xppdom.XppDom.</li>
675 <li>Deprecated c.t.x.mapper.XStream11XmlFriendlyMapper and c.t.x.mapper.AbstractXmlFriendlyMapper.</li>
676 <li>Added interface c.t.x.core.ReferencingMarshallingContext which is implemented by all referencing marshallers.</li>
677 <li>Added interface c.t.x.io.naming.NameCoder and implementations.</li>
678 <li>Deprecated c.t.x.io.xml.XmlFriendlyReplacer, c.t.x.io.xml.XmlFriendlyReader and
679 c.t.x.io.xml.XmlFriendlyWriter.</li>
680 <li>Deprecated c.t.x.io.xml.AbstractXmlDriver, c.t.x.io.xml.AbstractXmlReader and c.t.x.io.xml.AbstractXmlWriter,
681 added c.t.x.io.AbstractDriver, c.t.x.io.AbstractReader and c.t.x.io.AbstractWriter instead.</li>
682 <li>Deprecated all constructors of Driver, Reader and Writer implementations that take a XmlFriendlyReplacer as
683 argument, added constructors taking a NameCoder instead.</li>
684 <li>Added interface com.thoughtworks.xstream.converters.ErrorReporter to allow other types to report also errors
685 (apart from a HierarchicalStreamReader). Any converter and the parent object of the currently deserialized element
686 may provide additional error information now.</li>
687 </ul>
688
689 <h1 id="1.3.1">1.3.1</h1>
690
691 <p>Released December 6, 2008.</p>
692
693 <p class="highlight">CGLIB support must be explicitly activated now. The decision has been made due to possible
694 problems using an own classloader and because of ongoing complaints about occurring exceptions in the
695 CGLIBEnhancedConverter at XStream initialization although they are caused by incompatible ASM versions on the user's
696 classpath (JIRA:XSTR-469, JIRA:XSTR-513 and JIRA:XSTR-518).</p>
697
698 <p class="highlight">XStream uses some attributes on its own. Until now it was possible to use
699 XStream.aliasAttribute to define a different name. This does still work but is deprecated for system attributes. Use
700 the new call XStream.aliasSystemAttribute for such an alias.</p>
701
702 <h2>Major changes</h2>
703
704 <ul>
705 <li>JIRA:XSTR-515: CGLIB support is no longer activated automatically and has to be <a
706 href="faq.html#Serialization_CGLIB">explicitly turned on</a>.
707 </li>
708 <li>JIRA:XSTR-448: Separated system attributes and user defined attributes for aliases.</li>
709 <li>JIRA:XSTR-55: Ability to alias a package name.</li>
710 <li>JIRA:XSTR-434: New JsonWriter instead of JsonHierarchicalStreamWriter with mode to strip root node of
711 generated JSON (by Paul Hammant).</li>
712 <li>Support for Diablo JDK on FreeBSD (by Reto Bachmann-Gm&uuml;r).</li>
713 <li>JIRA:XSTR-495: New PersistenceStrategy instead of StreamStrategy (based on the code and comments by Alexander
714 Radzin).</li>
715 </ul>
716
717 <h2>Minor changes</h2>
718
719 <ul>
720 <li>Support special Jettison functionality for JSON to detect collections or arrays with one element introduced
721 with Jettison 1.0.</li>
722 <li>JIRA:XSTR-493: Using attributes for fields with XML-unfriendly names results in NPE at deserialization.</li>
723 <li>JIRA:XSTR-497: Unsafe operation with WeakHashMap can raise a NPE in Sun14ReflectionProvider.</li>
724 <li>JIRA:XSTR-423: Support of CGLIB enhanced proxies with multiple callbacks if the proxy uses a factory (CGLIB
725 default).</li>
726 <li>JIRA:XSTR-536: XStream silently ignores unknown elements.</li>
727 <li>JIRA:XSTR-503: Omitted properties in JavaBeans are requested at serialization (by Kevin Conaway).</li>
728 <li>Fix possible memory leak in ObjectIdMap for JVMs that provide real distinct identity hash codes (happened on
729 amd64 system).</li>
730 <li>JIRA:XSTR-480: Aliasing of array types.</li>
731 <li>JIRA:XSTR-515: The SubjectConverter and DurationConverter are only registered if the converted class is part
732 of the JDK, otherwise they must be registered now explicitly.</li>
733 <li>JIRA:XSTR-504: XmlHeaderAwareReader fails with improper sized PushbackInputStream.</li>
734 <li>JIRA:XSTR-489: @XStreamConverter supports now also SingleValueConverter implementations.</li>
735 <li>JIRA:XSTR-481: @XStreamConverter and @XStreamAsAttribute can be used together (as a result of JIRA:XSTR-489).</li>
736 <li>JIRA:XSTR-519: New annotation @XStreamInclude to force annotation detection of included types (by Seven
737 Sparling).</li>
738 <li>JIRA:XSTR-469: Support custom converters for enum types.</li>
739 <li>JIRA:XSTR-502: ClassNotFoundException even if writeReplace returns proper object.</li>
740 <li>JIRA:XSTR-529: NullPointerException for null elements in implicit lists.</li>
741 <li>JIRA:XSTR-517: Miscellaneous performance improvements (by Tatu Saloranta).</li>
742 <li>JIRA:XSTR-525: JsonHierarchicalStreamDriver writes invalid JSON in case of system attribute.</li>
743 <li>JIRA:XSTR-535: Mode to allow plain values as result for JSON without root node.</li>
744 <li>JIRA:XSTR-531: Possibility to omit system attributes.</li>
745 <li>JIRA:XSTR-508: Fix marshalling error for nested serializable objects with own writeReplace/readResolve
746 methods.</li>
747 <li>JIRA:XSTR-507: Advanced ReferenceByIdMarshaller uses id of the current object if available.</li>
748 <li>JIRA:XSTR-485: Check reference for valid object when deserializing.</li>
749 <li>Fix classloader problem, Xpp3 parser cannot be loaded within a web application.</li>
750 <li>Dependencies have been updated to latest versions of JDOM, Jettison, Joda Time, and Woodstox. Note for Maven
751 builds that the <em>groupId</em> of JDOM has changed.
752 </li>
753 <li>Fix possible IndexOutOfBoundsException creating returning the message for a ConversionException.</li>
754 <li>JIRA:XSTR-495: StreamStrategy cannot handle key with value <em>null</em>.
755 </li>
756 </ul>
757
758 <h2>API changes</h2>
759
760 <ul>
761 <li>Deprecated c.t.x.io.json.JsonHierarchicalStreamWriter in favour of c.t.x.io.json.JsonWriter.</li>
762 <li>c.t.x.mapper.EnumMapper no longer derives from the c.t.x.mapper.AttributeMapper as it has been before version
763 1.3. Therefore the new constructor has been deprecated in favour of the old one.</li>
764 <li>c.t.x.mapper.Mapper.getConverterFromAttribute(Class, String) has been deprecated in favour of
765 c.t.x.mapper.Mapper.getConverterFromAttribute(Class, String, Class) taking the type as third argument that should be
766 handled by the converter.</li>
767 <li>c.t.x.core.ReferenceByIdMarshaller.IdGenerator.next() has now the current object as argument.</li>
768 <li>New c.t.x.persistence.PersistenceStrategy and c.t.x.persistence.FilePersistenceStrategy.</li>
769 <li>Deprecated c.t.x.persistence.StreamStrategy and c.t.x.persistence.FileStreamStrategy.</li>
770 </ul>
771
772 <h1 id="1.3">1.3</h1>
773
774 <p>Released February 27, 2008.</p>
775
776 <h2>Major changes</h2>
777
778 <ul>
779 <li>ReflectionConverter writes now the fields of the parent classes first.</li>
780 <li>Support for Converter definition at field level.</li>
781 <li>Refactoring of Annotation support, invent auto-detection mode.</li>
782 <li>Annotated converters are no longer detected automatically, all annotations are now handled in the same way.</li>
783 <li>JIRA:XSTR-334: XStream will deserialize directly from a file or URL. Some parser take advantage of these
784 objects to define a SystemId used to resolve further references in XML, schema or DTD. Appropriate createReader
785 methods have been added to c.t.x.io.HierarchicalStreamDriver.</li>
786 <li>JIRA:XSTR-261: All c.t.x.io.HierarchicalStreamDriver implementations respect now the encoding of an XML
787 header if read from an InputStream.</li>
788 <li>DomDriver does no longer use explicitly UTF-8 by default, DomReader will therefore respect the encoding
789 defined in the XML header or use native encoding</li>
790 <li>JIRA:XSTR-415: JavaBeanConverter uses now BeanIntrospection (by Hinse ter Schuur).</li>
791 <li>JIRA:XSTR-424: DateConverter uses now by default SimpleDateFormat instances in non-lenient mode.</li>
792 <li>JIRA:XSTR-386: SingleValueConverter that utilizes PropertyEditor implementations (by Jukka Lindstr&ouml;m).</li>
793 <li>JIRA:XSTR-427: Converter for javax.xml.datatype.Duration (by John Kristian).</li>
794 <li>JIRA:XSTR-305: Field alias inheritance (by David Blevins).</li>
795 <li>XStream failed to initialize in environments without AWT or SQL classes.</li>
796 <li>JIRA:XSTR-420: XPath of references are not XmlFriendly encoded.</li>
797 <li>JIRA:XSTR-473: String &quot;\0&quot; serialized as invalid XML, support compliant behaviour according XML
798 version.</li>
799 <li>JIRA:XSTR-431: Direct support of enhanced mode for SAP JVM (thanks to Norbert Kuck by SAP).</li>
800 <li>JIRA:XSTR-437: Static cache in annotation processing causes failing OSGi bundles.</li>
801 <li>JIRA:XSTR-279+JIRA:XSTR-335: Annotations are not inherited from parent class.</li>
802 <li>Fix StringConverter using a WeakHashMap with strong references in its value.</li>
803 <li>JIRA:XSTR-403: Attributes are no longer written with JSONHierarchicalStreamDriver if current object is a
804 collection.</li>
805 <li>JIRA:XSTR-456: New LookAndFeelConverter handling LookAndFeel implementations with reflection.</li>
806 <li>JIRA:XSTR-462: CachingMapper keeps direct class references.</li>
807 <li>JIRA:XSTR-411: JsonHierarchicalStreamDriver does not escape characters according RFC 4627.</li>
808 <li>JsonHierarchicalStreamDriver writes wrong brackets around complex Java types with a single value.</li>
809 <li>JsonHierarchicalStreamDriver writes attribute names with a leading '@'.</li>
810 <li>JsonHierarchicalStreamDriver supports Map implementations.</li>
811 </ul>
812
813 <h2>Minor changes</h2>
814
815 <ul>
816 <li>Added converter for java.lang.StringBuilder instances.</li>
817 <li>Added converter for java.util.UUID instances.</li>
818 <li>JIRA:XSTR-430: Fields written as attributes could not be omitted.</li>
819 <li>JIRA:XSTR-407: Comparator might access uninitialized elements for TreeSet and TreeMap. A deserialized
820 Comparator is no longer called, the converters expect the elements now in a sorted order.</li>
821 <li>JIRA:XSTR-404, @XStreamImplicit() for ArrayList&lt;ArrayList&lt;Type&gt;&gt; throws ClassCastException.</li>
822 <li>@XStreamContainedType() for ArrayList&lt;ArrayList&lt;Type&gt;&gt; throws ClassCastException.</li>
823 <li>XStreamer did not persist a FieldKeySorter instance.</li>
824 <li>JIRA:XSTR-241: JavaBeanConverter now supports customized BeanProvider.</li>
825 <li>JIRA:XSTR-280: JavaBeanConverter now supports aliasField and omitField (by Hinse ter Schuur).</li>
826 <li>JIRA:XSTR-280: SerializationConverter now supports aliasField and omitField.</li>
827 <li>JIRA:XSTR-429: XmlFriendlyReplacer support for SaxWriter and TraxSource (by Adrian Wilkens).</li>
828 <li>JIRA:XSTR-421: Characters cannot be written as attribute.</li>
829 <li>JIRA:XSTR-426: java.swt.KeyStroke not properly serialized because of a character undefined in unicode.</li>
830 <li>JIRA:XSTR-352: Strings with arbitrary ISO control characters are not properly serialized.</li>
831 <li>JIRA:XSTR-428: An attribute named like a transient field did abort deserialization of following fields.</li>
832 <li>JIRA:XSTR-443: XStream.createObjectOutputStream does not use the given driver to create the
833 HierarchicalStreamWriter.</li>
834 <li>JIRA:XSTR-440: Implicit collections can be declared for fields that are not of Collection type.</li>
835 <li>JIRA:XSTR-446: Handle all primitives and their boxed counterpart for JsonHierarchicalStreamDriver.</li>
836 <li>JIRA:XSTR-447: Fix deserialization of Array class types in JDK 6 (see JDK bug 6500212).</li>
837 <li>JIRA:XSTR-450: @XStreamAlias is ignored if attributes should be used for the field type.</li>
838 <li>JIRA:XSTR-418: Inherited @XStreamAlias is ignored if field should be rendered as attribute.</li>
839 <li>JIRA:XSTR-393: Annotation processing is not consistent.</li>
840 <li>JIRA:XSTR-412: @XStreamImplicit throws NPE for untyped collections.</li>
841 <li>JIRA:XSTR-463: Cannot provide own default Mapper chain.</li>
842 <li>JIRA:XSTR-464: Cannot provide a ClassLoader that is used in all cases.</li>
843 <li>JIRA:XSTR-394: Allow enums as attributes.</li>
844 <li>JIRA:XSTR-413: Support @XStreamAsAttribute for enums.</li>
845 <li>JIRA:XSTR-478: Cannot specify default implementation for polymorphic enum.</li>
846 <li>JIRA:XSTR-419: Treat enums as immutable types.</li>
847 <li>Update annotation tutorial, explain limitations of auto-detection mode.</li>
848 <li>Added copyright notices to all files.</li>
849 <li>StaxWriter.flush did close Stax' XMLStreamWriter instead of flushing it.</li>
850 <li>JIRA:XSTR-471: XStream POMs do no longer declare a repository at all.</li>
851 <li>Calendar object could not be rendered with JSONHierarchicalStreamDriver.</li>
852 <li>JIRA:XSTR-476: Properties can be sorted by key.</li>
853 <li>XStream.createObjectInputStream and XStream.createObjectOutputStream overloaded to support a binary
854 InputStream or OutputStream.</li>
855 <li>JIRA:XSTR-470: Allow transient fields to be optionally deserialized.</li>
856 </ul>
857
858 <h2>API changes</h2>
859
860 <ul>
861 <li>c.t.x.annotation.Annotations, c.t.x.annotation.AnnotationReflectionConverter and
862 c.t.x.annotation.AnnotationProvider deprecated. Functionality is integrated in new c.t.x.mapper.AnnotationMapper and
863 accessible with new methods c.t.x.XStream.processAnnotations().</li>
864 <li>New auto-detection mode for annotations, that can be turned on with c.t.x.XStream.autodetectAnnotations()</li>
865 <li>c.t.x.annotation.@XStreamContainedType deprecated, the behaviour is now always active and the annotation
866 therefore superfluous.</li>
867 <li>Due to JIRA:XSTR-421 null characters are no longer written as tag with an attribute (&lt;char
868 null=&quot;true&quot;/&gt;), but as empty tag. The old representation is still supported at deserialization.</li>
869 <li>Characters that are not defined in unicode or ISO control characters (expect TAB and LF) are written as
870 numerical entity now.</li>
871 <li>XPath references are now also XML-friendly encoded to match the path exactly. Unencoded references will
872 normally work anyway, but in special cases the exact behaviour of XStream 1.2.x might be necessary. See acceptance
873 tests for XStream 1.2.x compatibility.</li>
874 <li>c.t.x.core.BaseException deprecated in favour of c.t.x.XStreamException as base exception for all exceptions
875 XStream throws.</li>
876 <li>c.t.x.XStream.InitializerException deprecated in favour of c.t.x.InitializerException.</li>
877 <li>New methods get() and keys() in interface c.t.x.converter.ErrorWriter.</li>
878 <li>c.t.x.mapper.XmlFriendlyMapper deprecated, technology is replaced since version 1.2 by
879 c.t.x.io.xml.XmlFriendlyReplacer as part of the different XmlWriter implementations.</li>
880 <li>c.t.x.mapper.Mapper.aliasForAttribute() and c.t.x.mapper.Mapper.attributeForAlias() deprecated, since it
881 provided in reality the combined functionality of c.t.x.mapper.Mapper.serializedMember()/realMember() and
882 c.t.x.mapper.Mapper.getConverterFromItemType().</li>
883 <li>c.t.x.XStream(ReflectionProvider, Mapper, HierarchicalStreamDriver) deprecated, in favour of
884 c.t.x.XStream(ReflectionProvider, HierarchicalStreamDriver, Mapper, ClassLoader).</li>
885 <li>New interface c.t.x.converter.ConverterRegistry to express explicit functionality managing the converters.</li>
886 <li>c.t.x.core.DefaultConverterLookup no longer uses a c.t.x.mapper.Mapper. Therefore the old constructor has
887 been deprecated in favour of a default constructor.</li>
888 <li>Overloaded methods of c.t.x.mapper.Mapper.getConverterFromItemType and
889 c.t.x.mapper.Mapper.getConverterFromAttribute have been deprecated. Only one version has been kept, the
890 implementation can handle all cases now at once and therefore multiple calls to the mapper chain are avoided.</li>
891 <li>c.t.x.mapper.EnumMapper derives now from the c.t.x.mapper.AttributeMapper to support enums as attributes.
892 Therefore the old constructor has been deprecated in favour of one taking an additional
893 c.t.x.converters.ConverterLookup that has to be passed to the new parent.</li>
894 </ul>
895
896 <p class="highlight">Note, to support a representation of null values in some way, it is absolutely necessary that
897 each converter can handle a null value in its marshalling methods. If you have implemented your own custom converters,
898 try to handle such a case also to prevent incompatibilities in case XStream will provide such values with its next
899 major version.</p>
900
901 <h1 id="1.2.2">Version 1.2.2</h1>
902
903 <p>Released May 24, 2007.</p>
904
905 <p class="hightlight">Note, that next version of XStream will behave slightly different by default. XStream emits
906 all fields in declaration order like Java serialization. But in contrast to Java it will omit the fields of parent
907 classes last while Java serialization emits them first. This makes it difficult to match a given XML schema that
908 defined inherited types or leads sometimes to obscure initialization problems. However, XStream itself will not be
909 affected by the changed order of elements in the XML, any deserialization of current XML representations will work
910 fine. Anyway we will provide with XStream 1.3 a FieldKeySorter implementation that mimics the old behaviour. In the
911 meanwhile you can enforce the new field sorting by installing the NaturalFieldKeySorter.</p>
912
913 <h2>Major changes</h2>
914
915 <ul>
916 <li>JIRA:XSTR-391, Support for writing (and reading) JSON by the new JettisonMappedXmlDriver (by Dejan Bosanac).</li>
917 <li>New FieldKeySorter interface allows a custom sort order of the XML elements.</li>
918 <li>JIRA:XSTR-68 and JIRA:XSTR-210, OmitField is now respected at deserialization to ignore removed fields.</li>
919 </ul>
920
921 <h2>Minor changes</h2>
922
923 <ul>
924 <li>JIRA:XSTR-387, Fix aliasing of inherited fields.</li>
925 <li>JIRA:XSTR-395, Fix StringConverter allocating PermGen space.</li>
926 <li>JIRA:XSTR-368, @XStreamConverter converters should be cached inside the AnnotationReflectionConverter.</li>
927 <li>JIRA:XSTR-392, @XStreamOmitField can be used to omit fields from the resulting XML (contributed by Chung-Onn
928 Cheong).</li>
929 <li>JIRA:XSTR-371, Fix JSONWriter that omits a closing bracket for for fields with null value.</li>
930 <li>JIRA:XSTR-398, DomDriver ignores given XmlFriendlyReplacer.</li>
931 <li>JIRA:XSTR-370, Buildable with JDK 6, fix FontConverter for JDK 6.</li>
932 <li>JIRA:XSTR-382, Support hex and octal number values.</li>
933 <li>DateConverter did not respect change in TimeZone after first usage.</li>
934 <li>JIRA:XSTR-375, Support for aliasing native types.</li>
935 <li>JIRA:XSTR-243 again, XML elements for transient fields are now ignored completely at deserialization.</li>
936 <li>Release unused object references to keep memory print low.</li>
937 <li>Support for AWT and SQL is now optional: XStream now works on embedded virtual machines lacking such APIs (by
938 Nicolas Gros d'Aillon).</li>
939 <li>Support raw bytes read from the ObjectInputStream.</li>
940 <li>JIRA:XSTR-373, Support for Hitachi JVM (tested by Yuji Yamano).</li>
941 <li>JIRA:XSTR-378 and JIRA:XSTR-379, Fix TextAttributeConverter and EnumSetConverter failing on Apache Harmony.</li>
942 <li>JIRA:XSTR-363, Support of native field order i.e. fields are processed in declaration order base classes
943 first.</li>
944 <li>JIRA:XSTR-320, Static field in child may hide non-static field in parent.</li>
945 </ul>
946
947 <h2>API changes</h2>
948
949 <ul>
950 <li>JIRA:XSTR-365, Multiple implicit collections with annotations. Deprecated @XStreamImclicitCollection in
951 favour of @XStreamImplicit declared at field level.</li>
952 </ul>
953
954 <h1 id="1.2.1">Version 1.2.1</h1>
955
956 <p>Released November 11, 2006.</p>
957
958 <h2>Major changes</h2>
959
960 <ul>
961 <li>Introduced DocumentWriter interface and generalized functionality for all writer implementations creating a
962 DOM structure (DOM4J, DOM, JDom, Xom, Xpp3Dom).</li>
963 <li>Refactored build system to use Maven 2. Ant still supported on XStream Core.</li>
964 <li>Created separate XStream Benchmark module</li>
965 </ul>
966
967 <h2>Minor changes</h2>
968
969 <ul>
970 <li>JIRA:XSTR-346, XStream.getClassMapper() does not return a ClassMapper for the current Mapper.</li>
971 <li>Fix problem with fields containing a double underscore.</li>
972 <li>JIRA:XSTR-345, Dom4JWriter adds up attributes.</li>
973 <li>JIRA:XSTR-336, XStream fails to reference an implicit element.</li>
974 <li>JIRA:XSTR-337, Annotation cycle bug.</li>
975 <li>Fix packaging error for the resulting jar building with Maven2.</li>
976 <li>JIRA:XSTR-339, NPE for attribute null values.</li>
977 <li>JIRA:XSTR-338, NPE in JSON writer for converters using non-extended HierarchicalStreamWriter.</li>
978 <li>JIRA:XSTR-357, Fix escaping of values in JSON writer.</li>
979 <li>JIRA:XSTR-356, Fix unmarshaling error for fields containing proxies.</li>
980 <li>JIRA:XSTR-349, Fix backward compatibility of Dom4jWriter.</li>
981 <li>JIRA:XSTR-309, More versatile boolean conversion options (contributed by David Blevins).</li>
982 <li>Add XStream.getReflectionProvider() to retrieve ReflectionProvider in use.</li>
983 <li>JIRA:XSTR-358, @XStreamConverter annotation does not call converter constructor.</li>
984 <li>Website generated using <a href="http://xsite.codehaus.org">XSite</a></li>
985 </ul>
986
987 <h2>API changes</h2>
988
989 <ul>
990 <li>Deprecate JDomWriter.getResult() in favour of DocumentWriter.getTopLevelNodes().</li>
991 <li>Deprecate ThreadSafeSimpleDateFormat, since this is an internal helper and not part of XStream API.</li>
992 </ul>
993
994 <h1 id="1.2">Version 1.2</h1>
995
996 <p>Released August 18, 2006.</p>
997
998 <h2>Major changes</h2>
999
1000 <ul>
1001 <li>JIRA:XSTR-269, Using attributes for fields (contributed by Paul Hammant and Ian Cartwright).</li>
1002 <li>Aliasing of arbitrary attributes.</li>
1003 <li>JIRA:XSTR-50, XStream can now serialize another XStream instance.</li>
1004 <li>JIRA:XSTR-227, XStream has now the XStreamer, that serializes an object together with its XStream instance.</li>
1005 <li>JIRA:XSTR-278, AnnotationConverter for fields (contributed by Guilherme Silveira).</li>
1006 <li>JIRA:XSTR-256, PureJavaReflectionProvider supports now final fields starting with JDK 1.5</li>
1007 <li>JIRA:XSTR-258, Any Collection type can now be declared implicit, the default implementation will be respected
1008 for unmarshaling.</li>
1009 <li>JIRA:XSTR-88, XStream can now write all references as absolute XPath expression.</li>
1010 <li>JIRA:XSTR-62 and JIRA:XSTR-211, New SingeValueConverter allows light weight converters if the value can be
1011 represented by a unique string.</li>
1012 <li>Aliasing of classes of a specific type.</li>
1013 <li>JIRA:XSTR-239, Support for certain types of proxies generated with the CGLIB Enhancer.</li>
1014 <li>JIRA:XSTR-90 and JIRA:XSTR-311, Support for BEA JRockit starting with R25.1.0 (contributed by Henrik
1015 St&aring;hl of BEA).</li>
1016 </ul>
1017
1018 <h2>Technology preview</h2>
1019
1020 <ul>
1021 <li>Experimental binary reader and writer.</li>
1022 <li>Experimental HierarichicalStreamCopier allows streams to be copied from one format to another without the
1023 overhead of serialization.</li>
1024 <li>Experimental JSON support allows streams to be copied from one format to another without the overhead of
1025 serialization (contributed by Paul Hammant).</li>
1026 </ul>
1027
1028 <h2>Minor changes</h2>
1029
1030 <ul>
1031 <li>JIRA:XSTR-266, XStream fails to serialize elements of a unserializable class, that is a base class of a
1032 derived class</li>
1033 <li>JIRA:XSTR-236, Priority constants for converter registration are now public</li>
1034 <li>JIRA:XSTR-215, XStream writes now fields in declaration order even for JVMs reporting them in reverse order
1035 like IBM JDK.</li>
1036 <li>JIRA:XSTR-276 and JIRA:XSTR-283, XStream does no longer attempt to create references to implicit element.</li>
1037 <li>JIRA:XSTR-244, Closing a Writer can now be done twice, but any write attempt will later on fail.</li>
1038 <li>JIRA:XSTR-243, Transient fields were unmarshalled from XML.</li>
1039 <li>JIRA:XSTR-250, Providing a mapper to the XStream constructor will no longer result in a NPE.</li>
1040 <li>JIRA:XSTR-281, After registering a new converter, the internal converter cache is now cleared.</li>
1041 <li>JIRA:XSTR-284, XStream checks the object returned by a converter for compatibility.</li>
1042 <li>XStream no longer fails serializing a Throwable without cause when no references shall be written.</li>
1043 <li>Converter for java.awt.font.TextAttribute.</li>
1044 <li>Converter for java.nio.charset.Charset.</li>
1045 <li>JIRA:XSTR-286, XStream detects impossible self serialization and throws now an appropriate
1046 ConversionException.</li>
1047 <li>JIRA:XSTR-291, XomDriver implementation added.</li>
1048 <li>JIRA:XSTR-299, Fix for implicit collections with items using the same name as the field name of the
1049 underlying collection.</li>
1050 <li>JIRA:XSTR-245, Broken XML with custom serialization in certain cases (patch contributed by Cyrille Le Clerc).</li>
1051 <li>JIRA:XSTR-304, Bad handling of repairing namespace flag for StaxDriver (patch contributed by John Kristian).</li>
1052 </ul>
1053
1054 <h2>API changes</h2>
1055
1056 <ul>
1057 <li>JIRA:XSTR-252, Refactored support for XML friendly character mapping.</li>
1058 <li>JIRA:XSTR-69, Refactored ReflectionConverter allows simpler subclassing.</li>
1059 <li>Unmarshalling context has now an overloaded version of the method convertAnother to provide the Converter
1060 directly.</li>
1061 <li>Deprecate ClassMapper for Mapper. All methods with a ClassMapper parameter have now a duplicate taking only a
1062 Mapper. The variant with the ClassMapper is deprecated.</li>
1063 <li>Deprecate c.t.x.alias.CannotResolveClassException for c.t.x.mapper.CannotResolveClassException.</li>
1064 <li>Deprecate NameMapper (was not used within XStream anymore anyway).</li>
1065 <li>Deprecate constructor of DefaultMapper taking an alternative name for the class attribute. Use the
1066 aliasAttribute method.</li>
1067 <li>Deprecate attributeForImplementationClass, attributeForClassDefiningField, attributeForReadResolveField, and
1068 attributeForEnumType in favour of the generalized aliasForAttribute in the Mapper interface.</li>
1069 <li>Removed all deprecated stuff from 1.1.x and 1.0.x</li>
1070 <li>JIRA:XSTR-211, A lot of existing (basic) Converters have been refactored to use the new SingleValueConverter
1071 interface.</li>
1072 <li>Dom4JWriter uses now a DocumentFactory and a XMLWriter as constructor arguments.</li>
1073 </ul>
1074
1075 <h1 id="1.1.3">Version 1.1.3</h1>
1076
1077 <p>Released January 13, 2006.</p>
1078
1079 <h2>Major changes</h2>
1080
1081 <ul>
1082 <li>Added XStream.toXML(OutputStream) and XStream.fromXML(InputStream).</li>
1083 <li>Ability to prevent fields from being serialized by calling XStream.omitField() or by implementing
1084 Mapper.shouldSerializeMember().</li>
1085 <li>Added Converter for Enum, EnumMap and EnumSet</li>
1086 <li>JIRA:XSTR-186, Added BeanConverter (contributed by Andrea Aime)</li>
1087 <li>JIRA:XSTR-246, Added ISO8601SqlTimestampConverter (contributed by Cheong, Chung-Onn)</li>
1088 <li>Added ISO8601GregorianCaledarConverter</li>
1089 <li>JIRA:XSTR-215, Fixed support for IBM JVM (contributed by Gabor Liptak)</li>
1090 <li>Enhanced mode support for Blackdown JDK</li>
1091 <li>JIRA:XSTR-265, support for javax.security.auth.Subject</li>
1092 <li>JIRA:XSTR-233, support for Integer[] arrays</li>
1093 </ul>
1094
1095 <h2>Minor changes</h2>
1096
1097 <ul>
1098 <li>Remove unnecessary PrintWriter wrapper in default writers (pointed out by Mathieu Champlon)</li>
1099 <li>Bugfix: EnumSet converter can now deal with empty sets (contributed by Baba Buehler)</li>
1100 <li>Update ISO8601DateConverter to use Joda 1.0</li>
1101 <li>JIRA:XSTR-242, GregorianCalenderConverter saves now the timezone</li>
1102 <li>JIRA:XSTR-247, ISO8601DateConverter now independent on timezone</li>
1103 <li>JIRA:XSTR-263, Circular references with Externalizable objects fail</li>
1104 </ul>
1105
1106 <h2>API changes</h2>
1107
1108 <ul>
1109 <li>None.</li>
1110 </ul>
1111
1112 <h1 id="1.1.2">Version 1.1.2</h1>
1113
1114 <p>Released April 30, 2005. Most popular feature requests implemented. Java 5 Enum support. Serialization of
1115 JavaBeans using accessors. Aliasing of fields. StAX integration, with namespaces. Improved support on JDK 1.3 and IBM
1116 JDK.</p>
1117
1118 <h2>Major changes</h2>
1119
1120 <ul>
1121 <li>JIRA:XSTR-186, Option to serialize JavaBeans using public accessors, rather than private fields (contributed
1122 by Andrea Aime).</li>
10061123 <li>Ability to alias fields as well as classes, using XStream.addFieldAlias().</li>
10071124 <li>JIRA:XSTR-70, JIRA:XSTR-204 Support for JDK 5 enums (contributed by Eric Snell and Bryan Coleman).</li>
10081125 <li>JIRA:XSTR-206 Clean representation of JDK 5 EnumMap and EnumSet.</li>
10091126 <li>XStream can now be built using JDK 1.3 (previously it required JDK 1.4 to compile, but 1.3 to run).</li>
1010 <li>JIRA:XSTR-215, Enhanced mode is now supported on the IBM 1.4 JDK.</li>
1011 <li>The default HierarchicalStreamWriter implementation is supplied by the HierarichicalStreamDriver (as well as the reader).</li>
1012 </ul>
1013
1014 <h2>Minor changes</h2>
1015
1016 <ul>
1017 <li>JIRA:XSTR-104 HierarchicalStreamReader now exposes all available attributes to the Converter implementations (contributed by Trygve Laugstol).</li>
1018 <li>Bugfix: Externalizable deserialization supported for objects not at the root of tree.</li>
1019 <li>JavaMethodConverter handles non public methods/constructors (contributed by Kevin Ring).</li>
1020 <li>PropertiesConverter also serializes default properties, if present (contributed by Kevin Ring).</li>
1021 <li>Bugfix: In some cases, XppReader and StaxReader would get confused when calling hasMoreChildren() and getValue() on the same node.</li>
1022 <li>JIRA:XSTR-217, ISO8601DateConverter now requires joda-time-1.2.1</li>
1023 <li>PrettyPrintWriter and CompactWriter may have their text/attribute escaping rules customized by overriding writeText() and writeAttributeValue().</li>
1024 </ul>
1025
1026 <h2>API changes</h2>
1027
1028 <ul>
1029 <li>HierarchicalStreamDriver implementations now require a createWriter() method. The simplest implementation is to return a new PrettyPrintWriter.</li>
1030 <li>Introduced ReaderWrapper/WriterWrapper classes to make it easier to wrap (decorate) HierarchicalStreamReader/Writer instances.</li>
1031 </ul>
1032
1033 <h1 id="1.1.1">Version 1.1.1</h1>
1034
1035 <p>Released March 7, 2005. Mostly bugfixes and minor feature enhancements.</p>
1036
1037 <h2>Major changes</h2>
1038
1039 <ul>
1040 <li>Converters can be registered with a priority, allowing more <i>generic</i> filters to handle classes that don't have more specific converters.</li>
1041 <li>Converters can now access underlying HierarchicalStreamReader/Writer implementations to make implementation specific calls.</li>
1127 <li>JIRA:XSTR-215, Enhanced mode is now supported on the IBM 1.4 JDK.</li>
1128 <li>The default HierarchicalStreamWriter implementation is supplied by the HierarichicalStreamDriver (as well as
1129 the reader).</li>
1130 </ul>
1131
1132 <h2>Minor changes</h2>
1133
1134 <ul>
1135 <li>JIRA:XSTR-104 HierarchicalStreamReader now exposes all available attributes to the Converter implementations
1136 (contributed by Trygve Laugstol).</li>
1137 <li>Bugfix: Externalizable deserialization supported for objects not at the root of tree.</li>
1138 <li>JavaMethodConverter handles non public methods/constructors (contributed by Kevin Ring).</li>
1139 <li>PropertiesConverter also serializes default properties, if present (contributed by Kevin Ring).</li>
1140 <li>Bugfix: In some cases, XppReader and StaxReader would get confused when calling hasMoreChildren() and
1141 getValue() on the same node.</li>
1142 <li>JIRA:XSTR-217, ISO8601DateConverter now requires joda-time-1.2.1</li>
1143 <li>PrettyPrintWriter and CompactWriter may have their text/attribute escaping rules customized by overriding
1144 writeText() and writeAttributeValue().</li>
1145 </ul>
1146
1147 <h2>API changes</h2>
1148
1149 <ul>
1150 <li>HierarchicalStreamDriver implementations now require a createWriter() method. The simplest implementation is
1151 to return a new PrettyPrintWriter.</li>
1152 <li>Introduced ReaderWrapper/WriterWrapper classes to make it easier to wrap (decorate)
1153 HierarchicalStreamReader/Writer instances.</li>
1154 </ul>
1155
1156 <h1 id="1.1.1">Version 1.1.1</h1>
1157
1158 <p>Released March 7, 2005. Mostly bugfixes and minor feature enhancements.</p>
1159
1160 <h2>Major changes</h2>
1161
1162 <ul>
1163 <li>Converters can be registered with a priority, allowing more <i>generic</i> filters to handle classes that
1164 don't have more specific converters.
1165 </li>
1166 <li>Converters can now access underlying HierarchicalStreamReader/Writer implementations to make implementation
1167 specific calls.</li>
10421168 <li>Improved support for classes using ObjectInputFields to follow the serialization specification.</li>
10431169 <li>JIRA:XSTR-179 Support for ObjectInputStream.registerValidation(ObjectInputValidation).</li>
10441170 <li>JIRA:XSTR-178 Serialized inner class now maintains reference to outer class.</li>
10471173
10481174 <h2>Minor changes</h2>
10491175
1050 <ul>
1051 <li>Bugfix: Thread context classloader is loaded by the correct thread. (Thanks to Padraic Renaghan for pointing this out).</li>
1052 <li>Bugfix: Default implementations of aliased classes were not being deserialized by SerializableConverter.</li>
1053 <li>Bugfix: JIRA:XSTR-180 Serializable objects support defaultReadObject() even when no default fields available.</li>
1054 <li>Bugfix: For serialized objects class hierarchy is serialized starting with superclass (as per Java Object Serialization).</li>
1176 <ul>
1177 <li>Bugfix: Thread context classloader is loaded by the correct thread. (Thanks to Padraic Renaghan for pointing
1178 this out).</li>
1179 <li>Bugfix: Default implementations of aliased classes were not being deserialized by SerializableConverter.</li>
1180 <li>Bugfix: JIRA:XSTR-180 Serializable objects support defaultReadObject() even when no default fields available.</li>
1181 <li>Bugfix: For serialized objects class hierarchy is serialized starting with superclass (as per Java Object
1182 Serialization).</li>
10551183 <li>Bugfix: readObject() is now called for classes containing only transient fields.</li>
10561184 <li>Bugfix: Order of fields are maintained when calling ObjectOutputStream.putFields().</li>
10571185 <li>Bugfix: FontConverter extended to support FontUIResource which does some awkward native calls.</li>
1058 <li>Bugfix: Deserialization of very complicated graphs (such as Swing components) sometimes resulted in broken object references. Now fixed.</li>
1186 <li>Bugfix: Deserialization of very complicated graphs (such as Swing components) sometimes resulted in broken
1187 object references. Now fixed.</li>
10591188 <li>Bugfix: JIRA:XSTR-188 Classes that use readResolve()/writeReplace() can now return different types.</li>
1060 <li>Bugfix: JIRA:XSTR-185, JIRA:XSTR-195 Support for loading of array classes for classes that have not yet been loaded. (Thanks to Henri Tremblay and Simon Daniel)</li>
1189 <li>Bugfix: JIRA:XSTR-185, JIRA:XSTR-195 Support for loading of array classes for classes that have not yet been
1190 loaded. (Thanks to Henri Tremblay and Simon Daniel)</li>
10611191 <li>Bugfix: JIRA:XSTR-190 PrettyPrintWriter and CompactWriter escape characters in XML attributes.</li>
1062 <li>Bugfix: JIRA:XSTR-176, JIRA:XSTR-196 The XStream ObjectInputStream and ObjectOutputStream implementations now propegate the flush() and close() events to the underlying streams.</li>
1192 <li>Bugfix: JIRA:XSTR-176, JIRA:XSTR-196 The XStream ObjectInputStream and ObjectOutputStream implementations now
1193 propegate the flush() and close() events to the underlying streams.</li>
10631194 <li>Bugfix: JIRA:XSTR-192 Implicit collection mappings are now supported in inheritance hierarchies.</li>
1064 </ul>
1065
1066 <h2>API changes</h2>
1067
1068 <ul>
1069 <li>ClassMapper is now deprecated. Replaced with MapperWrapper.</li>
1070 <li>HierarchicalStreamWriter implementations must now implement close(), flush() and underlyingWriter().</li>
1071 <li>HierarchicalStreamReader implementations must now implement close() and underlyingReader().</li>
1072 </ul>
1073
1074 <h1 id="1.1">Version 1.1</h1>
1075
1076 <p>Released January 15, 2005. Focus on support for objects defining custom serialization using the standard
1077 <a href="http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/serialTOC.html">Java serialization</a> mechanism.</p>
1078
1079 <h2>Major changes</h2>
1080
1081 <ul>
1082 <li>Provides drop in replacement for ObjectInputStream and ObjectOutputStream, using XStream.createObjectInputStream() and
1083 XStream.createObjectOutputStream() and XStream.createObjectInputStream(). This provides support for streaming objects.</li>
1084 <li>Support for objects that specify their own serialization schemes by implementing readObject() and writeObject()
1085 (as in Java serialization spec). This includes support for ObjectInputStream.getFields() and ObjectOuputStream.putFields().</li>
1086 <li>Support for objects to serialize other objects to the stream by implementing writeReplace() (as in Java serialization spec).</li>
1087 <li>Support for any object that performs custom serialization by implementing java.io.Externalizable (as in Java serialization spec).</li>
1088 <li>Implicit collections can be specified for classes, allowing the element wrapping the collection to be skipped.</li>
1089 <li>New writer implementations to allow XStream to serialize directly to a SAX stream or TrAX pipeline.</li>
1090 <li>The MarshallingContext and UnmarshallingContext interfaces now extend DataHolder, allowing arbitrary data to be stored
1091 by the user whilst walking the object graph and passed around to Converters. DataHolders can also be passed into
1092 XStream from the outside.</li>
1093 <li>Includes new DomWriter implementation to serialize directly to a W3C DOM tree (to complement the existing DomReader).</li>
1094 <li>Better support for instantiating objects on non Sun 1.4+ JVMs, including non-public constructors, private static inner classes and
1095 ANY class that implements java.io.Serializable.</li>
1096 <li>DOM, DOM4J, JDOM, XOM, Electric-XML, SAX, STAX</li>
1097 <li>Specific ClassLoaders can be passed into XStream, to allow for greater compatibility in J2EE containers.</li>
1098 <li>Ability to change the default converter</li>
1099 <li>Added optional ISO8601DateConverter for full ISO8601 date format support. The converter is not registered by default
1100 as it requires the joda-time dependency (http://joda-time.sf.net). To use, ensure joda-time is in classpath and register explicitly.</li>
1101 <li>Enhanced mode is now supported on the Apple 1.4 JDK.</li>
1102 </ul>
1103
1104 <h2>Minor changes</h2>
1105
1106 <ul>
1107 <li>PrettyPrintWriter only flushes stream when necessary - large performance improvement for serialization.</li>
1108 <li>Added XStream.fromXml(xml, root) convenience methods for deserializing into an existing root object.</li>
1109 <li>JDK 1.3 compatibility: Added mechanism for accessing nested exception.</li>
1110 <li>JDK 1.3 compatibility: GregorianCalendarConverter only calls Calendar.getTimeInMillis() the JDK supports it.</li>
1111 <li>Bugfix: All caches are now synchronized - there were some thread safety issues.</li>
1112 <li>Bugfix: Only <i>immutable</i> basic types will have references ignored in XML (for clarity).</li>
1113 <li>Bugfix: Class names can contain underscores.</li>
1114 <li>Bugfix: Support for '\0' char.</li>
1115 <li>Bugfix: PropertyConverter no longer attempts to serialize subclasses of Properties.</li>
1116 <li>Bugfix: JVM detection uses system properties, which is more accurate than searching the classpath.</li>
1117 </ul>
1118
1119 <h2>API changes</h2>
1120
1121 <ul>
1122 <li>XStream.addDefaultCollection() has been deprecated. Use XStream.addImplicitCollection() instead.</li>
1123 </ul>
1124
1125 <h1 id="1.0.2">Version 1.0.2</h1>
1126
1127 <p>Released August 7, 2004. Focus on improving the converters bundled with XStream to support a wider range of types.</p>
1128
1129 <h2>Major changes</h2>
1130
1131 <ul>
1132 <li>XML elements are written in order they are defined in class, rather than alphabetical.</li>
1133 <li>Converters for java.io.File, java.sql.Timestamp, java.awt.Color, and dynamic proxies are now
1134 registered by default.</li>
1135 <li>EncodedByteArrayConverter is now registered by default and uses a single Base64 string to store the contents
1136 of a byte[]. This now works on all JVMs as it no longer relies on Sun specific classes. This converter will also
1137 unmarshal byte[] that have been serialized without it, for backwards compatability.</li>
1138 <li>New converters for java.sql.Time, java.sql.Date, java.util.Locale, java.util.Currency, java.util.Calendar
1139 and java.awt.Font.</li>
1140 <li>All caching is done in XStream instance instead of statics, allowing applications that use hot redeployment
1141 of classes to use XStream in a parent classloader.</li>
1142 <li>XStream will fail fast if a field value is defined more than once in XML when deserializing.</li>
1143 </ul>
1144
1145 <h2>Minor changes</h2>
1146
1147 <ul>
1148 <li>The &lt;entry&gt; element used in Maps can now be specified by creating an alias for java.util.Map.Entry.</li>
1149 <li>Bugfix: Fields with characters that generate invalid XML (such as $ signs) are now escaped.</li>
1150 <li>Bugfix: Pre-instantiated objects can be unmarshalled through multiple levels.</li>
1151 </ul>
1152
1153 <h2>API changes</h2>
1154
1155 <ul>
1156 <li>None.</li>
1157 </ul>
1158
1159 <h1 id="1.0.1">Version 1.0.1</h1>
1160
1161 <p>Released May 30, 2004. Misc features and bugfixes.</p>
1162
1163 <h2>Major changes</h2>
1164
1165 <ul>
1166 <li>Support for multidimensional arrays.</li>
1167 <li>Object with readResolve() method will be treated the same way native serialization treats them.</li>
1168 </ul>
1169
1170 <h2>Minor changes</h2>
1171
1172 <ul>
1173 <li>New converters for Throwable and StackTraceElement that retain stack trace (JDK 1.4 only)</li>
1174 <li>Bugfix: System.identityHashCode() is not guaranteed to be unique. Ensure reference checking is used as well.</li>
1175 <li>Bugfix: Allows user classes to be defined in WEB-INF/classes in Servlet environments. Tries to use context classloader if available.</li>
1176 <li>Support for java.util.Currency (through readResolve()).</li>
1177 <li>Instances of Jakarta Commons Lang Enum are now reused (through readResolve()).</li>
1178 <li>Bugfix: JavaClassConverter handles primitive type classes (contributed by Matthew Sandoz).</li>
1179 </ul>
1180
1181 <h2>API changes</h2>
1182
1183 <ul>
1184 <li>Additional method: ConverterLookup.defaultConverter(). Custom implementations of this class should implement
1185 this new method.</li>
1186 </ul>
1187
1188 <h1 id="1.0">Version 1.0</h1>
1189
1190 <p>Released May 14, 2004. Focusses on finalizing the API for 1.0 release.</p>
1191
1192 <h2>Major changes</h2>
1193
1194 <ul>
1195 <li>Supports fields of same name, hidden by inheritance.</li>
1196 </ul>
1197
1198 <h2>Minor changes</h2>
1199
1200 <ul>
1201 <li>JavaDoc for most important parts of API.</li>
1202 </ul>
1203
1204 <h2>API changes</h2>
1205
1206 <ul>
1207 <li>The ReflectionConverter and ReflectionProviders have had an overhaul to support
1208 hidden fields. Most methods now take an extra argument to specify which class a field
1209 is declared in.</li>
1210 </ul>
1211
1212 <h1 id="1.0RC1">Version 1.0 (release candidate 1)</h1>
1213
1214 <p>Released May 9, 2004. Focusses on finalizing the API for 1.0 release.</p>
1215
1216 <h2>Major changes</h2>
1217
1218 <ul>
1219 <li>JDK 1.3 compatibility.</li>
1220 <li>Informative error messages.</li>
1221 <li>Defaults to using faster XPP based parser.</li>
1222 <li>Serializes final field under JDK 1.4.</li>
1223 <li>Fail fast when trying to serialize final field if not Sun 1.4 JRE.</li>
1224 </ul>
1225
1226 <h2>Minor changes</h2>
1227
1228 <ul>
1229 <li>Misc performance improvements.</li>
1230 <li>Converters for TreeMap and TreeSet that store the Comparator.</li>
1231 </ul>
1232
1233 <h2>API changes</h2>
1234
1235 <ul>
1236 <li>Default constructor for XStream class uses XppDriver instead of DomDriver.
1237 To use DomDriver, explicitly pass it in to the constructor.</li>
1238 <li>Exception is thrown if trying to serialize an object that contains a
1239 final field if not Sun 1.4 JRE.</li>
1240 </ul>
1241
1242 <p><a href="versioning.html">About XStream version numbers...</a></p>
1243
1244 <h1 id="0.6">Version 0.6</h1>
1245
1246 <p>Released May 7, 2004. Focusses on providing full object graph support.</p>
1247
1248 <h2>Major changes</h2>
1249
1250 <ul>
1251 <li>None.</li>
1252 </ul>
1253
1254 <h2>Minor changes</h2>
1255
1256 <ul>
1257 <li>Bugfix: Objects that had no children could not be derefenced properly (thanks to Brian Slesinsky and Nick Pomfret).</li>
1258 <li>Bugfix: DateConverter is now thread safe.</li>
1259 <li>Optimization: String instances are reused as much as possible.</li>
1260 <li>Converters for BigInteger and BigDecimal.</li>
1261 <li>IntConverter now recognises hexadecimal and octal notations (thanks to Konstantin Pribluda).</li>
1262 </ul>
1263
1264 <h2>API changes</h2>
1265
1266 <ul>
1267 <li>None.</li>
1268 </ul>
1269
1270 <h1 id="0.6RC1">Version 0.6 (release candidate 1)</h1>
1271
1272 <p>Released April 19, 2004. Focusses on providing full object graph support.</p>
1273
1274 <h2>Major changes</h2>
1275
1276 <ul>
1277 <li>Full support for object graphs, including duplicate references of same object and
1278 circular references.</li>
1279 <li>References can be identified using XPath (default), unique-IDs or disabled.</li>
1280 </ul>
1281
1282 <h2>Minor changes</h2>
1283
1284 <ul>
1285 <li>Release includes Ant build file.</li>
1286 <li>Converters for non standard collections such as Collections.EMPTY_LIST, syncronizedList(), unmodifiableMap(), etc.</li>
1287 <li>Converter for nulls.</li>
1288 <li>Converter for dynamic proxies.</li>
1289 <li>Converter for java.net.URL.</li>
1290 <li>Converters for java.util.LinkedHashMap and java.util.LinkedHashSet.</li>
1291 <li>Converters for java.lang.reflect.Method and java.lang.reflect.Constructor.</li>
1292 <li>If duplicate reference support is disabled and a circular reference is encountered, an exception will be thrown.</li>
1293 </ul>
1294
1295 <h2>API changes</h2>
1296
1297 <ul>
1298 <li>None.</li>
1299 </ul>
1300
1301 <h1 id="0.5">Version 0.5</h1>
1302
1303 <p>Released March 8, 2004. Focussed on performance.</p>
1304
1305 <h2>Major changes</h2>
1306
1307 <ul>
1308 <li>Massive performance improvements. Up to 3 times faster for serialization and 22
1309 times faster for deserialization!</li>
1310 <li>Non-DOM building pull parser based reader. Results in much smaller memory footprint,
1311 particularly when deserializing large object models.</li>
1312 </ul>
1313
1314 <h2>Minor changes</h2>
1315
1316 <ul>
1317 <li>Misc performance improvements.</li>
1318 <li>Misc bugfixes.</li>
1319 <li>Alternate encodings can be used with DomDriver.</li>
1320 </ul>
1321
1322 <h2>API changes</h2>
1323
1324 <ul>
1325 <li>Renamed XMLReader/Writer to HierarchicalStreamReader/Writer as XStream is not
1326 actually coupled to serializing just to XML.</li>
1327 <li>Cleaned up the public API.</li>
1328 <li>Moved internal XStream implementation classes to core package.</li>
1329 <li>Misc package/class renames to make more sense. Dumped lots of dead code.</li>
1330 </ul>
1331
1332 <h1 id="0.4">Version 0.4</h1>
1333
1334 <p>This version was never publicly released. All changes were made available in 0.5. Focussed on making it easier to create custom converters.</p>
1335
1336 <h2>Major changes</h2>
1337
1338 <ul>
1339 <li>Overhaul of interface for Converters. Makes Converters much cleaner to write.</li>
1340 </ul>
1341
1342 <h2>Minor changes</h2>
1343
1344 <ul>
1345 <li>Added custom converters for java.io.File, java.util.Properties, java.util.Vector, java.util.Hashtable, java.util.BitSet
1346 byte[] (Base64 encoded), char[].</li>
1347 <li>Misc bugfixes.</li>
1348 </ul>
1349
1350 <h2>API changes</h2>
1351
1352 <ul>
1353 <li>New interface to be implemented by custom converters.</li>
1354 </ul>
1355
1356 <h1 id="0.3">Version 0.3</h1>
1357
1358 <p>Released January 1, 2004.</p>
1359
1360 <h2>Major changes</h2>
1361
1362 <ul>
1363 <li>Added ElementMapper interface and default implementations to allow fine
1364 grained control over element name to class mapper operations.</li>
1365 <li>Added an XPP based reader and writer that uses a pull-parser to create a lightweight DOM tree.</li>
1366 </ul>
1367
1368 <h2>Minor changes</h2>
1369
1370 <ul>
1371 <li>Added XStream.fromXML(XMLReader xmlReader,Object root) method to
1372 allow the population of an object graph starting with a live object root.</li>
1373 <li>Added XMLReader.peek() method to allow access to the underlying hierarchical
1374 object being unmarshalled.</li>
1375 </ul>
1376
1377 <h2>API changes</h2>
1378
1379 <ul>
1380 <li>Aligned the the methods in XStream to use the specified ObjectFactory in the constructor
1381 instead of creating a SunReflectionObjectFactory.</li>
1382 </ul>
1383
1384 <h1 id="older">Older versions</h1>
1385
1386 <p>Changes in XStream prior to version 0.3 were not logged.</p>
1387
1388 </body>
1195 </ul>
1196
1197 <h2>API changes</h2>
1198
1199 <ul>
1200 <li>ClassMapper is now deprecated. Replaced with MapperWrapper.</li>
1201 <li>HierarchicalStreamWriter implementations must now implement close(), flush() and underlyingWriter().</li>
1202 <li>HierarchicalStreamReader implementations must now implement close() and underlyingReader().</li>
1203 </ul>
1204
1205 <h1 id="1.1">Version 1.1</h1>
1206
1207 <p>
1208 Released January 15, 2005. Focus on support for objects defining custom serialization using the standard <a
1209 href="http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/serialTOC.html">Java serialization</a> mechanism.
1210 </p>
1211
1212 <h2>Major changes</h2>
1213
1214 <ul>
1215 <li>Provides drop in replacement for ObjectInputStream and ObjectOutputStream, using
1216 XStream.createObjectInputStream() and XStream.createObjectOutputStream() and XStream.createObjectInputStream(). This
1217 provides support for streaming objects.</li>
1218 <li>Support for objects that specify their own serialization schemes by implementing readObject() and
1219 writeObject() (as in Java serialization spec). This includes support for ObjectInputStream.getFields() and
1220 ObjectOuputStream.putFields().</li>
1221 <li>Support for objects to serialize other objects to the stream by implementing writeReplace() (as in Java
1222 serialization spec).</li>
1223 <li>Support for any object that performs custom serialization by implementing java.io.Externalizable (as in Java
1224 serialization spec).</li>
1225 <li>Implicit collections can be specified for classes, allowing the element wrapping the collection to be
1226 skipped.</li>
1227 <li>New writer implementations to allow XStream to serialize directly to a SAX stream or TrAX pipeline.</li>
1228 <li>The MarshallingContext and UnmarshallingContext interfaces now extend DataHolder, allowing arbitrary data to
1229 be stored by the user whilst walking the object graph and passed around to Converters. DataHolders can also be passed
1230 into XStream from the outside.</li>
1231 <li>Includes new DomWriter implementation to serialize directly to a W3C DOM tree (to complement the existing
1232 DomReader).</li>
1233 <li>Better support for instantiating objects on non Sun 1.4+ JVMs, including non-public constructors, private
1234 static inner classes and ANY class that implements java.io.Serializable.</li>
1235 <li>DOM, DOM4J, JDOM, XOM, Electric-XML, SAX, STAX</li>
1236 <li>Specific ClassLoaders can be passed into XStream, to allow for greater compatibility in J2EE containers.</li>
1237 <li>Ability to change the default converter</li>
1238 <li>Added optional ISO8601DateConverter for full ISO8601 date format support. The converter is not registered by
1239 default as it requires the joda-time dependency (http://joda-time.sf.net). To use, ensure joda-time is in classpath
1240 and register explicitly.</li>
1241 <li>Enhanced mode is now supported on the Apple 1.4 JDK.</li>
1242 </ul>
1243
1244 <h2>Minor changes</h2>
1245
1246 <ul>
1247 <li>PrettyPrintWriter only flushes stream when necessary - large performance improvement for serialization.</li>
1248 <li>Added XStream.fromXml(xml, root) convenience methods for deserializing into an existing root object.</li>
1249 <li>JDK 1.3 compatibility: Added mechanism for accessing nested exception.</li>
1250 <li>JDK 1.3 compatibility: GregorianCalendarConverter only calls Calendar.getTimeInMillis() the JDK supports it.</li>
1251 <li>Bugfix: All caches are now synchronized - there were some thread safety issues.</li>
1252 <li>Bugfix: Only <i>immutable</i> basic types will have references ignored in XML (for clarity).
1253 </li>
1254 <li>Bugfix: Class names can contain underscores.</li>
1255 <li>Bugfix: Support for '\0' char.</li>
1256 <li>Bugfix: PropertyConverter no longer attempts to serialize subclasses of Properties.</li>
1257 <li>Bugfix: JVM detection uses system properties, which is more accurate than searching the classpath.</li>
1258 </ul>
1259
1260 <h2>API changes</h2>
1261
1262 <ul>
1263 <li>XStream.addDefaultCollection() has been deprecated. Use XStream.addImplicitCollection() instead.</li>
1264 </ul>
1265
1266 <h1 id="1.0.2">Version 1.0.2</h1>
1267
1268 <p>Released August 7, 2004. Focus on improving the converters bundled with XStream to support a wider range of
1269 types.</p>
1270
1271 <h2>Major changes</h2>
1272
1273 <ul>
1274 <li>XML elements are written in order they are defined in class, rather than alphabetical.</li>
1275 <li>Converters for java.io.File, java.sql.Timestamp, java.awt.Color, and dynamic proxies are now registered by
1276 default.</li>
1277 <li>EncodedByteArrayConverter is now registered by default and uses a single Base64 string to store the contents
1278 of a byte[]. This now works on all JVMs as it no longer relies on Sun specific classes. This converter will also
1279 unmarshal byte[] that have been serialized without it, for backwards compatability.</li>
1280 <li>New converters for java.sql.Time, java.sql.Date, java.util.Locale, java.util.Currency, java.util.Calendar and
1281 java.awt.Font.</li>
1282 <li>All caching is done in XStream instance instead of statics, allowing applications that use hot redeployment
1283 of classes to use XStream in a parent classloader.</li>
1284 <li>XStream will fail fast if a field value is defined more than once in XML when deserializing.</li>
1285 </ul>
1286
1287 <h2>Minor changes</h2>
1288
1289 <ul>
1290 <li>The &lt;entry&gt; element used in Maps can now be specified by creating an alias for java.util.Map.Entry.</li>
1291 <li>Bugfix: Fields with characters that generate invalid XML (such as $ signs) are now escaped.</li>
1292 <li>Bugfix: Pre-instantiated objects can be unmarshalled through multiple levels.</li>
1293 </ul>
1294
1295 <h2>API changes</h2>
1296
1297 <ul>
1298 <li>None.</li>
1299 </ul>
1300
1301 <h1 id="1.0.1">Version 1.0.1</h1>
1302
1303 <p>Released May 30, 2004. Misc features and bugfixes.</p>
1304
1305 <h2>Major changes</h2>
1306
1307 <ul>
1308 <li>Support for multidimensional arrays.</li>
1309 <li>Object with readResolve() method will be treated the same way native serialization treats them.</li>
1310 </ul>
1311
1312 <h2>Minor changes</h2>
1313
1314 <ul>
1315 <li>New converters for Throwable and StackTraceElement that retain stack trace (JDK 1.4 only)</li>
1316 <li>Bugfix: System.identityHashCode() is not guaranteed to be unique. Ensure reference checking is used as well.</li>
1317 <li>Bugfix: Allows user classes to be defined in WEB-INF/classes in Servlet environments. Tries to use context
1318 classloader if available.</li>
1319 <li>Support for java.util.Currency (through readResolve()).</li>
1320 <li>Instances of Jakarta Commons Lang Enum are now reused (through readResolve()).</li>
1321 <li>Bugfix: JavaClassConverter handles primitive type classes (contributed by Matthew Sandoz).</li>
1322 </ul>
1323
1324 <h2>API changes</h2>
1325
1326 <ul>
1327 <li>Additional method: ConverterLookup.defaultConverter(). Custom implementations of this class should implement
1328 this new method.</li>
1329 </ul>
1330
1331 <h1 id="1.0">Version 1.0</h1>
1332
1333 <p>Released May 14, 2004. Focusses on finalizing the API for 1.0 release.</p>
1334
1335 <h2>Major changes</h2>
1336
1337 <ul>
1338 <li>Supports fields of same name, hidden by inheritance.</li>
1339 </ul>
1340
1341 <h2>Minor changes</h2>
1342
1343 <ul>
1344 <li>JavaDoc for most important parts of API.</li>
1345 </ul>
1346
1347 <h2>API changes</h2>
1348
1349 <ul>
1350 <li>The ReflectionConverter and ReflectionProviders have had an overhaul to support hidden fields. Most methods
1351 now take an extra argument to specify which class a field is declared in.</li>
1352 </ul>
1353
1354 <h1 id="1.0RC1">Version 1.0 (release candidate 1)</h1>
1355
1356 <p>Released May 9, 2004. Focusses on finalizing the API for 1.0 release.</p>
1357
1358 <h2>Major changes</h2>
1359
1360 <ul>
1361 <li>JDK 1.3 compatibility.</li>
1362 <li>Informative error messages.</li>
1363 <li>Defaults to using faster XPP based parser.</li>
1364 <li>Serializes final field under JDK 1.4.</li>
1365 <li>Fail fast when trying to serialize final field if not Sun 1.4 JRE.</li>
1366 </ul>
1367
1368 <h2>Minor changes</h2>
1369
1370 <ul>
1371 <li>Misc performance improvements.</li>
1372 <li>Converters for TreeMap and TreeSet that store the Comparator.</li>
1373 </ul>
1374
1375 <h2>API changes</h2>
1376
1377 <ul>
1378 <li>Default constructor for XStream class uses XppDriver instead of DomDriver. To use DomDriver, explicitly pass
1379 it in to the constructor.</li>
1380 <li>Exception is thrown if trying to serialize an object that contains a final field if not Sun 1.4 JRE.</li>
1381 </ul>
1382
1383 <p>
1384 <a href="versioning.html">About XStream version numbers...</a>
1385 </p>
1386
1387 <h1 id="0.6">Version 0.6</h1>
1388
1389 <p>Released May 7, 2004. Focusses on providing full object graph support.</p>
1390
1391 <h2>Major changes</h2>
1392
1393 <ul>
1394 <li>None.</li>
1395 </ul>
1396
1397 <h2>Minor changes</h2>
1398
1399 <ul>
1400 <li>Bugfix: Objects that had no children could not be derefenced properly (thanks to Brian Slesinsky and Nick
1401 Pomfret).</li>
1402 <li>Bugfix: DateConverter is now thread safe.</li>
1403 <li>Optimization: String instances are reused as much as possible.</li>
1404 <li>Converters for BigInteger and BigDecimal.</li>
1405 <li>IntConverter now recognises hexadecimal and octal notations (thanks to Konstantin Pribluda).</li>
1406 </ul>
1407
1408 <h2>API changes</h2>
1409
1410 <ul>
1411 <li>None.</li>
1412 </ul>
1413
1414 <h1 id="0.6RC1">Version 0.6 (release candidate 1)</h1>
1415
1416 <p>Released April 19, 2004. Focusses on providing full object graph support.</p>
1417
1418 <h2>Major changes</h2>
1419
1420 <ul>
1421 <li>Full support for object graphs, including duplicate references of same object and circular references.</li>
1422 <li>References can be identified using XPath (default), unique-IDs or disabled.</li>
1423 </ul>
1424
1425 <h2>Minor changes</h2>
1426
1427 <ul>
1428 <li>Release includes Ant build file.</li>
1429 <li>Converters for non standard collections such as Collections.EMPTY_LIST, syncronizedList(), unmodifiableMap(),
1430 etc.</li>
1431 <li>Converter for nulls.</li>
1432 <li>Converter for dynamic proxies.</li>
1433 <li>Converter for java.net.URL.</li>
1434 <li>Converters for java.util.LinkedHashMap and java.util.LinkedHashSet.</li>
1435 <li>Converters for java.lang.reflect.Method and java.lang.reflect.Constructor.</li>
1436 <li>If duplicate reference support is disabled and a circular reference is encountered, an exception will be
1437 thrown.</li>
1438 </ul>
1439
1440 <h2>API changes</h2>
1441
1442 <ul>
1443 <li>None.</li>
1444 </ul>
1445
1446 <h1 id="0.5">Version 0.5</h1>
1447
1448 <p>Released March 8, 2004. Focussed on performance.</p>
1449
1450 <h2>Major changes</h2>
1451
1452 <ul>
1453 <li>Massive performance improvements. Up to 3 times faster for serialization and 22 times faster for
1454 deserialization!</li>
1455 <li>Non-DOM building pull parser based reader. Results in much smaller memory footprint, particularly when
1456 deserializing large object models.</li>
1457 </ul>
1458
1459 <h2>Minor changes</h2>
1460
1461 <ul>
1462 <li>Misc performance improvements.</li>
1463 <li>Misc bugfixes.</li>
1464 <li>Alternate encodings can be used with DomDriver.</li>
1465 </ul>
1466
1467 <h2>API changes</h2>
1468
1469 <ul>
1470 <li>Renamed XMLReader/Writer to HierarchicalStreamReader/Writer as XStream is not actually coupled to serializing
1471 just to XML.</li>
1472 <li>Cleaned up the public API.</li>
1473 <li>Moved internal XStream implementation classes to core package.</li>
1474 <li>Misc package/class renames to make more sense. Dumped lots of dead code.</li>
1475 </ul>
1476
1477 <h1 id="0.4">Version 0.4</h1>
1478
1479 <p>This version was never publicly released. All changes were made available in 0.5. Focussed on making it easier
1480 to create custom converters.</p>
1481
1482 <h2>Major changes</h2>
1483
1484 <ul>
1485 <li>Overhaul of interface for Converters. Makes Converters much cleaner to write.</li>
1486 </ul>
1487
1488 <h2>Minor changes</h2>
1489
1490 <ul>
1491 <li>Added custom converters for java.io.File, java.util.Properties, java.util.Vector, java.util.Hashtable,
1492 java.util.BitSet byte[] (Base64 encoded), char[].</li>
1493 <li>Misc bugfixes.</li>
1494 </ul>
1495
1496 <h2>API changes</h2>
1497
1498 <ul>
1499 <li>New interface to be implemented by custom converters.</li>
1500 </ul>
1501
1502 <h1 id="0.3">Version 0.3</h1>
1503
1504 <p>Released January 1, 2004.</p>
1505
1506 <h2>Major changes</h2>
1507
1508 <ul>
1509 <li>Added ElementMapper interface and default implementations to allow fine grained control over element name to
1510 class mapper operations.</li>
1511 <li>Added an XPP based reader and writer that uses a pull-parser to create a lightweight DOM tree.</li>
1512 </ul>
1513
1514 <h2>Minor changes</h2>
1515
1516 <ul>
1517 <li>Added XStream.fromXML(XMLReader xmlReader,Object root) method to allow the population of an object graph
1518 starting with a live object root.</li>
1519 <li>Added XMLReader.peek() method to allow access to the underlying hierarchical object being unmarshalled.</li>
1520 </ul>
1521
1522 <h2>API changes</h2>
1523
1524 <ul>
1525 <li>Aligned the the methods in XStream to use the specified ObjectFactory in the constructor instead of creating
1526 a SunReflectionObjectFactory.</li>
1527 </ul>
1528
1529 <h1 id="older">Older versions</h1>
1530
1531 <p>Changes in XStream prior to version 0.3 were not logged.</p>
1532
1533 </body>
13891534 </html>
00 <html>
11 <!--
22 Copyright (C) 2005, 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2014, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2014, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
165165 <td><a href="javadoc/com/thoughtworks/xstream/converters/basic/StringBuildererConverter.html">StringBuilderConverter</a></td>
166166 <td>java.lang.StringBuilder</td>
167167 <td class="example">&lt;string-builder&gt;hello world&lt;/string-builder&gt;</td>
168 <td>Available under Java 1.5 or greater.</td>
168 <td>Available with Java 1.5 or greater.</td>
169169 <td>normal</td>
170170 </tr>
171171 <tr>
182182 &nbsp;&nbsp;&lt;/stack-trace&gt;<br/>
183183 &lt;/java.io.IOException&gt;
184184 </td>
185 <td>This is only available under Java 1.4 or greater. It retains the full stack trace, including that of any
185 <td>This is only available with Java 1.4 or greater. It retains the full stack trace, including that of any
186186 nested exceptions. The stack trace elements are handled by the
187187 <a href="javadoc/com/thoughtworks/xstream/converters/extended/StackTraceElementConverter.html">StackTraceElementConverter</a>.</td>
188188 <td>normal</td>
191191 <td><a href="javadoc/com/thoughtworks/xstream/converters/enums/EnumConverter.html">EnumConverter</a></td>
192192 <td>java.lang.Enum</td>
193193 <td class="example">&lt;java.lang.annotation.RetentionPolicy&gt;<br/>CLASS<br/>&lt;/java.lang.annotation.RetentionPolicy&gt;</td>
194 <td>Available under Java 1.5 or greater.</td>
194 <td>Available with Java 1.5 or greater.</td>
195195 <td>normal</td>
196196 </tr>
197197 <tr>
199199 <td>java.lang.Enum</td>
200200 <td>The Converter must be initialized with an Enum type and an optional mapping between strings and enum values. By default
201201 it will use the Enum's string representation as value.</td>
202 <td>Available under Java 1.5 or greater. Must be registered explicitly for the Enum type or locally.</td>
202 <td>Available with Java 1.5 or greater. Must be registered explicitly for the Enum type or locally.</td>
203203 <td>&nbsp;</td>
204204 </tr>
205205
385385 <td><a href="javadoc/com/thoughtworks/xstream/converters/extended/ISO8601DateConverter.html">ISO8601DateConverter</a></td>
386386 <td>java.util.Date</td>
387387 <td class="example">&lt;date&gt;2006-07-28T12:06:17.654-03:00&lt;/date&gt;</td>
388 <td>Not automatically registered, can be used globally or locally. Implementation needs joda-time.</td>
388 <td>Not automatically registered, can be used globally or locally. Implementation needs joda-time for JDK 1.7 or below.</td>
389389 <td>&nbsp;</td>
390390 </tr>
391391 <tr>
396396 2006-07-28T12:07:02.788-03:00<br/>
397397 &lt;/gregorian-calendar&gt;
398398 </td>
399 <td>Not automatically registered, can be used globally or locally. Implementation needs joda-time.</td>
399 <td>Not automatically registered, can be used globally or locally. Implementation needs joda-time for JDK 1.7 or below.</td>
400400 <td>&nbsp;</td>
401401 </tr>
402402 <tr>
410410 <td><a href="javadoc/com/thoughtworks/xstream/converters/extended/CurrencyConverter.html">CurrencyConverter</a></td>
411411 <td>java.util.Currency</td>
412412 <td class="example">&lt;currency&gt;USD&lt;/currency&gt;</td>
413 <td>Available under Java 1.4 or greater.</td>
413 <td>Available with Java 1.4 or greater.</td>
414414 <td>normal</td>
415415 </tr>
416416 <tr>
417417 <td><a href="javadoc/com/thoughtworks/xstream/converters/basic/UUIDConverter.html">UUIDConverter</a></td>
418418 <td>java.util.UUID</td>
419419 <td class="example">&lt;uuid&gt;ca05f023-e07f-4956-a6ef-14ddd23df47b&lt;/uuid&gt;</td>
420 <td>Available under Java 1.5 or greater.</td>
420 <td>Available with Java 1.5 or greater.</td>
421421 <td>normal</td>
422422 </tr>
423423 <tr>
434434 &nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;sky&lt;/string&gt;<br/>
435435 &nbsp;&nbsp;&lt;/entry&gt;<br/>
436436 &lt;/enum-map&gt;</td>
437 <td>Available under Java 1.5 or greater.</td>
437 <td>Available with Java 1.5 or greater.</td>
438438 <td>normal</td>
439439 </tr>
440440 <tr>
444444 &lt;enum-set enum-type=&quot;simple&quot;&gt;<br/>
445445 &nbsp;&nbsp;GREEN,BLUE<br/>
446446 &lt;/enum-set&gt;</td>
447 <td>Available under Java 1.5 or greater.</td>
447 <td>Available with Java 1.5 or greater.</td>
448448 <td>normal</td>
449449 </tr>
450450 <tr>
456456 &nbsp;&nbsp;&lt;flags&gt;0&lt;/flags&gt;<br/>
457457 &lt;/java.util.regex.Pattern&gt;
458458 </td>
459 <td>Available under Java 1.4 or greater.</td>
459 <td>Available with Java 1.4 or greater.</td>
460 <td>normal</td>
461 </tr>
462
463 <!-- .................................................................................................. -->
464 <tr>
465 <td colspan="5" class="headerRow"><h1 id="java.time">java.time</h1></td>
466 </tr>
467 <tr>
468 <th>Converter</th>
469 <th>Supported types</th>
470 <th>Example</th>
471 <th>Notes</th>
472 <th>Prio</th>
473 </tr>
474 <tr>
475 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/DurationConverter.html">DurationConverter</a></td>
476 <td>java.time.Duration</td>
477 <td class="example">
478 &lt;duration&gt;PT24000H&lt;/duration&gt;
479 </td>
480 <td>Available with Java 8 or greater.</td>
481 <td>normal</td>
482 </tr>
483 <tr>
484 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/InstantConverter.html">InstantConverter</a></td>
485 <td>java.time.Instant</td>
486 <td class="example">
487 &lt;instant&gt;2017-07-30T20:40:00Z&lt;/instant&gt;
488 </td>
489 <td>Available with Java 8 or greater.</td>
490 <td>normal</td>
491 </tr>
492 <tr>
493 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/LocalDateConverter.html">LocalDateConverter</a></td>
494 <td>java.time.LocalDate</td>
495 <td class="example">
496 &lt;local-date&gt;2017-10-30&lt;/local-date&gt;
497 </td>
498 <td>Available with Java 8 or greater.</td>
499 <td>normal</td>
500 </tr>
501 <tr>
502 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/LocalDateTimeConverter.html">LocalDateTimeConverter</a></td>
503 <td>java.time.LocalDateTime</td>
504 <td class="example">
505 &lt;local-date-time&gt;2017-10-30T20:40:15&lt;/local-date-time&gt;
506 </td>
507 <td>Available with Java 8 or greater.</td>
508 <td>normal</td>
509 </tr>
510 <tr>
511 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/LocalTimeConverter.html">LocalTimeConverter</a></td>
512 <td>java.time.LocalTime</td>
513 <td class="example">
514 &lt;local-time&gt;20:40:15&lt;/local-time&gt;
515 </td>
516 <td>Available with Java 8 or greater.</td>
517 <td>normal</td>
518 </tr>
519 <tr>
520 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/MonthDayConverter.html">MonthDayConverter</a></td>
521 <td>java.time.MonthDay</td>
522 <td class="example">
523 &lt;month-day&gt;--01-13&lt;/month-day&gt;
524 </td>
525 <td>Available with Java 8 or greater.</td>
526 <td>normal</td>
527 </tr>
528 <tr>
529 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/OffsetDateTimeConverter.html">OffsetDateTimeConverter</a></td>
530 <td>java.time.OffsetDateTime</td>
531 <td class="example">
532 &lt;offset-date-time&gt;2017-07-30T20:40:00Z&lt;/offset-date-time&gt;
533 </td>
534 <td>Available with Java 8 or greater.</td>
535 <td>normal</td>
536 </tr>
537 <tr>
538 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/OffsetTimeConverter.html">OffsetTimeConverter</a></td>
539 <td>java.time.OffsetTime</td>
540 <td class="example">
541 &lt;offset-time&gt;20:40:15+01:00&lt;/offset-time&gt;
542 </td>
543 <td>Available with Java 8 or greater.</td>
544 <td>normal</td>
545 </tr>
546 <tr>
547 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/PeriodConverter.html">PeriodConverter</a></td>
548 <td>java.time.Period</td>
549 <td class="example">
550 &lt;period&gt;P1000D&lt;/period&gt;
551 </td>
552 <td>Available with Java 8 or greater.</td>
553 <td>normal</td>
554 </tr>
555 <tr>
556 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/SystemClockConverter.html">SystemClockConverter</a></td>
557 <td>java.time.Clock$SystemClock</td>
558 <td class="example">
559 &lt;system-clock&gt;
560 &nbsp;&nbsp;&lt;zone&gt;Europe/Berlin&lt;/zone&gt;
561 &lt;/system-clock&gt;
562 </td>
563 <td>Available with Java 8 or greater.</td>
564 <td>normal</td>
565 </tr>
566 <tr>
567 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/YearConverter.html">YearConverter</a></td>
568 <td>java.time.Year</td>
569 <td class="example">
570 &lt;year&gt;2017&lt;/year&gt;
571 </td>
572 <td>Available with Java 8 or greater.</td>
573 <td>normal</td>
574 </tr>
575 <tr>
576 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/YearMonthConverter.html">YearMonthConverter</a></td>
577 <td>java.time.YearMonth</td>
578 <td class="example">
579 &lt;year-month&gt;2017-02&lt;/year-month&gt;
580 </td>
581 <td>Available with Java 8 or greater.</td>
582 <td>normal</td>
583 </tr>
584 <tr>
585 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/ZonedDateTimeConverter.html">ZonedDateTimeConverter</a></td>
586 <td>java.time.ZonedDateTime</td>
587 <td class="example">
588 &lt;zoned-date-time&gt;2017-10-30T20:40:00Z[Europe/London]&lt;/zoned-date-time&gt;
589 </td>
590 <td>Available with Java 8 or greater.</td>
591 <td>normal</td>
592 </tr>
593 <tr>
594 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/ZoneIdConverter.html">ZoneIdConverter</a></td>
595 <td>java.time.ZoneId<br/>java.time.ZoneOffset<br/>java.time.ZoneRegion</td>
596 <td class="example">
597 &lt;zone-id&gt;Z&lt;/zone-id&gt;
598 </td>
599 <td>Available with Java 8 or greater.</td>
600 <td>normal</td>
601 </tr>
602
603 <!-- .................................................................................................. -->
604 <tr>
605 <td colspan="5" class="headerRow"><h1 id="java.time.chrono">java.time.chrono</h1></td>
606 </tr>
607 <tr>
608 <th>Converter</th>
609 <th>Supported types</th>
610 <th>Example</th>
611 <th>Notes</th>
612 <th>Prio</th>
613 </tr>
614 <tr>
615 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/ChronologyConverter.html">ChronologyConverter</a></td>
616 <td>java.time.chrono.Chronology implementations</td>
617 <td class="example">
618 &lt;chronology&gt;ISO&lt;/chronology&gt;
619 </td>
620 <td>Available with Java 8 or greater.</td>
621 <td>normal</td>
622 </tr>
623 <tr>
624 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/HijrahDateConverter.html">HijrahDateConverter</a></td>
625 <td>java.time.chrono.HijrahDate</td>
626 <td class="example">
627 &lt;hijrah-date&gt;Hijrah-umalqura AH 1438-11-07&lt;/hijrah-date&gt;
628 </td>
629 <td>Available with Java 8 or greater.</td>
630 <td>normal</td>
631 </tr>
632 <tr>
633 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/JapaneseDateConverter.html">JapaneseDateConverter</a></td>
634 <td>java.time.chrono.JapaneseDate</td>
635 <td class="example">
636 &lt;japanese-date&gt;Japanese Heisei 29-07-30&lt;/japanese-date&gt;
637 </td>
638 <td>Available with Java 8 or greater.</td>
639 <td>normal</td>
640 </tr>
641 <tr>
642 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/JapaneseEraConverter.html">JapaneseEraConverter</a></td>
643 <td>java.time.chrono.JapaneseEra</td>
644 <td class="example">
645 &lt;japanese-era&gt;Taisho&lt;/japanese-era&gt;
646 </td>
647 <td>Available with Java 8 or greater.</td>
648 <td>normal</td>
649 </tr>
650 <tr>
651 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/MinguoDateConverter.html">MinguoDateConverter</a></td>
652 <td>java.time.chrono.MinguoDate</td>
653 <td class="example">
654 &lt;minguo-date&gt;Minguo ROC 106-07-30&lt;/minguo-date&gt;
655 </td>
656 <td>Available with Java 8 or greater.</td>
657 <td>normal</td>
658 </tr>
659 <tr>
660 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/ThaiBuddhistDateConverter.html">ThaiBuddhistDateConverter</a></td>
661 <td>java.time.chrono.ThaiBuddhistDate</td>
662 <td class="example">
663 &lt;thai-buddhist-date&gt;haiBuddhist BE 2560-07-30&lt;/thai-buddhist-date&gt;
664 </td>
665 <td>Available with Java 8 or greater.</td>
666 <td>normal</td>
667 </tr>
668
669 <!-- .................................................................................................. -->
670 <tr>
671 <td colspan="5" class="headerRow"><h1 id="java.time.temporal">java.time.temporal</h1></td>
672 </tr>
673 <tr>
674 <th>Converter</th>
675 <th>Supported types</th>
676 <th>Example</th>
677 <th>Notes</th>
678 <th>Prio</th>
679 </tr>
680 <tr>
681 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/ValueRangeConverter.html">ValueRangeConverter</a></td>
682 <td>java.time.temporal.ValueRange</td>
683 <td class="example">
684 &lt;temporal-value-range&gt;<br/>
685 &nbsp;&nbsp;&lt;maxLargest&gt;45&lt;/maxLargest&gt;<br/>
686 &nbsp;&nbsp;&lt;maxSmallest&gt;30&lt;/maxSmallest&gt;<br/>
687 &nbsp;&nbsp;&lt;minLargest&gt;1&lt;/minLargest&gt;<br/>
688 &nbsp;&nbsp;&lt;minSmallest&gt;0&lt;/minSmallest&gt;<br/>
689 &lt;/temporal-value-range&gt;
690 </td>
691 <td>Available with Java 8 or greater.</td>
692 <td>normal</td>
693 </tr>
694 <tr>
695 <td><a href="javadoc/com/thoughtworks/xstream/converters/time/WeekFieldsConverter.html">WeekFieldsConverter</a></td>
696 <td>java.time.temporal.WeekFields</td>
697 <td class="example">
698 &lt;week-fields&gt;<br/>
699 &nbsp;&nbsp;&lt;minimalDays&gt;2&lt;/minimalDays&gt;<br/>
700 &nbsp;&nbsp;&lt;firstDayOfWeek&gt;MONDAY&lt;/firstDayOfWeek&gt;<br/>
701 &lt;/week-fields&gt;
702 </td>
703 <td>Available with Java 8 or greater.</td>
460704 <td>normal</td>
461705 </tr>
462706
496740 <td><a href="javadoc/com/thoughtworks/xstream/converters/extended/ISO8601SqlTimestampConverter.html">ISO8601SqlTimestampConverter</a></td>
497741 <td>java.sql.Timestamp</td>
498742 <td class="example">&lt;sql-timestamp&gt;2006-07-28T12:06:17.654000000-03:00&lt;/sql-timestamp&gt;</td>
499 <td>Not automatically registered, can be used globally or locally. Implementation needs joda-time.</td>
743 <td>Not automatically registered, can be used globally or locally. Implementation needs joda-time for JDK 1.7 or below.</td>
500744 <td>&nbsp;</td>
501745 </tr>
502746
606850 <td><a href="javadoc/com/thoughtworks/xstream/converters/extended/CharsetConverter.html">CharsetConverter</a></td>
607851 <td>java.nio.charset.Charset</td>
608852 <td class="example">&lt;charset&gt;US-ASCII&lt;/charset&gt;</td>
609 <td>Available under Java 1.4 or greater.</td>
853 <td>Available with Java 1.4 or greater.</td>
610854 <td>normal</td>
611855 </tr>
612856 <tr>
613857 <td><a href="javadoc/com/thoughtworks/xstream/converters/extended/PathConverter.html">PathConverter</a></td>
614858 <td>java.nio.file.Path</td>
615859 <td class="example">&lt;path&gt;../dir/file.txt&lt;/path&gt;</td>
616 <td>Available under Java 1.7 or greater.</td>
860 <td>Available with Java 7 or greater.</td>
617861 <td>normal</td>
618862 </tr>
619863
632876 <td><a href="javadoc/com/thoughtworks/xstream/converters/extended/JavaClassConverter.html">JavaClassConverter</a></td>
633877 <td>java.lang.Class</td>
634878 <td class="example">&lt;class&gt;com.foo.MyThing&lt;/class&gt;</td>
635 <td>This converter uses the ClassLoaderReference of the XStream insatance. Can be regisreted with
879 <td>This converter uses the ClassLoaderReference of the XStream instance. Can be registered with
636880 Mapper globally or locally to respect type aliases.</td>
637881 <td>normal</td>
638882 </tr>
645889 &nbsp;&nbsp;&lt;class&gt;com.foo.MyThing&lt;/class&gt;<br/>
646890 &lt;/field&gt;
647891 </td>
648 <td>This converter uses the ClassLoaderReference of the XStream insatance. Can be regisreted with
892 <td>This converter uses the ClassLoaderReference of the XStream instance. Can be registered with
649893 Mapper globally or locally to respect type aliases.</td>
650894 <td>normal</td>
651895 </tr>
752996
753997 <!-- .................................................................................................. -->
754998 <tr>
755 <td colspan="5" class="headerRow"><h1 id="java.awt.font">java.awt.font</h1></td>
999 <td colspan="5" class="headerRow"><h1 id="javax.activation">javax.activation</h1></td>
7561000 </tr>
7571001 <tr>
7581002 <th>Converter</th>
7711015 &nbsp;&nbsp;&lt;representationClass&gt;java.io.InputStream&lt;/representationClass&gt;<br/>
7721016 &lt;/activation-data-flavor&gt;
7731017 </td>
774 <td>Available under Java 1.6 or greater. Only automatically registered if runtime has AWT support.<br/>
1018 <td>Available with Java 6, 7 and 8. Requires module <em>java.activation</em> with Java 9 or greater.<br/>
7751019 <td>normal</td>
7761020 </tr>
7771021
8161060 &nbsp;&nbsp;&lt;readOnly&gt;false&lt;/readOnly&gt;<br/>
8171061 &lt;/auth-subject&gt;<br/>
8181062 </td>
819 <td>Available under Java 1.4 or greater. This converter does not serialize any credentials but only the principals.</td>
1063 <td>Available with Java 1.4 or greater. This converter does not serialize any credentials but only the principals.</td>
8201064 <td>normal</td>
8211065 </tr>
8221066
8351079 <td><a href="javadoc/com/thoughtworks/xstream/converters/extended/DurationConverter.html">DurationConverter</a></td>
8361080 <td>javax.xml.datatype.Duration</td>
8371081 <td class="example">&lt;duration&gt;PT1H2M&lt;/duration&gt;</td>
838 <td>Available under Java 1.5 or greater.</td>
1082 <td>Available with Java 1.5 or greater.</td>
8391083 <td>normal</td>
8401084 </tr>
8411085
8751119 <tr>
8761120 <td><a href="javadoc/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.html">ExternalizableConverter</a></td>
8771121 <td>java.io.Externalizable</td>
878 <td>The Converter is used for any JDK-externalizable types, if not handled by a specialized Converter.</td>
1122 <td>The Converter is used for any externalizable type, if not handled by a specialized Converter.</td>
8791123 <td>&nbsp;</td>
8801124 <td>low</td>
8811125 </tr>
8821126 <tr>
8831127 <td><a href="javadoc/com/thoughtworks/xstream/converters/reflection/LambdaConverter.html">LambdaConverter</a></td>
884 <td>For serializable and non-serializable lambda types. Noon-serialzable lambda instances will be mapped to null, since they
885 contain no information for recreation. Serializable lambda types have such info, but it is specific to compiler vendor and
886 occurrence in the code. Never assume that you can deserialize such an element when you use a different version of your code
887 or a different compiler.</td>
888 <td>&nbsp;</td>
889 <td>Only automatically registered for Java 8.</td>
1128 <td>For serializable lambda types.</td>
1129 <td>Non-serializable lambda instances will be mapped to null, since they contain no information for recreation. Serializable
1130 lambda types have such info, but it is specific to compiler vendor and occurrence in the code. Never assume that you can
1131 deserialize such an element when you use a different version of your code or a different compiler.</td>
1132 <td>Available with Java 8 or greater.</td>
8901133 <td>normal</td>
8911134 </tr>
8921135 <tr>
00 <html>
11 <!--
22 Copyright (C) 2005, 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
1717
1818 <p><a href="versioning.html">About XStream version numbers...</a></p>
1919
20 <h1 id="stable">Stable Version: <span class="version">1.4.9</span></h1>
20 <h1 id="stable">Stable Version: <span class="version">1.4.10</span></h1>
2121
2222 <ul>
23 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-distribution/1.4.9/xstream-distribution-1.4.9-bin.zip">Binary distribution:</a></b>
23 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-distribution/1.4.10/xstream-distribution-1.4.10-bin.zip">Binary distribution:</a></b>
2424 Contains the XStream jar files, the Hibernate and Benchmark modules and all the dependencies.</li>
25 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-distribution/1.4.9/xstream-distribution-1.4.9-src.zip">Source distribution:</a></b>
25 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-distribution/1.4.10/xstream-distribution-1.4.10-src.zip">Source distribution:</a></b>
2626 Contains the complete XStream project as if checked out from the Subversion version tag.</li>
27 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream/1.4.9/xstream-1.4.9.jar">XStream Core only:</a>
27 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream/1.4.10/xstream-1.4.10.jar">XStream Core only:</a>
2828 The xstream.jar only as it is downloaded automatically when it is referenced as Maven dependency.</b></li>
29 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-hibernate/1.4.9/xstream-hibernate-1.4.9.jar">XStream Hibernate module:</a></b>
29 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-hibernate/1.4.10/xstream-hibernate-1.4.10.jar">XStream Hibernate module:</a></b>
3030 The xstream-hibernate.jar as it is downloaded automatically when it is referenced as Maven dependency.</li>
31 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-benchmark/1.4.9/xstream-jmh-1.4.9.jar">XStream JMH module:</a></b>
32 The xstream-jmh.jar as it is downloaded automatically when it is referenced as Maven dependency.</li>
31 <li><b><a href="http://repo1.maven.org/maven2/com/thoughtworks/xstream/xstream-jmh/1.4.10/xstream-jmh-1.4.10-app.zip">XStream JMH module:</a></b>
32 The xstream-jmh-app.zip as standalone application with start scripts and all required libraries.</li>
3333 </ul>
3434
3535 <!--
4141 <li><a href="https://nexus.codehaus.org/content/groups/public/com/thoughtworks/xstream/xstream-distribution/1.5.0-SNAPSHOT/">Complete distributions</a></li>
4242 <li><a href="https://nexus.codehaus.org/content/groups/public/com/thoughtworks/xstream/xstream/1.5.0-SNAPSHOT/">XStream Core only</a></li>
4343 <li><a href="https://nexus.codehaus.org/content/groups/public/com/thoughtworks/xstream/xstream-hibernate/1.5.0-SNAPSHOT/">XStream Hibernate module</a></li>
44 <li><a href="https://nexus.codehaus.org/content/groups/public/com/thoughtworks/xstream/xstream-benchmark/1.5.0-SNAPSHOT/">XStream Benchmark module</a></li>
44 <li><a href="https://nexus.codehaus.org/content/groups/public/com/thoughtworks/xstream/xstream-jmh/1.5.0-SNAPSHOT/">XStream JMH module</a></li>
4545 </ul>
4646
4747 <h1 id="snapshot-1.4.x">Latest Snapshot 1.4.x BRANCH revision</h1>
8383 </li>
8484 <li>Other optional 3rd party dependencies:
8585 <ul>
86 <li><a href="http://downloads.sourceforge.net/joda-time/joda-time-1.6.zip">Joda Time</a> for optional ISO8601 date/time formats.</li>
86 <li><a href="http://downloads.sourceforge.net/joda-time/joda-time-1.6.zip">Joda Time</a> for optional ISO8601 date/time converters in JDK 1.7 or below.</li>
8787 <li><a href="http://downloads.sourceforge.net/cglib/cglib-nodep-2.2.jar">CGLIB</a> for optional support of some proxies generated with the CGLIB Enhancer.</li>
8888 <li><a href="http://repo.maven.apache.org/maven2/org/codehaus/jettison/jettison/1.2/jettison-1.2.jar">Jettison</a> for serialization and deserialization support with JSON. Note, that newer versions 1.3.x are no longer compatible with XStream.</li>
8989 <li><a href="http://repo.maven.apache.org/maven2/org/codehaus/jettison/jettison/1.0/jettison-1.0.jar">Jettison 1.0.1</a> for serialization and deserialization support with JSON in JDK 1.4. Note, that newer version 1.1 is not compatible with XStream.</li>
114114 <ul>
115115 <li>JMH dependencies:
116116 <ul>
117 <li><a href="http://repo.maven.apache.org/maven2/org/openjdk/jmh-core/1.11.1/jmh-core-1.11.1.jar">JMH Core 1.11.1</a>, for Java 6 or higher.</li>
118 <li><a href="http://repo.maven.apache.org/maven2/org/openjdk/jmh-generator-annprocess/1.11.1/jmh-generator-annprocess-1.11.1.jar">JMH Generator Annotation Processor 1.11.1</a>, for Java 6 or higher.</li>
117 <li><a href="http://repo.maven.apache.org/maven2/org/openjdk/jmh-core/1.19/jmh-core-1.19.jar">JMH Core 1.19</a>, for Java 6 or higher.</li>
118 <li><a href="http://repo.maven.apache.org/maven2/org/openjdk/jmh-generator-annprocess/1.19/jmh-generator-annprocess-1.19.jar">JMH Generator Annotation Processor 1.19</a>, for Java 6 or higher.</li>
119119 </ul>
120120 </li>
121121 </ul>
00 <html>
11 <!--
22 Copyright (C) 2005, 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
3030 <h1 id="Compatibility">Compatibility</h1>
3131
3232 <!-- ...................................................... -->
33 <h2 id="Compatibility_JDK">Which JDK is required to use XStream?</h2>
34 <p>1.4 or later.</p>
33 <h2 id="Compatibility_JRE">Which Java runtime is required to run XStream?</h2>
34 <p>XStream 1.4.x requires Java 1.4 or later. Note, that the XStream libraries contains class files targeting
35 different Java runtime versions or Java features. These classes are loaded by reflection and only used if XStream
36 is running on an appropriate runtime environment.</p>
37
38 <!-- ...................................................... -->
39 <h2 id="Compatibility_JDK">Which JDK is required to build XStream?</h2>
40 <p>XStream 1.4.x can be build still with JDK 1.4 (see BUILD.txt). However, to support the latest features it
41 requires currently a JDK of Java 8. Otherwise the resulting jar files will miss some classes not available on
42 earlier runtimes. Depending on the target environment this can be useful (e.g. for Android or GAE).</p>
3543
3644 <!-- ...................................................... -->
3745 <h2 id="Compatibility_Dependencies">Which dependencies are required to run XStream?</h2>
5159 <!-- ...................................................... -->
5260 <h2 id="Compatibility_enhanced_mode_jvm">Which JVMs allow XStream to operate in enhanced mode?</h2>
5361
54 <p>XStream will check since version 1.4.5 a working enhanced mode dynamically if it is available based on
55 undocumented internal Java runtime classes. This enhanced mode is known to be working on the Oracle/Sun, Apple, HP,
56 IBM and Blackdown 1.4 JVMs and onwards, for IcedTea 6 and onwards, for Hitachi, SAP and Diablo from 1.5 and
57 onwards, for BEA JRockit starting with R25.1.0. Generally it works for all modern Java runtimes based on OpenJDK.
58 Android basically supports the enhanced mode as well as the Google ApplicationEngine, but the latter's security
59 model limits the types that can be handled. Note, that an active SecurityManager might prevent the usage of the
60 enhanced mode also.</p>
62 <p>XStream checks since version 1.4.5 automatically for a working enhanced mode - based on undocumented internal
63 Java runtime classes. This enhanced mode is known to be working on the Oracle/Sun, Apple, HP, IBM and Blackdown
64 1.4 JVMs and onwards, for IcedTea 6 and onwards, for Hitachi, SAP and Diablo from 1.5 and onwards, for BEA JRockit
65 starting with R25.1.0. Generally it works for all modern Java runtimes based on OpenJDK. Android basically supports
66 the enhanced mode as well as the Google Application Engine, but the latter's security model limits the types that
67 can be handled. Note, that an active SecurityManager might prevent the usage of the enhanced mode also.</p>
6168
6269 <!-- ...................................................... -->
6370 <h2 id="Compatibility_enhanced_mode_advantage">What are the advantages of using enhanced mode over pure Java mode?</h2>
7885 <tr><td>Private fields</td><td>Yes</td><td>Yes</td></tr>
7986 <tr><td>Final fields</td><td>Yes &gt;= JDK 1.5</td><td>Yes</td></tr>
8087 </table>
88
89 <p>Note, that these undocumented features are still available with Java 9, since there is currently no public
90 functionality provided as replacement.</p>
8191
8292 <!-- ...................................................... -->
8393 <h2 id="Compatibility_XPP">Why is my application not able to create a XmlPullParser with the XppDriver since XStream 1.4?</h2>
98108 the JavaBeanConverter. Note, that Android provides an XML Pull Parser, therefore XStream can work without
99109 additional dependencies.</p>
100110
111 <p>XStream contains class files targeting different Java runtime versions. Depending on the target version of
112 Android, it is not possible to use the original XStream library directly, because it tries to convert all classes
113 of XStream to the Dalvik runtime. You might have to build a custom version of XStream (see BUILD.txt) with a JDK
114 that is equivalent to the Java level supported by the target version of Android.</p>
115
101116 <!-- ...................................................... -->
102117 <h2 id="Compatibility_GAE">Which limits exists for XStream in Google's Application Engine (GAE)?</h2>
103118
134149 for details. Actually XStream's converters try to check since version 1.4.6 any critical operation, before they
135150 claim to be able to handle a type. As consequence XStream can behave differently running under a SecurityManager.
136151 E.g. if the SecurityManager does not permit to create an instance for a derived class of ObjectOutputStream, the
137 SerializationConverter will not handle any type and the ReflecitonConverter will take over (as long it has proper
152 SerializationConverter will not handle any type and the ReflectionConverter will take over (as long it has proper
138153 rights for its own reflection-based operations).</p>
139154
140155 <!-- ...................................................... -->
171186 <a href="#Serialization_sort_fields">sort the fields</a> according XStream 1.2.2.</p>
172187
173188 <!-- ...................................................... -->
174 <h2 id="Compatibility_WebSphere_8">WebShere 8 can no longer use XStream 1.4.x?</h2>
189 <h2 id="Compatibility_WebSphere_8">WebSphere 8 can no longer use XStream 1.4.x?</h2>
175190
176191 <p>XStream has a long history to support types from recent JDKs without dropping backward compatibility. Therefore it contains class files targeting different JDKs.
177192 However, WebShpere scans by default all JAR files in its classpath for annotations to support CDI independent of the presence of a beans.xml file in META-INF. This
679694 <!-- ...................................................... -->
680695 <h2 id="Security_EventHandler">Why does XStream not convert an java.beans.EventHandler?</h2>
681696
682 <p>Since XStream verison 1.4.7 it does no longer handle an
697 <p>Since XStream version 1.4.7 it does no longer handle an
683698 <a href="http://docs.oracle.com/javase/7/docs/api/java/beans/EventHandler.html">EventHandler</a> automatically.
684 Such an instance can be used to initiate calls on arbitray instances at deserialization time e.g.
699 Such an instance can be used to initiate calls on arbitrary instances at deserialization time e.g.
685700 <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#start()">ProcessBuilder.start()</a>
686701 You can register a ReflectionConverter instance explicitly for the EventHandler if you need support for such
687702 instances.</p>
706721 </ul>
707722
708723 <!-- ...................................................... -->
709 <h2 id="Security_XXEVulnerability">Is XStream XXE vulnerable?</h2>
724 <h2 id="Security_VulnerabilityWarning">XStream suddenly emits a vulnerability warning!</h2>
725
726 <p>If the security framework has not been initialized, XStream will emit such a warning since version 1.4.10. You
727 use the <a href="security.html">security rules</a> to setup a white list of class types that will be processed.</p>
728
729 <p>For XStream 1.4.x you may call the setupDefaultSecurity method to initialize a XStream instance in the same way
730 as it will be done for XStream 1.5.x. This means also a compatibility preparation for XStream 1.5.x.</p>
731
732 <!-- ...................................................... -->
733 <h2 id="Security_XXEVulnerability">Is XStream XXE vulnerable (CVE-2016-3674)?</h2>
710734
711735 <p>XStream does not contain an own XML parser, therefore it depends on the parser selected with the
712736 <a href="javadoc/com/thoughtworks/xstream/io/HierarchicalStreamDriver.html">HierarchicalStreamDriver</a>
713737 if the current XStream instance is <a href="https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing">
714 XXE vulnerable</a> at deserialization time. However, XStream tries to deactivate the processing of external
738 XXE vulnerable</a> at deserialization time. However, XStream tries to deactivate the processing of external
715739 entities by default. Status for the different supported XML parsers:</p>
716740
717741 <table summary="Comparison of drivers regarding XEE vulnerability">
722746 <tr><td>Dom4JDriver</td><td>no</td><td>Driver turns off DOCTYPE processing to suppress handling of external
723747 entities with SAX reader in use.</td></tr>
724748 <tr><td>DomDriver</td><td>no, Java 6 or higher<br/>yes, Java 5</td><td>Driver turns off DOCTYPE processing with
725 Java 7 runtime or higher to suppress handling of external entities with SAX reader in use. Suppress external
749 Java 7 runtime or higher to suppress handling of external entities with SAX reader in use. Suppress external
726750 entities only for Java 6 or lower, fails for parameterized entities.</td></tr>
727751 <tr><td>JDomDriver</td><td>no</td><td>Driver turns off DOCTYPE processing to suppress handling of external
728752 entities with SAX reader in use.</td></tr>
731755 <tr><td>KXml2DomDriver</td><td>no</td><td>kXML2 parser does not support entities.</td></tr>
732756 <tr><td>KXml2Driver</td><td>no</td><td>kXML2 parser does not support entities.</td></tr>
733757 <tr><td>SjsxpDriver</td><td>no, Java 7 or higher<br/>yes, Java 6</td><td>Driver turns off support for external
734 entities for the internal StaX parser of the Sun JDK, but fails for parameter entities in a Java 6 runtime.</td></tr>
735 <tr><td>StandardStaxDriver</td><td>?</td><td>Driver tries to turns off support for external entities for
736 the internal StaX parser of the Java runtime. Save for Oracle JDK 7 or higher.</td></tr>
758 entities for the internal StaX parser of the Sun JDK, but fails for parameter entities in a Java 6 runtime.</td></tr>
759 <tr><td>StandardStaxDriver</td><td>?</td><td>Driver tries to turn off support for external entities for
760 the internal StaX parser of the Java runtime. Save for Oracle JDK 7 or higher.</td></tr>
737761 <tr><td>StaxDriver</td><td>?</td><td>Driver tries to turns off support for external entities for the
738 standard StaX parser. However, the finally used StAX implementation is defined externally (see JDK
762 standard StaX parser. However, the finally used StAX implementation is defined externally (see JDK
739763 documentation) and a test should be made on the target platform to ensure that the parser respects the setting.</td></tr>
740764 <tr><td>WstxDriver</td><td>no</td><td>Driver turns off support for external entities for the Woodstox StAX
741765 parser.</td></tr>
744768 </table>
745769
746770 <p class="highlight">Note: Only a HierarchicalStreamReader created with the HierarchicalStreamDriver is setup to
747 avoid the XXE vulnerability. If you create such driver instances on your own, it is your task to setup the XML
748 parser instance on your own.</p>
771 avoid the XXE vulnerability. If you create such driver instances on your own, it is also your task to setup the XML
772 parser instance properly.</p>
749773
750774 <!-- ****************************************************** -->
751775 <h1 id="Other_Products">Comparison to other products</h1>
774798 allowing objects to be serialized/deserialized concurrently (unless you enable the
775799 <a href="annotations-tutorial.html#AutoDetect">auto-detection</a> to process annotations on-the-fly). Actually the
776800 creation and initialization of XStream is quite expensive, therefore it is recommended to keep the XStream instance
777 itself. If you abolutely have to rely on annotation processing on the fly, you will have to use separate XStream
778 instances for each thread - either by using everytime a new instance or by a shared pool.</p>
801 itself. If you absolutely have to rely on annotation processing on the fly, you will have to use separate XStream
802 instances for each thread - either by using every time a new instance or by a shared pool.</p>
779803
780804 <!-- ...................................................... -->
781805 <h2 id="Scalability_Memory">How much memory does XStream consume?</h2>
831855 <!-- ...................................................... -->
832856 <h2 id="Uses_Generate_Code">Can XStream generate classes from XSD?</h2>
833857
834 <p>No. For this kind of work a data binding tool such as <a href="http://xmlbeans.apache.org">XMLBeans</a> is appropriate.</p>
858 <p>No. For this kind of work data binding tools such as JAXB or <a href="http://xmlbeans.apache.org">XMLBeans</a> are
859 appropriate.</p>
835860
836861 <!-- ...................................................... -->
837862 <h2 id="Uses_No_SAX_Reader">Why is there no SaxReader?</h2>
00 <html>
11 <!--
22 Copyright (C) 2005, 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2011, 2012, 2013, 2014, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2011, 2012, 2013, 2014, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
7272
7373 <h1 id="news">Latest News</h1>
7474
75 <h2 id="1.4.9"><b>March 15, 2016</b> XStream 1.4.9 released</h2>
75 <h2 id="1.4.10"><b>May 23, 2017</b> XStream 1.4.10 released</h2>
7676
77 <p>Maintenance release 1.4.9 of XStream with bug fixes eliminating XXE vulnerability and new benchmark module.</p>
77 <p class="highlight">This maintenance release addresses the security vulnerability <a href="CVE-2017-7957.html">
78 CVE-2017-7957</a>, a possibility for a denial of service attack. All previous versions are affected.</p>
7879
79 <p>Several parsers were vulnerable by processing external entities (XXE vulnerability). This has been turned off as far as possible.</p>
80 <p>XStream supports now the java.time.* package of Java 8 with various new converters.</p>
8081
81 <p>The home-grown benchmark module has been replaced using an implementation based on JMH.</p>
82 <p>Emit warning message if XStream instance is still running with an uninitialized security framework.</p>
8283
83 <p>XStream supports now java.nio.Path with a specialized converter.</p>
84 <p>View the complete <a href="changes.html">change log</a> and <a href="download.html">download</a>.</p>
8485
8586 <p>Note, the next major release 1.5 will require Java 7.</p>
8687
00 <html>
11 <!--
22 Copyright (C) 2005, 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
1515
1616 <body>
1717
18 <h2 id="1.4.10"><b>May 23, 2017</b> XStream 1.4.10 released</h2>
19
20 <p class="highlight">This maintenance release addresses the security vulnerability <a href="CVE-2017-7957.html">
21 CVE-2017-7957</a>, a possibility for a denial of service attack. All previous versions are affected.</p>
22
23 <p>XStream supports now the java.time.* package of Java 8 with various new converters.</p>
24
25 <p>Emit warning message if XStream instance is still running with an uninitialized security framework.</p>
26
27 <p>View the complete <a href="changes.html">change log</a> and <a href="download.html">download</a>.</p>
28
29 <p>Note, the next major release 1.5 will require Java 7.</p>
30
1831 <h2 id="1.4.9"><b>March 15, 2016</b> XStream 1.4.9 released</h2>
1932
20 <p>Maintenance release 1.4.9 of XStream with bug fixes eliminating XXE vulnerability and new benchmark module.</p>
21
22 <p>Several parsers were vulnerable by processing external entities (XXE vulnerability). This has been turned off as far as possible.</p>
33 <p>Maintenance release 1.4.9 of XStream with bug fixes eliminating <a href="CVE-2016-3674.html">XXE
34 vulnerability</a> and new benchmark module.</p>
35
36 <p class="highlight"><a href="CVE-2016-3674.html">CVE-2016-3674</a>: Several parsers were vulnerable by
37 processing external entities (XXE vulnerability). This has been turned off as far as possible.</p>
2338
2439 <p>The home-grown benchmark module has been replaced using an implementation based on JMH.</p>
2540
5671
5772 <h2 id="1.4.7"><b>February 8, 2014</b> XStream 1.4.7 released</h2>
5873
59 <p class="highlight">This maintenance release addresses mainly the security vulnerability CVE-2013-7285, an
60 arbitrary execution of commands when unmarshalling. All previous versions are affected running at least Java 5.</p>
74 <p class="highlight">This maintenance release addresses mainly the security vulnerability
75 <a href="CVE-2013-7285.html">CVE-2013-7285</a>, an arbitrary execution of commands when unmarshalling. All
76 previous versions are affected running at least Java 5.</p>
6177
6278 <p>XStream contains now a security framework to fine-control the unmarshalled types.</p>
6379
00 <html>
11 <!--
2 Copyright (C) 2014, 2015 XStream committers.
2 Copyright (C) 2014, 2015, 2017 XStream committers.
33 All rights reserved.
44
55 The software in this package is published under the terms of the BSD
1717 XML, and XML to Java objects. As a result, it is possible to create an instance of XStream with the default
1818 constructor, call a method to convert an object into XML, then call another method to turn the XML back into an
1919 equivalent Java object. By design, there are few limits to the type of objects XStream can handle.</p>
20
21 <p>This flexibility comes at a price. XStream applies various techniques under the hood to ensure it is able to
20
21 <p class=highlight>Note: XStream supports other data formats than XML, e.g. JSON. Those formats can be used for
22 the same attacks.</p>
23
24 <p>This flexibility comes at a price. XStream applies various techniques under the hood to ensure it is able to
2225 handle all types of objects. This includes using undocumented Java features and reflection. The XML generated by
2326 XStream includes all information required to build objects of almost any type. This introduces a potential
2427 security problem.</p>
25
26 <p>The XML provided to XStream for conversion to a Java object can be manipulated to inject objects into the
27 unmarshalled object graph, which were not present at marshalling time. An attacker could exploit this to execute
28 arbitrary code or shell commands in the context of the server running the XStream process. This issue is
29 identified by CVE-2013-7285.</p>
30
31 <p>Note that the XML data could be manipulated on different levels. For example, manipulating values on existing
28
29 <p>The provided XML data is used by XStream to unmarshal Java objects. This data can be manipulated by injecting
30 the XML representation of other objects, that were not present at marshalling time. An attacker could take
31 advantage of this to execute arbitrary code or shell commands in the context of the server running the XStream
32 process. A concrete case is described in <a href="CVE-2013-7285.html">CVE-2013-7285</a>.</p>
33
34 <p>Note that the XML data can be manipulated on different levels. For example, manipulating values on existing
3235 objects (such as a price value), or breaking the format and causing the XML parser to fail. The latter case will
3336 raise an exception, but the former case must be handled by validity checks in any application which processes
34 user-supplied XML. The worst case scenario is injection of arbitrary code or shell commands, as noted above.</p>
37 user-supplied XML. A worst case scenario is the injection of arbitrary code or shell commands, as noted above.
38 Even worse, <a href="CVE-2017-7957.html">CVE-2017-7957</a> describes a case to crash the Java Virtual Machine
39 causing a Denial of Service.</p>
3540
3641 <h2 id="external">External Security</h2>
3742
4651 <h2 id="implicit">Implicit Security</h2>
4752
4853 <p>As explained above, it is possible to inject other object instances if an attacker is able to define the data
49 used to deserialize the Java objects (typically XML, but XStream supports other formats like JSON). A known
50 exploit can be created with the help of the Java runtime library using the Java Bean
51 <a href="http://docs.oracle.com/javase/7/docs/api/java/beans/EventHandler.html">EventHandler</a>. As an instance
52 for the <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/InvocationHandler.html">InvocationHandler</a>
53 of a dynamic proxy, it can be used to install a redirect for an arbitrary call to the original object to the method
54 of a completely different instance of an embedded object of the EventHandler itself.</p>
55         
56 <p>This scenario can be used perfectly to replace/inject a dynamic proxy with such an EventHandler at any location
57 in the XML where its parent expects an object of such an interface's type or a simple object instance (any list
58 element will suffice). The usage of a ProcessBuilder as an embedded element, coupled with the redirection of any
59 call to the ProcessBuilder's <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#start()">start()</a>
60 method allows an attacker to call shell commands. Knowing how to define such an attack is the only prerequisite.</p>
61         
54 used to deserialize the Java objects. E.g. a known exploit can be created with the help of the Java runtime
55 library using the Java Bean <a href="http://docs.oracle.com/javase/7/docs/api/java/beans/EventHandler.html">EventHandler</a>
56 as described in <a href="CVE-2013-7285.html">CVE-2013-7285</a>. This scenario can be used perfectly to
57 replace/inject a dynamic proxy with such an EventHandler at any location in the XML where its parent expects an
58 object of such an interface's type or a simple object instance (any list element will suffice). The usage of a
59 ProcessBuilder as an embedded element, coupled with the redirection of any call to the ProcessBuilder's
60 <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#start()">start()</a> method allows
61 an attacker to call shell commands. Knowing how to define such an attack is the only prerequisite.</p>
62         
63 <p>More scenarios have been identified for types that are already delivered with the Java runtime. Looking at
64 well-known and commonly used Java libraries libraries such as ASM, CGLIB, or Groovy, the possibility for more
65 exploits is very high.</p>
66
67 <p class="hightlight">Therefore creates a black list for special classes only a scenario for a false security,
68 because no-one can assure, that no other scenario arise. A better approach is white listing i.e. the allowed class
69 types are setup explicitly. This will be the default for XStream 1.5.x.</p>
70
6271 <p>Starting with XStream 1.4.7, an instance of the EventHandler is no longer handled by default. You have to
6372 explicitly register a ReflectionConverter for the EventHandler type, if your application has the requirement to
64 persist such an object. However, you still have to take special care regarding the location of the persisted data,
65 and how your application can ensure its integrity.</p>
66         
67 <p class=highlight>Note: this vulnerability is not even a special problem of XStream. XML being deserialized by
73 persist such an object. Starting with XStream 1.4.10 the list of revoked types is enhanced by all types of the
74 java.crypto package and any inner class named LazyIterator. On top you still have to take special care regarding
75 the location of the persisted data, and how your application can ensure its integrity.</p>
76         
77 <p class=highlight>Note: This vulnerability is not even a special problem of XStream. XML being deserialized by
6878 XStream acts here like a script, and the scenario above can be created with any script that is executed within a
6979 Java runtime (e.g. using its JavaScript interpreter) if someone is able to manipulate it externally. The key
7080 message for application developers is that deserializing arbitrary user-supplied content is a dangerous proposition
71 in all cases.</p>
81 in all cases. The best approach to prevent such an attach is a <a href="#example">white list</a>, i.e. the
82 deserialization mechanism should only allow explicit types.</p>
7283
7384 <h2 id="explicit">Explicit Security</h2>
74
75 <p>While XStream implicitly avoids the vulnerability scenario with the EventHandler class, there might be other
76 combinations with types from well-known and commonly-used Java libraries such as ASM, CGLIB, Groovy, or even in
77 the Java runtime, that are currently simply unknown.</p>
7885     
7986 <p>Starting with XStream 1.4.7, it is possible to define <a href="#framework">permissions</a> for types, to check
80 the type of an object that should be unmarshalled. Those permissions can be used to allow or deny types explicitly.
81 With these permissions it is at least not possible to inject unexpected types into an object graph. Any application
82 that deserializes data from an external source should at least use this feature to limit the danger of arbitrary
83 command execution.</p>
87 the type of an object that should be unmarshalled. Those permissions can be used to allow or deny types explicitly
88 With these permissions it is at least not possible to inject unexpected types into an object graph. The security
89 framework supports the setup of a black or white listing scenario. Any application should use this feature to
90 limit the danger of arbitrary command execution if it deserializes data from an external source.</p>
91
92 <p>XStream itself sets up a black list by default, i.e. it blocks all currently known critical classes of the Java
93 runtime. Main reason for the black list is compatibility, because otherwise newer versions of XStream 1.4.x can no
94 longer be used as drop-in replacement. Unfortunately this provides a false sense of security. Every XStream
95 client should therefore switch to a white listing on its own as soon as possible. XStream itself will use white
96 listing as default starting with 1.5.x and only clients that have also changed their setup will be able to use this
97 newer version again as drop-in replacement.</p>
8498         
8599 <p class=highlight>Apart from value manipulations, this implementation still allows the injection of allowed
86100 objects at wrong locations, e.g. inserting an integer into a list of strings.</p>
91105 <h2 id="validation">XML Validation</h2>
92106
93107 <p>XML itself supports input validation using a schema and a validating parser. With XStream, you can use e.g. a
94 StAX parser for validation, but it will take some effort to ensure that the XML read and written by XStream matches
95 the schema in first place. Typically you will have to write some custom converters, but it can be worth the effort
96 depending on the use case.</p>
108 DOM parser for validation, but it will take some effort to ensure that the XML read and written by XStream matches
109 the schema in first place, because XStream uses additionally own attributes. Typically you will have to write some
110 custom converters, but it can be worth the effort depending on the use case.</p>
97111
98112 <h1 id="framework">Security Framework</h1>
99113
201215 </tr>
202216 <tr>
203217 <td><a href="javadoc/com/thoughtworks/xstream/security/PrimitiveTypePermission.html">PrimitiveTypePermission</a></td>
204 <td>Allow any primitive type and its boxed counterpart (incl void). You may use the PRIMITIVES instance directly.</td>
218 <td>Allow any primitive type and its boxed counterpart (excluding void). You may use the PRIMITIVES instance
219 directly.</td>
205220 <td>&nbsp;</td>
206221 <td>no</td>
207222 </tr>
231246 </tr>
232247 </table>
233248
234 <h2 id="example">Example Code</h2>
249 <h2 id="example">Example Code White Listing</h2>
235250
236251 <p>XStream uses the AnyTypePermission by default, i.e. any type is accepted. You have to clear out this default
237252 and register your own permissions to activate the security framework (the Blog type is from the
00 <html>
11 <!--
22 Copyright (C) 2005, 2006 Joe Walnes.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016 XStream committers.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017 XStream committers.
44 All rights reserved.
55
66 The software in this package is published under the terms of the BSD
120120 <li>David Jorm</li>
121121 <li>Geoff Groos</li>
122122 <li>Aaron Johnson</li>
123 <li>Stefan Cordes</li>
124 <li>Carsten Hammer</li>
125 <li>Matej Cimbora</li>
123126 </ul>
124127
125128 <p>Please direct all correspondence about XStream to the <a href="mailing-lists.html">mailing list</a>
4040 <name>Javadoc</name>
4141 <link title="XStream Core">javadoc/index.html</link>
4242 <link title="Hibernate Extensions">hibernate-javadoc/index.html</link>
43 <link title="JMH Module">benchmark-jmh/index.html</link>
43 <link title="JMH Module">jmh-javadoc/index.html</link>
44 </section>
45 <section>
46 <name>Vulnerabilities</name>
47 <page>CVE-2017-7957.html</page>
48 <page>CVE-2016-3674.html</page>
49 <page>CVE-2013-7285.html</page>
4450 </section>
4551 <section>
4652 <name>Tutorials</name>
00 <?xml version="1.0"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
11 <!--
2 Copyright (C) 2011, 2012, 2013, 2015 XStream committers.
2 Copyright (C) 2011, 2012, 2013, 2015, 2017 XStream committers.
33 All rights reserved.
44
55 The software in this package is published under the terms of the BSD
1212 <parent>
1313 <groupId>com.thoughtworks.xstream</groupId>
1414 <artifactId>xstream-parent</artifactId>
15 <version>1.4.9</version>
15 <version>1.4.10</version>
1616 </parent>
1717 <artifactId>xstream-hibernate</artifactId>
1818 <packaging>jar</packaging>
2323
2424 <profiles>
2525 <profile>
26 <id>jdk18-ge</id>
26 <id>jdk19-ge</id>
2727 <activation>
28 <jdk>[1.8,)</jdk>
28 <jdk>[9,)</jdk>
29 </activation>
30 <properties>
31 <surefire.argline>--permit-illegal-access</surefire.argline>
32 </properties>
33 </profile>
34 <profile>
35 <id>jdk18</id>
36 <activation>
37 <jdk>1.8</jdk>
2938 </activation>
3039 <build>
3140 <plugins>
00 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
11 <!--
2 Copyright (C) 2015 XStream committers.
2 Copyright (C) 2015, 2017 XStream committers.
33 All rights reserved.
44
55 The software in this package is published under the terms of the BSD
1212 <parent>
1313 <groupId>com.thoughtworks.xstream</groupId>
1414 <artifactId>xstream-parent</artifactId>
15 <version>1.4.9</version>
15 <version>1.4.10</version>
1616 </parent>
1717 <artifactId>xstream-jmh</artifactId>
1818 <packaging>jar</packaging>
2121
2222 <profiles>
2323 <profile>
24 <id>jdk18-ge</id>
24 <id>jdk19-ge</id>
2525 <activation>
26 <jdk>[1.8,)</jdk>
26 <jdk>[9,)</jdk>
27 </activation>
28 <build>
29 <plugins>
30 <plugin>
31 <groupId>org.apache.maven.plugins</groupId>
32 <artifactId>maven-compiler-plugin</artifactId>
33 <configuration>
34 <fork>true</fork>
35 <compilerArgs>
36 <arg>-J--add-modules</arg>
37 <arg>-Jjava.xml.ws.annotation</arg>
38 </compilerArgs>
39 </configuration>
40 </plugin>
41 </plugins>
42 </build>
43 </profile>
44 <profile>
45 <id>jdk18</id>
46 <activation>
47 <jdk>1.8</jdk>
2748 </activation>
2849 <build>
2950 <plugins>
4545
4646 @REM * Set options
4747 @REM *************
48 set JAVA_OPTS=%JAVA_OPTS% -Xmx1024m
48 set JAVA_OPTS=%JAVA_OPTS% -Xmx2048m -Xss4m
4949
5050
5151 @REM * Main class
4242
4343 # * Set options
4444 # *************
45 JAVA_OPTS="$JAVA_OPTS -Xmx1024m"
45 JAVA_OPTS="$JAVA_OPTS -Xmx2048m -Xss4m"
4646
4747 # * Main class
4848 # ************
00 /*
1 * Copyright (C) 2015 XStream Committers.
1 * Copyright (C) 2015, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
3737 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
3838 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
3939 import com.thoughtworks.xstream.io.xml.Xpp3Driver;
40 import com.thoughtworks.xstream.security.ArrayTypePermission;
41 import com.thoughtworks.xstream.security.NoTypePermission;
42 import com.thoughtworks.xstream.security.PrimitiveTypePermission;
4043
4144
4245 /**
227230 @Setup(Level.Trial)
228231 public void setUp(final BenchmarkParams params) {
229232 xstream = new XStream(new Xpp3Driver());
230 xstream.allowTypes(new Class[]{Model.class});
233 xstream.addPermission(NoTypePermission.NONE);
234 xstream.addPermission(ArrayTypePermission.ARRAYS);
235 xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
236 xstream.allowTypes(new Class[]{Model.class, String.class, BigInteger.class, UUID.class});
231237 final String benchmark = params.getBenchmark();
232238 final String name = benchmark.substring(ConverterTypeBenchmark.class.getName().length() + 1);
233239 if (name.equals("reflection")) {
00 /*
1 * Copyright (C) 2015 XStream Committers.
1 * Copyright (C) 2015, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
3131 import com.thoughtworks.xstream.io.naming.NameCoder;
3232 import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
3333 import com.thoughtworks.xstream.io.xml.Xpp3Driver;
34 import com.thoughtworks.xstream.security.ArrayTypePermission;
35 import com.thoughtworks.xstream.security.NoTypePermission;
36 import com.thoughtworks.xstream.security.PrimitiveTypePermission;
3437
3538
3639 /**
265268 throw new IllegalStateException("Unsupported benchmark type: " + benchmark);
266269 }
267270 xstream = new XStream(new Xpp3Driver(nameCoder));
268 xstream.allowTypes(new Class[]{_1._2._3._4._5.Unfriendly.class});
271 xstream.addPermission(NoTypePermission.NONE);
272 xstream.addPermission(ArrayTypePermission.ARRAYS);
273 xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
274 xstream.allowTypes(new Class[]{_1._2._3._4._5.Unfriendly.class, String.class});
269275 if (nameCoder.getClass() == NoNameCoder.class) {
270276 xstream.alias(_1._2._3._4._5.Unfriendly.class.getName().replace('$', '\u00b7'),
271277 _1._2._3._4._5.Unfriendly.class);
00 /*
1 * Copyright (C) 2015 XStream Committers.
1 * Copyright (C) 2015, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
4848 import com.thoughtworks.xstream.io.xml.WstxDriver;
4949 import com.thoughtworks.xstream.io.xml.XomDriver;
5050 import com.thoughtworks.xstream.io.xml.Xpp3Driver;
51 import com.thoughtworks.xstream.security.ArrayTypePermission;
52 import com.thoughtworks.xstream.security.NoTypePermission;
53 import com.thoughtworks.xstream.security.PrimitiveTypePermission;
5154
5255
5356 /**
114117 * @since 1.4.9
115118 */
116119 DOM4J(new Dom4JDriver() { // XML writer of DOM4J fails
120 @Override
117121 public HierarchicalStreamWriter createWriter(final Writer out) {
118122 return new PrettyPrintWriter(out, getNameCoder());
119123 }
223227 * @since 1.4.9
224228 */
225229 NestedElements {
226 private static final int DEPTH = 500;
230 private static final int DEPTH = 1000;
227231 private List<Integer> list;
228232
229233 @Override
314318 @Setup
315319 public void init() {
316320 xstream = new XStream();
321 xstream.addPermission(NoTypePermission.NONE);
322 xstream.addPermission(ArrayTypePermission.ARRAYS);
323 xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
324 xstream.allowTypes(new Class[]{List.class, String.class});
317325 xstream.setMode(XStream.NO_REFERENCES);
318326 driver = driverFactory.getDriver();
319327 }
00 /*
1 * Copyright (C) 2015 XStream Committers.
1 * Copyright (C) 2015, 2017 XStream Committers.
22 * All rights reserved.
33 *
44 * The software in this package is published under the terms of the BSD
3838 import com.thoughtworks.xstream.io.xml.CompactWriter;
3939 import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
4040 import com.thoughtworks.xstream.io.xml.Xpp3Driver;
41 import com.thoughtworks.xstream.security.ArrayTypePermission;
42 import com.thoughtworks.xstream.security.NoTypePermission;
4143
4244
4345 /**
255257 throw new IllegalStateException("Unsupported benchmark type: " + benchmark);
256258 }
257259 xstream = new XStream(new Xpp3Driver());
260 xstream.addPermission(NoTypePermission.NONE);
261 xstream.addPermission(ArrayTypePermission.ARRAYS);
262 xstream.allowTypes(new Class[] {String.class});
258263 xstream.registerConverter(converter);
259264 }
260265
00 Benchmark Mode Cnt Score Error Units
1 ConverterTypeBenchmark.custom avgt 16 11276718.384 ± 660395.171 ns/op
2 ConverterTypeBenchmark.javaBean avgt 16 28878706.293 ± 2718745.446 ns/op
3 ConverterTypeBenchmark.reflection avgt 16 40085786.696 ± 2712102.798 ns/op
1 ConverterTypeBenchmark.custom avgt 16 9827295.423 ± 216353.603 ns/op
2 ConverterTypeBenchmark.javaBean avgt 16 18939434.561 ± 196809.719 ns/op
3 ConverterTypeBenchmark.reflection avgt 16 19450925.166 ± 181312.751 ns/op
00 Benchmark Mode Cnt Score Error Units
1 NameCoderBenchmark.cachedEscapedUnderscoreCoding avgt 25 7867671.962 ± 513789.786 ns/op
2 NameCoderBenchmark.dollarCoding avgt 25 7767196.902 ± 594898.960 ns/op
3 NameCoderBenchmark.escapedUnderscoreCoding avgt 25 9894393.289 ± 556251.884 ns/op
4 NameCoderBenchmark.noCoding avgt 25 7299475.975 ± 363895.593 ns/op
5 NameCoderBenchmark.xmlFriendlyCoding avgt 25 8635501.208 ± 703145.664 ns/op
1 NameCoderBenchmark.cachedEscapedUnderscoreCoding avgt 25 4531410.494 ± 128534.700 ns/op
2 NameCoderBenchmark.dollarCoding avgt 25 4635671.256 ± 154209.189 ns/op
3 NameCoderBenchmark.escapedUnderscoreCoding avgt 25 5974244.102 ± 68996.714 ns/op
4 NameCoderBenchmark.noCoding avgt 25 4057270.642 ± 50166.734 ns/op
5 NameCoderBenchmark.xmlFriendlyCoding avgt 25 4953594.706 ± 98502.894 ns/op
00 Benchmark (driverFactory) Mode Cnt Score Error Units
1 ParserBenchmark.parseBigText Xpp3 avgt 15 2109341.076 ± 19369.901 ns/op
2 ParserBenchmark.parseBigText kXML2 avgt 15 3391204.266 ± 31040.727 ns/op
3 ParserBenchmark.parseBigText JDKStax avgt 15 7366387.272 ± 132117.523 ns/op
4 ParserBenchmark.parseBigText Woodstox avgt 15 1884858.525 ± 29364.633 ns/op
5 ParserBenchmark.parseBigText BEAStax avgt 15 3108517.699 ± 44905.395 ns/op
6 ParserBenchmark.parseBigText DOM avgt 15 10037380.795 ± 402305.418 ns/op
7 ParserBenchmark.parseBigText DOM4J avgt 15 7816280.084 ± 244809.864 ns/op
8 ParserBenchmark.parseBigText JDom avgt 15 6368317.636 ± 180516.662 ns/op
9 ParserBenchmark.parseBigText JDom2 avgt 15 5767640.105 ± 56112.801 ns/op
10 ParserBenchmark.parseBigText Xom avgt 15 7950778.533 ± 74710.412 ns/op
11 ParserBenchmark.parseBigText Binary avgt 15 1144243.750 ± 18924.227 ns/op
12 ParserBenchmark.parseBigText Jettison avgt 15 3002547.220 ± 39676.507 ns/op
13 ParserBenchmark.parseManyChildren Xpp3 avgt 15 1309607.210 ± 18539.487 ns/op
14 ParserBenchmark.parseManyChildren kXML2 avgt 15 1514514.680 ± 30170.502 ns/op
15 ParserBenchmark.parseManyChildren JDKStax avgt 15 1334398.501 ± 19324.267 ns/op
16 ParserBenchmark.parseManyChildren Woodstox avgt 15 1240767.393 ± 9572.885 ns/op
17 ParserBenchmark.parseManyChildren BEAStax avgt 15 1310406.961 ± 15256.069 ns/op
18 ParserBenchmark.parseManyChildren DOM avgt 15 54234293.351 ± 400240.973 ns/op
19 ParserBenchmark.parseManyChildren DOM4J avgt 15 92998322.952 ± 741924.537 ns/op
20 ParserBenchmark.parseManyChildren JDom avgt 15 7910979.223 ± 101267.507 ns/op
21 ParserBenchmark.parseManyChildren JDom2 avgt 15 10570210.653 ± 590365.314 ns/op
22 ParserBenchmark.parseManyChildren Xom avgt 15 38704485.310 ± 485342.779 ns/op
23 ParserBenchmark.parseManyChildren Binary avgt 15 1062031.901 ± 16391.974 ns/op
24 ParserBenchmark.parseManyChildren Jettison avgt 15 1159238.555 ± 18479.230 ns/op
25 ParserBenchmark.parseNestedElements Xpp3 avgt 15 3301732.767 ± 94076.135 ns/op
26 ParserBenchmark.parseNestedElements kXML2 avgt 15 8105934.241 ± 103517.648 ns/op
27 ParserBenchmark.parseNestedElements JDKStax avgt 15 688229.709 ± 2873.173 ns/op
28 ParserBenchmark.parseNestedElements Woodstox avgt 15 650470.623 ± 7920.722 ns/op
29 ParserBenchmark.parseNestedElements BEAStax avgt 15 669111.164 ± 10692.266 ns/op
30 ParserBenchmark.parseNestedElements DOM avgt 15 1917332.056 ± 31699.337 ns/op
31 ParserBenchmark.parseNestedElements DOM4J avgt 15 2108075.646 ± 98269.758 ns/op
32 ParserBenchmark.parseNestedElements JDom avgt 15 3862796.027 ± 74010.953 ns/op
33 ParserBenchmark.parseNestedElements JDom2 avgt 15 2980906.727 ± 43315.160 ns/op
34 ParserBenchmark.parseNestedElements Xom avgt 15 2471019.743 ± 45829.109 ns/op
35 ParserBenchmark.parseNestedElements Binary avgt 15 496839.565 ± 7180.978 ns/op
36 ParserBenchmark.parseNestedElements Jettison avgt 15 682182.733 ± 9614.467 ns/op
1 ParserBenchmark.parseBigText Xpp3 avgt 15 2084516.475 ± 18357.160 ns/op
2 ParserBenchmark.parseBigText kXML2 avgt 15 3539743.111 ± 40107.429 ns/op
3 ParserBenchmark.parseBigText JDKStax avgt 15 7314997.951 ± 47929.496 ns/op
4 ParserBenchmark.parseBigText Woodstox avgt 15 1888835.931 ± 22134.786 ns/op
5 ParserBenchmark.parseBigText BEAStax avgt 15 2658801.705 ± 18343.532 ns/op
6 ParserBenchmark.parseBigText DOM avgt 15 9781342.261 ± 56171.129 ns/op
7 ParserBenchmark.parseBigText DOM4J avgt 15 7737425.182 ± 60332.494 ns/op
8 ParserBenchmark.parseBigText JDom avgt 15 6303281.491 ± 38500.209 ns/op
9 ParserBenchmark.parseBigText JDom2 avgt 15 5912161.208 ± 60666.941 ns/op
10 ParserBenchmark.parseBigText Xom avgt 15 8086930.673 ± 84884.910 ns/op
11 ParserBenchmark.parseBigText Binary avgt 15 1149384.865 ± 18245.639 ns/op
12 ParserBenchmark.parseBigText Jettison avgt 15 2983598.441 ± 51508.673 ns/op
13 ParserBenchmark.parseManyChildren Xpp3 avgt 15 693019.370 ± 3982.017 ns/op
14 ParserBenchmark.parseManyChildren kXML2 avgt 15 837861.515 ± 5737.910 ns/op
15 ParserBenchmark.parseManyChildren JDKStax avgt 15 727323.621 ± 12819.229 ns/op
16 ParserBenchmark.parseManyChildren Woodstox avgt 15 622817.191 ± 8434.515 ns/op
17 ParserBenchmark.parseManyChildren BEAStax avgt 15 716108.170 ± 3738.679 ns/op
18 ParserBenchmark.parseManyChildren DOM avgt 15 52632217.909 ± 820752.640 ns/op
19 ParserBenchmark.parseManyChildren DOM4J avgt 15 93587705.473 ± 576597.653 ns/op
20 ParserBenchmark.parseManyChildren JDom avgt 15 7066427.706 ± 67403.369 ns/op
21 ParserBenchmark.parseManyChildren JDom2 avgt 15 9159926.646 ± 91300.562 ns/op
22 ParserBenchmark.parseManyChildren Xom avgt 15 36550127.033 ± 85933.816 ns/op
23 ParserBenchmark.parseManyChildren Binary avgt 15 438657.801 ± 4495.124 ns/op
24 ParserBenchmark.parseManyChildren Jettison avgt 15 564172.475 ± 4212.309 ns/op
25 ParserBenchmark.parseNestedElements Xpp3 avgt 15 12426115.039 ± 129574.773 ns/op
26 ParserBenchmark.parseNestedElements kXML2 avgt 15 34291308.328 ± 168044.895 ns/op
27 ParserBenchmark.parseNestedElements JDKStax avgt 15 594349.622 ± 4103.535 ns/op
28 ParserBenchmark.parseNestedElements Woodstox avgt 15 645986.465 ± 7631.906 ns/op
29 ParserBenchmark.parseNestedElements BEAStax avgt 15 579754.753 ± 2345.131 ns/op
30 ParserBenchmark.parseNestedElements DOM avgt 15 5103544.581 ± 43300.158 ns/op
31 ParserBenchmark.parseNestedElements DOM4J avgt 15 5832065.181 ± 58233.910 ns/op
32 ParserBenchmark.parseNestedElements JDom avgt 15 14168656.571 ± 199034.717 ns/op
33 ParserBenchmark.parseNestedElements JDom2 avgt 15 10786607.592 ± 136001.568 ns/op
34 ParserBenchmark.parseNestedElements Xom avgt 15 7799715.857 ± 102903.181 ns/op
35 ParserBenchmark.parseNestedElements Binary avgt 15 290646.503 ± 1769.476 ns/op
36 ParserBenchmark.parseNestedElements Jettison avgt 15 632427.902 ± 4369.921 ns/op
00 Benchmark Mode Cnt Score Error Units
1 StringConverterBenchmark.intern avgt 16 23060982.052 ± 1760952.641 ns/op
2 StringConverterBenchmark.limitedConcurrentMap avgt 16 21796001.298 ± 2092865.246 ns/op
3 StringConverterBenchmark.limitedSynchronizedWeakCache avgt 16 21838410.801 ± 981634.755 ns/op
4 StringConverterBenchmark.nonCaching avgt 16 19626160.696 ± 1456804.584 ns/op
5 StringConverterBenchmark.unlimitedConcurrentMap avgt 16 21378299.003 ± 1913288.565 ns/op
6 StringConverterBenchmark.unlimitedSynchronizedWeakCache avgt 16 22011251.691 ± 1713892.622 ns/op
1 StringConverterBenchmark.intern avgt 16 12650471.288 ± 165474.187 ns/op
2 StringConverterBenchmark.limitedConcurrentMap avgt 16 12072029.228 ± 175936.759 ns/op
3 StringConverterBenchmark.limitedSynchronizedWeakCache avgt 16 12748751.700 ± 205485.179 ns/op
4 StringConverterBenchmark.nonCaching avgt 16 9755034.512 ± 210645.214 ns/op
5 StringConverterBenchmark.unlimitedConcurrentMap avgt 16 11431423.547 ± 176483.052 ns/op
6 StringConverterBenchmark.unlimitedSynchronizedWeakCache avgt 16 11178461.611 ± 177404.016 ns/op