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 @@
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());
+ }
}