diff --git a/xstream-distribution/src/content/changes.html b/xstream-distribution/src/content/changes.html index 45ac67b62..63f98fdbe 100644 --- a/xstream-distribution/src/content/changes.html +++ b/xstream-distribution/src/content/changes.html @@ -102,11 +102,28 @@

Stream compatibility

  • No support for Hibernate 3 collections.
  • - + +

    Major changes

    + + + +

    Stream compatibility

    + + + +

    API changes

    + +

    1.4.19

    diff --git a/xstream-distribution/src/content/converters.html b/xstream-distribution/src/content/converters.html index f96c2490f..d8a469a61 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-distribution/src/content/team.html b/xstream-distribution/src/content/team.html index 90b93ee48..32d9116ea 100644 --- a/xstream-distribution/src/content/team.html +++ b/xstream-distribution/src/content/team.html @@ -130,6 +130,7 @@

    Contributors

  • Falko Modler
  • Julia Boes of Oracle
  • Chris Hegarty of Oracle
  • +
  • Basil Crow
  • Please direct all correspondence about XStream to the mailing list diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java index 415b46fc6..57a06a56c 100644 --- a/xstream/src/java/com/thoughtworks/xstream/XStream.java +++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java @@ -101,6 +101,7 @@ import java.util.UUID; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import com.thoughtworks.xstream.converters.ConversionException; @@ -141,6 +142,7 @@ import com.thoughtworks.xstream.converters.enums.EnumConverter; import com.thoughtworks.xstream.converters.enums.EnumMapConverter; import com.thoughtworks.xstream.converters.enums.EnumSetConverter; +import com.thoughtworks.xstream.converters.extended.AtomicBooleanConverter; import com.thoughtworks.xstream.converters.extended.CharsetConverter; import com.thoughtworks.xstream.converters.extended.ColorConverter; import com.thoughtworks.xstream.converters.extended.CurrencyConverter; @@ -716,9 +718,10 @@ protected void setupSecurity() { allowTypeHierarchy(Path.class); final Set> types = new HashSet<>(); - types.addAll(Arrays.>asList(BitSet.class, Charset.class, Class.class, Currency.class, Date.class, - DecimalFormatSymbols.class, File.class, Locale.class, Object.class, Pattern.class, StackTraceElement.class, - String.class, StringBuffer.class, StringBuilder.class, URL.class, URI.class, UUID.class)); + types.addAll(Arrays.>asList(AtomicBoolean.class, BitSet.class, Charset.class, Class.class, + Currency.class, Date.class, DecimalFormatSymbols.class, File.class, Locale.class, Object.class, + Pattern.class, StackTraceElement.class, String.class, StringBuffer.class, StringBuilder.class, URL.class, + URI.class, UUID.class)); if (JVM.isSQLAvailable()) { types.add(JVM.loadClassForName("java.sql.Timestamp")); types.add(JVM.loadClassForName("java.sql.Time")); @@ -823,6 +826,7 @@ protected void setupAliases() { alias("linked-hash-map", LinkedHashMap.class); alias("linked-hash-set", LinkedHashSet.class); alias("concurrent-hash-map", ConcurrentHashMap.class); + alias("atomic-boolean", AtomicBoolean.class); alias("enum-set", EnumSet.class); alias("enum-map", EnumMap.class); @@ -954,6 +958,7 @@ protected void setupConverters() { registerConverter(new BigIntegerConverter(), PRIORITY_NORMAL); registerConverter(new BigDecimalConverter(), PRIORITY_NORMAL); registerConverter(new PathConverter(), PRIORITY_NORMAL); + registerConverter((Converter)new AtomicBooleanConverter(), PRIORITY_NORMAL); registerConverter(new ArrayConverter(mapper), PRIORITY_NORMAL); registerConverter(new CharArrayConverter(), PRIORITY_NORMAL); 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..cc58a10b5 --- /dev/null +++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicBooleanConverter.java @@ -0,0 +1,72 @@ +/* + * 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 Basil Crow + * @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(); + } + + @Override + public boolean canConvert(final Class type) { + return type != null && type == AtomicBoolean.class; + } + + @Override + public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) { + writer.setValue(toString(source)); + } + + @Override + 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; + } + } + + @Override + public String toString(final Object obj) { + return super.toString(((AtomicBoolean)obj).get() ? Boolean.TRUE : Boolean.FALSE); + } + + @Override + public Object fromString(final String str) { + return new AtomicBoolean(((Boolean)super.fromString(str)).booleanValue()); + } +} diff --git a/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java b/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java index 33a52dd83..cb8b4081e 100644 --- a/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java +++ b/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2015, 2017, 2018, 2021 XStream Committers. + * Copyright (C) 2012, 2015, 2017, 2018, 2021, 2022 XStream Committers. * All rights reserved. * * The software in this package is published under the terms of the BSD @@ -12,6 +12,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import com.thoughtworks.xstream.converters.collections.MapConverter; @@ -19,7 +20,7 @@ public class ConcurrentTypesTest extends AbstractAcceptanceTest { public void testConcurrentHashMap() { - final ConcurrentHashMap map = new ConcurrentHashMap(); + final ConcurrentHashMap map = new ConcurrentHashMap<>(); map.put("walnes", "joe"); final String xml = xstream.toXML(map); final String expected = "" @@ -55,4 +56,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()); + } }