From 0eb58db1b7e07a6d277d86b3fcb666a372a17d33 Mon Sep 17 00:00:00 2001 From: joehni Date: Sun, 27 Nov 2022 00:10:37 +0100 Subject: [PATCH] Add converter for AtomicBoolean. Closes #308 and #309. --- xstream-distribution/src/content/changes.html | 19 ++++++ .../src/content/converters.html | 23 ++++++- xstream/pom.xml | 2 + .../com/thoughtworks/xstream/XStream.java | 4 ++ .../extended/AtomicBooleanConverter.java | 66 +++++++++++++++++++ .../acceptance/Concurrent15TypesTest.java | 29 +++++--- 6 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicBooleanConverter.java diff --git a/xstream-distribution/src/content/changes.html b/xstream-distribution/src/content/changes.html index b5e83bc8e..e868edb75 100644 --- a/xstream-distribution/src/content/changes.html +++ b/xstream-distribution/src/content/changes.html @@ -33,12 +33,31 @@

Upcoming 1.4.x maintenance release

Not yet released.

+

Major changes

+ + +

Minor changes

+

Stream compatibility

+ + + +

API changes

+ + +

1.4.19

Released January 29, 2022.

diff --git a/xstream-distribution/src/content/converters.html b/xstream-distribution/src/content/converters.html index d88c2f736..708bf4546 100644 --- a/xstream-distribution/src/content/converters.html +++ b/xstream-distribution/src/content/converters.html @@ -1,7 +1,7 @@ + +

java.util.concurrent.atomic

+ + + Converter + Supported types + Example + Notes + Prio + + + AtomicBooleanConverter + java.util.concurrent.atomic.AtomicBoolean + + <atomic-boolean>true</atomic-boolean> + + Available with Java 1.5 or greater. + normal + +

java.time

