Skip to content

Commit

Permalink
Unable to serialize AtomicBoolean on Java 17 (#7270)
Browse files Browse the repository at this point in the history
  • Loading branch information
basil authored Oct 18, 2022
1 parent 47322f3 commit 7ad10b7
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
2 changes: 2 additions & 0 deletions core/src/main/java/hudson/util/XStream2.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import jenkins.util.SystemProperties;
import jenkins.util.xstream.AtomicBooleanConverter;
import jenkins.util.xstream.SafeURLConverter;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
Expand Down Expand Up @@ -273,6 +274,7 @@ private void init() {
// http://www.openwall.com/lists/oss-security/2017/04/03/4
denyTypes(new Class[] { void.class, Void.class });

registerConverter(new AtomicBooleanConverter(), 10);
registerConverter(new RobustCollectionConverter(getMapper(), getReflectionProvider()), 10);
registerConverter(new RobustMapConverter(getMapper()), 10);
registerConverter(new ImmutableMapConverter(getMapper(), getReflectionProvider()), 10);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package jenkins.util.xstream;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.SingleValueConverterWrapper;
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;
import java.util.concurrent.atomic.AtomicBoolean;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

/** Converts an {@link AtomicBoolean}. */
@Restricted(NoExternalUse.class)
public class AtomicBooleanConverter implements Converter {

@Override
public boolean canConvert(Class type) {
return type != null && AtomicBoolean.class.isAssignableFrom(type);
}

@Override
public void marshal(
Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
final AtomicBoolean atomicBoolean = (AtomicBoolean) source;
writer.startNode("value");
context.convertAnother(
atomicBoolean.get(), new SingleValueConverterWrapper(BooleanConverter.BINARY));
writer.endNode();
}

@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
reader.moveDown();
Object item =
context.convertAnother(
null,
Boolean.class,
new SingleValueConverterWrapper(BooleanConverter.BINARY));
boolean value = item instanceof Boolean ? ((Boolean) item).booleanValue() : false;
reader.moveUp();
return new AtomicBoolean(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package jenkins.util.xstream;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import com.thoughtworks.xstream.io.binary.BinaryStreamReader;
import com.thoughtworks.xstream.io.binary.BinaryStreamWriter;
import hudson.util.XStream2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;

public class AtomicBooleanFieldsTest {

public static class Musican {
public String name;
public String genre;
public AtomicBoolean alive;

public Musican(final String name, final String genre, final AtomicBoolean alive) {
this.name = name;
this.genre = genre;
this.alive = alive;
}
}

@Test
public void testAtomicBooleanFields() {
List<Musican> jazzIcons = new ArrayList<>();
jazzIcons.add(new Musican("Miles Davis", "jazz", new AtomicBoolean(false)));
jazzIcons.add(new Musican("Wynton Marsalis", "jazz", new AtomicBoolean(true)));

XStream2 xstream = new XStream2();
xstream.alias("musician", Musican.class);

String xmlString = xstream.toXML(jazzIcons);
assertEquals(
"<list>\n"
+ " <musician>\n"
+ " <name>Miles Davis</name>\n"
+ " <genre>jazz</genre>\n"
+ " <alive>\n"
+ " <value>0</value>\n"
+ " </alive>\n"
+ " </musician>\n"
+ " <musician>\n"
+ " <name>Wynton Marsalis</name>\n"
+ " <genre>jazz</genre>\n"
+ " <alive>\n"
+ " <value>1</value>\n"
+ " </alive>\n"
+ " </musician>\n"
+ "</list>",
xmlString);
List<Musican> obj = (List<Musican>) xstream.fromXML(xmlString);
assertNotNull(obj);
assertEquals(xstream.toXML(jazzIcons), xstream.toXML(obj));

ByteArrayOutputStream baos = new ByteArrayOutputStream();
xstream.marshal(jazzIcons, new BinaryStreamWriter(baos));
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
obj = (List<Musican>) xstream.unmarshal(new BinaryStreamReader(bais));
assertNotNull(obj);
assertEquals(xstream.toXML(jazzIcons), xstream.toXML(obj));
}
}

0 comments on commit 7ad10b7

Please sign in to comment.