From 6444f7afc393807fb4ac63a2c2911c5a70671b3f Mon Sep 17 00:00:00 2001 From: Alex Blekhman Date: Mon, 27 Mar 2023 19:47:25 +1100 Subject: [PATCH] Fix AtomicReference marshalling. Closes #326. --- .../extended/AtomicReferenceConverter.java | 28 +++++++++++-------- .../acceptance/ConcurrentTypesTest.java | 7 ++++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicReferenceConverter.java b/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicReferenceConverter.java index fb4638569..15d058a35 100644 --- a/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicReferenceConverter.java +++ b/xstream/src/java/com/thoughtworks/xstream/converters/extended/AtomicReferenceConverter.java @@ -43,23 +43,29 @@ public boolean canConvert(final Class type) { @Override public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) { final AtomicReference ref = (AtomicReference)source; - writer.startNode(mapper.serializedMember(AtomicReference.class, "value")); - final Object object = ref.get(); - final String name = mapper.serializedClass(object != null ? object.getClass() : null); - writer.addAttribute(mapper.aliasForSystemAttribute("class"), name); - context.convertAnother(ref.get()); - writer.endNode(); + if (object != null) { + writer.startNode(mapper.serializedMember(AtomicReference.class, "value")); + + final String name = mapper.serializedClass(object.getClass()); + writer.addAttribute(mapper.aliasForSystemAttribute("class"), name); + context.convertAnother(object); + writer.endNode(); + } } @Override public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { - reader.moveDown(); + if (reader.hasMoreChildren()) { + reader.moveDown(); - final Class type = HierarchicalStreams.readClassType(reader, mapper); - final Object value = context.convertAnother(context, type); - reader.moveUp(); - return new AtomicReference<>(value); + final Class type = HierarchicalStreams.readClassType(reader, mapper); + final Object value = context.convertAnother(context, type); + reader.moveUp(); + return new AtomicReference<>(value); + } else { + return new AtomicReference<>(); + } } } diff --git a/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java b/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java index 0d6d16246..e0e5cf4ee 100644 --- a/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java +++ b/xstream/src/test/com/thoughtworks/acceptance/ConcurrentTypesTest.java @@ -108,12 +108,17 @@ public void testAtomicReference() { @SuppressWarnings("unchecked") public void testAtomicReferenceWithOldFormat() { - assertEquals(new AtomicReference("test").get(), ((AtomicReference)xstream.fromXML("" // + assertEquals(new AtomicReference<>("test").get(), ((AtomicReference)xstream.fromXML("" // + "\n" // + " test\n" // + "")).get()); } + public void testEmptyAtomicReference() { + final AtomicReference atomicRef = new AtomicReference<>(); + assertBothWays(atomicRef, ""); + } + public void testAtomicReferenceWithAlias() { xstream.aliasField("junit", AtomicReference.class, "value"); final AtomicReference atomicRef = new AtomicReference<>("test");