Index: src/java/com/thoughtworks/xstream/XStream.java =================================================================== --- src/java/com/thoughtworks/xstream/XStream.java (revision 876) +++ src/java/com/thoughtworks/xstream/XStream.java (working copy) @@ -1105,7 +1105,7 @@ public ObjectOutputStream createObjectOutputStream( final HierarchicalStreamWriter writer, String rootNodeName) throws IOException { final StatefulWriter statefulWriter = new StatefulWriter(writer); - statefulWriter.startNode(rootNodeName); + statefulWriter.startNode(rootNodeName, null); return new CustomObjectOutputStream(new CustomObjectOutputStream.StreamCallback() { public void writeToStream(Object object) { marshal(object, statefulWriter); Index: src/java/com/thoughtworks/xstream/io/xml/XppDomWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/XppDomWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/XppDomWriter.java (working copy) @@ -34,6 +34,10 @@ elementStack.addLast(configuration); } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void setValue(String text) { top().setValue(text); } Index: src/java/com/thoughtworks/xstream/io/xml/Dom4JWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/Dom4JWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/Dom4JWriter.java (working copy) @@ -36,7 +36,7 @@ throw new StreamException(e); } } - + public void startNode(String name) { if (elementStack.size() > 0) { try { @@ -50,6 +50,10 @@ children = false; } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void setValue(String text) { char[] value = text.toCharArray(); if (value.length > 0) { Index: src/java/com/thoughtworks/xstream/io/xml/DomWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/DomWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/DomWriter.java (working copy) @@ -33,7 +33,7 @@ document = rootElement.getOwnerDocument(); current = rootElement; } - + public void startNode(String name) { final Element child = document.createElement(escapeXmlName(name)); if (current == null) { @@ -44,6 +44,10 @@ current = child; } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void addAttribute(String name, String value) { current.setAttribute(escapeXmlName(name), value); } Index: src/java/com/thoughtworks/xstream/io/xml/AbstractXmlWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/AbstractXmlWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/AbstractXmlWriter.java (working copy) @@ -1,6 +1,7 @@ package com.thoughtworks.xstream.io.xml; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriter; /** * Abstract base implementation of HierarchicalStreamWriter that provides common functionality @@ -8,7 +9,7 @@ * * @author Mauro Talevi */ -public abstract class AbstractXmlWriter implements HierarchicalStreamWriter { +public abstract class AbstractXmlWriter implements ExtendedHierarchicalStreamWriter { private XmlFriendlyReplacer replacer; @@ -29,5 +30,5 @@ protected String escapeXmlName(String name) { return replacer.escapeName(name); } - + } Index: src/java/com/thoughtworks/xstream/io/xml/JDomWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/JDomWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/JDomWriter.java (working copy) @@ -54,6 +54,10 @@ elementStack.add(0, element); } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void setValue(String text) { top().addContent(this.documentFactory.text(text)); } Index: src/java/com/thoughtworks/xstream/io/xml/SaxWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/SaxWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/SaxWriter.java (working copy) @@ -576,6 +576,10 @@ } } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void addAttribute(String name, String value) { if (this.startTagInProgress) { String escapedName = escapeXmlName(name); Index: src/java/com/thoughtworks/xstream/io/xml/XomWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/XomWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/XomWriter.java (working copy) @@ -17,13 +17,17 @@ super(replacer); this.node = parentElement; } - + public void startNode(String name) { Element newNode = new Element(escapeXmlName(name)); node.appendChild(newNode); node = newNode; } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void addAttribute(String name, String value) { node.addAttribute(new Attribute(escapeXmlName(name), value)); } Index: src/java/com/thoughtworks/xstream/io/xml/PrettyPrintWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/PrettyPrintWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/PrettyPrintWriter.java (working copy) @@ -67,7 +67,6 @@ this(writer, new char[]{' ', ' '}); } - public void startNode(String name) { String escapedName = escapeXmlName(name); tagIsEmpty = false; @@ -81,6 +80,10 @@ tagIsEmpty = true; } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void setValue(String text) { readyForNewLine = false; tagIsEmpty = false; Index: src/java/com/thoughtworks/xstream/io/xml/StaxWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/xml/StaxWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/xml/StaxWriter.java (working copy) @@ -164,6 +164,11 @@ } } + public void startNode(String name, Class clazz) { + startNode(name); + } + + public HierarchicalStreamWriter underlyingWriter() { return this; } Index: src/java/com/thoughtworks/xstream/io/binary/BinaryStreamWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/binary/BinaryStreamWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/binary/BinaryStreamWriter.java (working copy) @@ -2,6 +2,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.StreamException; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriter; import java.io.DataOutputStream; import java.io.OutputStream; @@ -9,7 +10,7 @@ import java.util.Map; import java.util.HashMap; -public class BinaryStreamWriter implements HierarchicalStreamWriter { +public class BinaryStreamWriter implements ExtendedHierarchicalStreamWriter { private final IdRegistry idRegistry = new IdRegistry(); private final DataOutputStream out; @@ -23,6 +24,10 @@ write(new Token.StartNode(idRegistry.getId(name))); } + public void startNode(String name, Class clazz) { + startNode(name); + } + public void addAttribute(String name, String value) { write(new Token.Attribute(idRegistry.getId(name), value)); } Index: src/java/com/thoughtworks/xstream/io/StatefulWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/StatefulWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/StatefulWriter.java (working copy) @@ -65,6 +65,16 @@ } public void startNode(final String name) { + startNodeCommon(); + super.startNode(name); + } + + public void startNode(final String name, final Class clazz) { + startNodeCommon(); + super.startNode(name, clazz); + } + + private void startNodeCommon() { checkClosed(); if (state == STATE_VALUE) { // legal XML, but not in XStream ... ? @@ -73,7 +83,6 @@ state = STATE_NODE_START; ++balance; attributes.push(new HashSet()); - super.startNode(name); } public void addAttribute(String name, String value) { Index: src/java/com/thoughtworks/xstream/io/path/PathTrackingWriter.java =================================================================== --- src/java/com/thoughtworks/xstream/io/path/PathTrackingWriter.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/path/PathTrackingWriter.java (working copy) @@ -22,9 +22,14 @@ public void startNode(String name) { pathTracker.pushElement(name); - super.startNode(name); + super.startNode(name); } + public void startNode(String name, Class clazz) { + pathTracker.pushElement(name); + super.startNode(name, clazz); + } + public void endNode() { super.endNode(); pathTracker.popElement(); Index: src/java/com/thoughtworks/xstream/io/WriterWrapper.java =================================================================== --- src/java/com/thoughtworks/xstream/io/WriterWrapper.java (revision 876) +++ src/java/com/thoughtworks/xstream/io/WriterWrapper.java (working copy) @@ -5,7 +5,7 @@ * * @author Joe Walnes */ -public abstract class WriterWrapper implements HierarchicalStreamWriter { +public abstract class WriterWrapper implements ExtendedHierarchicalStreamWriter { protected HierarchicalStreamWriter wrapped; @@ -17,6 +17,11 @@ wrapped.startNode(name); } + public void startNode(String name, Class clazz) { + + ((ExtendedHierarchicalStreamWriter) wrapped).startNode(name, clazz); + } + public void endNode() { wrapped.endNode(); } Index: src/java/com/thoughtworks/xstream/core/TreeMarshaller.java =================================================================== --- src/java/com/thoughtworks/xstream/core/TreeMarshaller.java (revision 876) +++ src/java/com/thoughtworks/xstream/core/TreeMarshaller.java (working copy) @@ -7,6 +7,7 @@ import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.core.util.ObjectIdDictionary; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.Mapper; import java.util.Iterator; @@ -68,7 +69,7 @@ writer.startNode(mapper.serializedClass(null)); writer.endNode(); } else { - writer.startNode(mapper.serializedClass(item.getClass())); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(item.getClass()), item.getClass()); convertAnother(item); writer.endNode(); } Index: src/java/com/thoughtworks/xstream/converters/basic/NullConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/basic/NullConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/basic/NullConverter.java (working copy) @@ -5,6 +5,7 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.Mapper; /** @@ -19,7 +20,7 @@ } public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { - writer.startNode("null"); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, "null", null); writer.endNode(); } Index: src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/reflection/ExternalizableConverter.java (working copy) @@ -8,14 +8,13 @@ import com.thoughtworks.xstream.core.util.CustomObjectOutputStream; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.Mapper; import java.io.Externalizable; import java.io.IOException; import java.io.NotActiveException; -import java.io.ObjectInput; import java.io.ObjectInputValidation; -import java.io.ObjectOutput; import java.util.Map; /** @@ -45,7 +44,7 @@ writer.startNode("null"); writer.endNode(); } else { - writer.startNode(mapper.serializedClass(object.getClass())); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(object.getClass()), object.getClass()); context.convertAnother(object); writer.endNode(); } Index: src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/reflection/AbstractReflectionConverter.java (working copy) @@ -7,6 +7,7 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.Mapper; import java.lang.reflect.Field; @@ -87,7 +88,7 @@ if (!mapper.shouldSerializeMember(definedIn, aliasName)) { return; } - writer.startNode(mapper.serializedMember(definedIn, aliasName)); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedMember(definedIn, aliasName), fieldType); Class actualType = newObj.getClass(); Index: src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java (working copy) @@ -5,6 +5,7 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.CGLIBMapper; import com.thoughtworks.xstream.mapper.Mapper; @@ -62,7 +63,7 @@ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { Class type = source.getClass(); boolean hasFactory = Factory.class.isAssignableFrom(type); - writer.startNode("type"); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, "type", type); context.convertAnother(type.getSuperclass()); writer.endNode(); writer.startNode("interfaces"); @@ -71,7 +72,7 @@ if (interfaces[i] == Factory.class) { continue; } - writer.startNode(mapper.serializedClass(interfaces[i].getClass())); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(interfaces[i].getClass()), interfaces[i].getClass()); context.convertAnother(interfaces[i]); writer.endNode(); } @@ -84,15 +85,15 @@ throw new ConversionException("Cannot handle CGLIB enhanced proxies with multiple callbacks"); } boolean isInterceptor = MethodInterceptor.class.isAssignableFrom(callbacks[0].getClass()); - - writer.startNode(mapper.serializedClass(callbacks[0].getClass())); + + ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(callbacks[0].getClass()), callbacks[0].getClass()); context.convertAnother(callbacks[0]); writer.endNode(); try { final Field field = type.getDeclaredField("serialVersionUID"); field.setAccessible(true); long serialVersionUID = field.getLong(null); - writer.startNode("serialVersionUID"); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, "serialVersionUID", String.class); writer.setValue(String.valueOf(serialVersionUID)); writer.endNode(); } catch (NoSuchFieldException e) { Index: src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/reflection/SerializableConverter.java (working copy) @@ -21,6 +21,7 @@ import com.thoughtworks.xstream.core.util.CustomObjectOutputStream; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.Mapper; /** @@ -84,7 +85,7 @@ writer.startNode(ELEMENT_NULL); writer.endNode(); } else { - writer.startNode(mapper.serializedClass(object.getClass())); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper.serializedClass(object.getClass()), object.getClass()); context.convertAnother(object); writer.endNode(); } Index: src/java/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/javabean/JavaBeanConverter.java (working copy) @@ -7,6 +7,7 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.Mapper; /** @@ -60,8 +61,7 @@ } private void writeField(String propertyName, Class fieldType, Object newObj) { - writer.startNode(classMapper.serializedMember(source.getClass(), propertyName)); - + ExtendedHierarchicalStreamWriterHelper.startNode(writer, classMapper.serializedMember(source.getClass(), propertyName), fieldType); Class actualType = newObj.getClass(); Class defaultType = classMapper.defaultImplementationOf(fieldType); Index: src/java/com/thoughtworks/xstream/converters/collections/ArrayConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/collections/ArrayConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/collections/ArrayConverter.java (working copy) @@ -33,6 +33,7 @@ Object item = Array.get(source, i); writeItem(item, context, writer); } + } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Index: src/java/com/thoughtworks/xstream/converters/collections/AbstractCollectionConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/collections/AbstractCollectionConverter.java (revision 876) +++ src/java/com/thoughtworks/xstream/converters/collections/AbstractCollectionConverter.java (working copy) @@ -6,6 +6,7 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper; import com.thoughtworks.xstream.mapper.Mapper; /** @@ -36,14 +37,18 @@ public abstract Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context); + + protected void writeItem(Object item, MarshallingContext context, HierarchicalStreamWriter writer) { // PUBLISHED API METHOD! If changing signature, ensure backwards compatability. if (item == null) { // todo: this is duplicated in TreeMarshaller.start() - writer.startNode(mapper().serializedClass(null)); + String name = mapper().serializedClass(null); + writer.startNode(name); writer.endNode(); } else { - writer.startNode(mapper().serializedClass(item.getClass())); + String name = mapper().serializedClass(item.getClass()); + ExtendedHierarchicalStreamWriterHelper.startNode(writer, name, item.getClass()); context.convertAnother(item); writer.endNode(); }