Skip to content

Commit

Permalink
Add converter for AtomicBoolean. Closes #308 and #309.
Browse files Browse the repository at this point in the history
  • Loading branch information
joehni committed Dec 17, 2022
1 parent 9d63169 commit 0eb58db
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 9 deletions.
19 changes: 19 additions & 0 deletions xstream-distribution/src/content/changes.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,31 @@ <h1 id="upcoming-1.4.x">Upcoming 1.4.x maintenance release</h1>

<p>Not yet released.</p>

<h2>Major changes</h2>

<ul>
<li>GHI:#308: Add converter for AtomicBoolean of package java.util.concurrent.atomic.</li>
</ul>

<h2>Minor changes</h2>

<ul>
<li>GHPR:#287: Close stream opened from provided URL.</li>
</ul>

<h2>Stream compatibility</h2>

<ul>
<li>The atomic types with new converters of package java.util.concurrent.atomic, that have been written with
previous versions of XStream, can still be deserialized.</li>
</ul>

<h2>API changes</h2>

<ul>
<li>Added c.t.x.converters.extended.AtomicBooleanConverter.</li>
</ul>

<h1 id="1.4.19">1.4.19</h1>

<p>Released January 29, 2022.</p>
Expand Down
23 changes: 22 additions & 1 deletion xstream-distribution/src/content/converters.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<html>
<!--
Copyright (C) 2005, 2006 Joe Walnes.
Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2014, 2015, 2016, 2017 XStream committers.
Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2014, 2015, 2016, 2017, 2022 XStream committers.
All rights reserved.
The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -461,6 +461,27 @@
<td>normal</td>
</tr>

<!-- .................................................................................................. -->
<tr>
<td colspan="5" class="headerRow"><h1 id="java.util.concurrent.atomic">java.util.concurrent.atomic</h1></td>
</tr>
<tr>
<th>Converter</th>
<th>Supported types</th>
<th>Example</th>
<th>Notes</th>
<th>Prio</th>
</tr>
<tr>
<td><a href="javadoc/com/thoughtworks/xstream/converters/extended/AtomicBooleanConverter.html">AtomicBooleanConverter</a></td>
<td>java.util.concurrent.atomic.AtomicBoolean</td>
<td class="example">
&lt;atomic-boolean&gt;true&lt;/atomic-boolean&gt;
</td>
<td>Available with Java 1.5 or greater.</td>
<td>normal</td>
</tr>

<!-- .................................................................................................. -->
<tr>
<td colspan="5" class="headerRow"><h1 id="java.time">java.time</h1></td>
Expand Down
2 changes: 2 additions & 0 deletions xstream/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@
<exclude>**/enums/*</exclude>
<exclude>**/EnumMapper*</exclude>
<exclude>**/*15.java</exclude>
<exclude>**/Atomic*Converter.java</exclude>
<exclude>**/PathConverter.java</exclude>
<exclude>**/Base64*Codec.java</exclude>
<exclude>**/Types.java</exclude>
Expand Down Expand Up @@ -591,6 +592,7 @@
<exclude>**/core/util/Types*</exclude>
<exclude>**/reflection/*15*</exclude>
<exclude>**/extended/*15*</exclude>
<exclude>**/extended/Atomic*Converter.java</exclude>
<exclude>**/extended/PathConverter*</exclude>
<exclude>**/io/xml/JDom2*</exclude>
</excludes>
Expand Down
4 changes: 4 additions & 0 deletions xstream/src/java/com/thoughtworks/xstream/XStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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&ouml;rg Schaible
*/
public class AtomicBooleanConverter extends BooleanConverter implements Converter {

/**
* Constructs an AtomicBooleanConverter. Initializes the converter with <em>true</em> and <em>false</em> 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());
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -20,10 +21,10 @@
public class Concurrent15TypesTest extends AbstractAcceptanceTest {

public void testConcurrentHashMap() {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
final ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
map.put("walnes", "joe");
String xml = xstream.toXML(map);
String expected = ""
final String xml = xstream.toXML(map);
final String expected = ""
+ "<concurrent-hash-map>\n"
+ " <entry>\n"
+ " <string>walnes</string>\n"
Expand All @@ -32,7 +33,7 @@ public void testConcurrentHashMap() {
+ "</concurrent-hash-map>";
assertEquals(xml, expected);
@SuppressWarnings("unchecked")
ConcurrentHashMap<String, String> out = (ConcurrentHashMap<String, String>)xstream.fromXML(xml);
final ConcurrentHashMap<String, String> out = (ConcurrentHashMap<String, String>)xstream.fromXML(xml);
assertEquals("{walnes=joe}", out.toString());
}

Expand All @@ -45,10 +46,10 @@ public void testDerivedConcurrentHashMap() {
xstream.alias("derived-map", DerivedConcurrentHashMap.class);
xstream.registerConverter(new MapConverter(xstream.getMapper(), DerivedConcurrentHashMap.class));

Map<Object, Object> map = new DerivedConcurrentHashMap();
final Map<Object, Object> map = new DerivedConcurrentHashMap();
map.put("test", "JUnit");

String xml = ""
final String xml = ""
+ "<derived-map>\n"
+ " <entry>\n"
+ " <string>test</string>\n"
Expand All @@ -59,4 +60,16 @@ public void testDerivedConcurrentHashMap() {
assertBothWays(map, xml);
}
}

public void testAtomicBoolean() {
final AtomicBoolean atomicBoolean = new AtomicBoolean();
assertBothWays(atomicBoolean, "<atomic-boolean>" + atomicBoolean + "</atomic-boolean>");
}

public void testAtomicBooleanWithOldFormat() {
assertEquals(new AtomicBoolean(true).toString(), xstream.fromXML("" //
+ "<java.util.concurrent.atomic.AtomicBoolean>\n" //
+ " <value>1</value>\n" //
+ "</java.util.concurrent.atomic.AtomicBoolean>").toString());
}
}

0 comments on commit 0eb58db

Please sign in to comment.