diff --git a/xstream/pom.xml b/xstream/pom.xml index 4dcfbd68e..9462c3523 100644 --- a/xstream/pom.xml +++ b/xstream/pom.xml @@ -329,6 +329,7 @@ **/enums/* **/EnumMapper* **/*15.java + **/Atomic*Converter.java **/PathConverter.java **/Base64*Codec.java **/Types.java @@ -591,6 +592,7 @@ **/core/util/Types* **/reflection/*15* **/extended/*15* + **/extended/Atomic*Converter.java **/extended/PathConverter* **/io/xml/JDom2* diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java index 18cb47112..fe14d5640 100644 --- a/xstream/src/java/com/thoughtworks/xstream/XStream.java +++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java @@ -682,6 +682,7 @@ protected void setupSecurity() { types.add(URL.class); types.add(URI.class); types.add(JVM.loadClassForName("java.util.UUID")); + types.add(JVM.loadClassForName("java.util.concurrent.atomic.AtomicBoolean")); if (JVM.isSQLAvailable()) { types.add(JVM.loadClassForName("java.sql.Timestamp")); types.add(JVM.loadClassForName("java.sql.Time")); @@ -835,6 +836,7 @@ protected void setupAliases() { alias("enum-map", JVM.loadClassForName("java.util.EnumMap")); alias("string-builder", JVM.loadClassForName("java.lang.StringBuilder")); alias("uuid", JVM.loadClassForName("java.util.UUID")); + alias("atomic-boolean", JVM.loadClassForName("java.util.concurrent.atomic.AtomicBoolean")); } if (JVM.isVersion(7)) { @@ -992,6 +994,8 @@ protected void setupConverters() { PRIORITY_NORMAL, null, null); registerConverterDynamically("com.thoughtworks.xstream.converters.basic.UUIDConverter", PRIORITY_NORMAL, null, null); + registerConverterDynamically("com.thoughtworks.xstream.converters.extended.AtomicBooleanConverter", PRIORITY_NORMAL, + null, null); } if (JVM.loadClassForName("javax.activation.ActivationDataFlavor") != null) { registerConverterDynamically("com.thoughtworks.xstream.converters.extended.ActivationDataFlavorConverter", diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicBooleanConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicBooleanConverter.java new file mode 100644 index 000000000..ba9cc5523 --- /dev/null +++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicBooleanConverter.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 XStream Committers. + * All rights reserved. + * + * The software in this package is published under the terms of the BSD + * style license a copy of which has been included with this distribution in + * the LICENSE.txt file. + * + * Created on 26. November 2022 by Joerg Schaible + */ +package com.thoughtworks.xstream.converters.extended; + +import java.util.concurrent.atomic.AtomicBoolean; + +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.converters.basic.BooleanConverter; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; + + +/** + * Converts an AtomicBoolean type. + * + * @author Jörg Schaible + */ +public class AtomicBooleanConverter extends BooleanConverter implements Converter { + + /** + * Constructs an AtomicBooleanConverter. Initializes the converter with true and false as + * string representation. + */ + public AtomicBooleanConverter() { + super(); + } + + public boolean canConvert(final Class type) { + return type != null && type == AtomicBoolean.class; + } + + public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) { + writer.setValue(toString(source)); + } + + public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { + final String data = reader.getValue(); // needs to be called before hasMoreChildren. + if (!reader.hasMoreChildren()) { + return fromString(data); + } else { + // backwards compatibility ... unmarshal nested element + reader.moveDown(); + final AtomicBoolean atomicBoolean = new AtomicBoolean("1".equals(reader.getValue())); + reader.moveUp(); + return atomicBoolean; + } + } + + public String toString(final Object obj) { + return super.toString(((AtomicBoolean)obj).get() ? Boolean.TRUE : Boolean.FALSE); + } + + public Object fromString(final String str) { + return new AtomicBoolean(((Boolean)super.fromString(str)).booleanValue()); + } +} diff --git a/xstream/src/test/com/thoughtworks/acceptance/Concurrent15TypesTest.java b/xstream/src/test/com/thoughtworks/acceptance/Concurrent15TypesTest.java index 9de4979a6..608a6ce63 100644 --- a/xstream/src/test/com/thoughtworks/acceptance/Concurrent15TypesTest.java +++ b/xstream/src/test/com/thoughtworks/acceptance/Concurrent15TypesTest.java @@ -1,17 +1,18 @@ /* - * Copyright (C) 2012, 2015, 2017, 2018 XStream Committers. + * Copyright (C) 2012, 2015, 2017, 2018, 2022 XStream Committers. * All rights reserved. * * The software in this package is published under the terms of the BSD * style license a copy of which has been included with this distribution in * the LICENSE.txt file. - * + * * Created on 21. March 2012 by Joerg Schaible */ package com.thoughtworks.acceptance; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import com.thoughtworks.xstream.converters.collections.MapConverter; import com.thoughtworks.xstream.core.JVM; @@ -20,10 +21,10 @@ public class Concurrent15TypesTest extends AbstractAcceptanceTest { public void testConcurrentHashMap() { - ConcurrentHashMap map = new ConcurrentHashMap(); + final ConcurrentHashMap map = new ConcurrentHashMap<>(); map.put("walnes", "joe"); - String xml = xstream.toXML(map); - String expected = "" + final String xml = xstream.toXML(map); + final String expected = "" + "\n" + " \n" + " walnes\n" @@ -32,7 +33,7 @@ public void testConcurrentHashMap() { + ""; assertEquals(xml, expected); @SuppressWarnings("unchecked") - ConcurrentHashMap out = (ConcurrentHashMap)xstream.fromXML(xml); + final ConcurrentHashMap out = (ConcurrentHashMap)xstream.fromXML(xml); assertEquals("{walnes=joe}", out.toString()); } @@ -45,10 +46,10 @@ public void testDerivedConcurrentHashMap() { xstream.alias("derived-map", DerivedConcurrentHashMap.class); xstream.registerConverter(new MapConverter(xstream.getMapper(), DerivedConcurrentHashMap.class)); - Map map = new DerivedConcurrentHashMap(); + final Map map = new DerivedConcurrentHashMap(); map.put("test", "JUnit"); - String xml = "" + final String xml = "" + "\n" + " \n" + " test\n" @@ -59,4 +60,16 @@ public void testDerivedConcurrentHashMap() { assertBothWays(map, xml); } } + + public void testAtomicBoolean() { + final AtomicBoolean atomicBoolean = new AtomicBoolean(); + assertBothWays(atomicBoolean, "" + atomicBoolean + ""); + } + + public void testAtomicBooleanWithOldFormat() { + assertEquals(new AtomicBoolean(true).toString(), xstream.fromXML("" // + + "\n" // + + " 1\n" // + + "").toString()); + } }