Bug 6910: Fix anyxml node streaming
authorTom Pantelis <tpanteli@brocade.com>
Mon, 10 Oct 2016 20:57:32 +0000 (16:57 -0400)
committerTom Pantelis <tpanteli@brocade.com>
Tue, 11 Oct 2016 15:58:20 +0000 (15:58 +0000)
On output, changed AbstractNormalizedNodeDataOutput to transform the
DOMSource to a result String that is serialized to the stream. On input,
modified NormalizedNodeInputStreamReader to parse the XML string into
a org.w3c.dom.Node and create a DOMSource.

Change-Id: Ib10822c4444331351cf7f25e1f26d981f7d41dc7
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
java/org/opendaylight/controller/cluster/datastore/node/utils/stream/AbstractNormalizedNodeDataOutput.java
java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java

index 5512f3171601d96f1710e8048f3c19993369d0bc..3dc8f1c591d37e18027cc1d886c5f6b9b5acafd4 100644 (file)
@@ -11,10 +11,16 @@ import com.google.common.base.Preconditions;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
@@ -273,11 +279,17 @@ abstract class AbstractNormalizedNodeDataOutput implements NormalizedNodeDataOut
     @Override
     public void anyxmlNode(final NodeIdentifier name, final Object value) throws IOException, IllegalArgumentException {
         Preconditions.checkNotNull(name, "Node identifier should not be null");
-        LOG.debug("Writing a new xml node");
+        LOG.debug("Writing any xml node");
 
         startNode(name.getNodeType(), NodeTypes.ANY_XML_NODE);
 
-        writeObject(value);
+        try {
+            StreamResult xmlOutput = new StreamResult(new StringWriter());
+            TransformerFactory.newInstance().newTransformer().transform((DOMSource)value, xmlOutput);
+            writeObject(xmlOutput.getWriter().toString());
+        } catch (TransformerException | TransformerFactoryConfigurationError e) {
+            throw new IOException("Error writing anyXml", e);
+        }
     }
 
     @Override
index 118b4c0debdced86d69a2ea2d24bc6529c8b5f63..8a114893e66b7c0bca923af23f2c69323e1925d8 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import java.io.DataInput;
 import java.io.IOException;
+import java.io.StringReader;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
@@ -21,6 +22,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.dom.DOMSource;
 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -38,6 +41,9 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
 
 /**
  * NormalizedNodeInputStreamReader reads the byte stream and constructs the normalized node including its children nodes.
@@ -178,7 +184,7 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput
 
             case NodeTypes.ANY_XML_NODE :
                 LOG.debug("Read xml node");
-                return Builders.anyXmlBuilder().withValue((DOMSource) readObject()).build();
+                return Builders.anyXmlBuilder().withNodeIdentifier(identifier).withValue(readDOMSource()).build();
 
             case NodeTypes.MAP_NODE :
                 LOG.debug("Read map node {}", identifier);
@@ -227,6 +233,19 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput
         }
     }
 
+    private DOMSource readDOMSource() throws IOException {
+        String xml = readObject().toString();
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            factory.setNamespaceAware(true);
+            Element node = factory.newDocumentBuilder().parse(
+                    new InputSource(new StringReader(xml))).getDocumentElement();
+            return new DOMSource(node);
+        } catch (SAXException | ParserConfigurationException e) {
+            throw new IOException("Error parsing XML: " + xml, e);
+        }
+    }
+
     private QName readQName() throws IOException {
         // Read in the same sequence of writing
         String localName = readCodedString();