Bug 5825: Migrate restconf to the new XML parser 86/60286/4
authorIgor Foltin <igor.foltin@pantheon.tech>
Thu, 13 Jul 2017 13:16:01 +0000 (15:16 +0200)
committerIgor Foltin <igor.foltin@pantheon.tech>
Tue, 18 Jul 2017 06:16:00 +0000 (06:16 +0000)
Migrate restconf components to the new XML parser from YANG tools

Change-Id: I87aa8df157ca5cba953852415c49806f2c61ff7b
Signed-off-by: Igor Foltin <igor.foltin@pantheon.tech>
restconf/sal-rest-connector/pom.xml
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlNormalizedNodeBodyReader.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlToPatchBodyReader.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/md/sal/rest/common/TestRestconfUtils.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/nn/to/json/test/NnToJsonLeafrefType.java

index 74acd42672d48b9c9abde1254a563b88e5e0c3ff..c086aa81c3d770afd9558d876034d40edd0ec877 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-config</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-util</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-api</artifactId>
index 4458995e7766182481eb1554a91bca38efe9ab8b..c79beb74a25163d7527310e10638b24ff8e6197c 100644 (file)
@@ -11,16 +11,20 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterables;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.StringReader;
+import java.net.URISyntaxException;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Deque;
 import java.util.List;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
@@ -32,9 +36,11 @@ import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
@@ -49,7 +55,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
-import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
 
 @Provider
 @Consumes({ Rfc8040.MediaTypes.DATA + RestconfConstants.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
@@ -73,9 +79,8 @@ public class XmlNormalizedNodeBodyReader extends AbstractNormalizedNodeBodyReade
         }
     }
 
-    private NormalizedNodeContext parse(final InstanceIdentifierContext<?> pathContext,final Document doc) {
-
-        final List<Element> elements = Collections.singletonList(doc.getDocumentElement());
+    private NormalizedNodeContext parse(final InstanceIdentifierContext<?> pathContext, final Document doc)
+            throws XMLStreamException, IOException, ParserConfigurationException, SAXException, URISyntaxException {
         final SchemaNode schemaNodeContext = pathContext.getSchemaNode();
         DataSchemaNode schemaNode;
         boolean isRpc = false;
@@ -91,11 +96,6 @@ public class XmlNormalizedNodeBodyReader extends AbstractNormalizedNodeBodyReade
         final String docRootElm = doc.getDocumentElement().getLocalName();
         final String docRootNamespace = doc.getDocumentElement().getNamespaceURI();
         final List<YangInstanceIdentifier.PathArgument> iiToDataList = new ArrayList<>();
-        InstanceIdentifierContext<? extends SchemaNode> outIIContext;
-
-        final DomToNormalizedNodeParserFactory parserFactory =
-                DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER,
-                    pathContext.getSchemaContext());
 
         if (isPost() && !isRpc) {
             final Deque<Object> foundSchemaNodes = findPathToSchemaNodeByName(schemaNode, docRootElm, docRootNamespace);
@@ -123,28 +123,29 @@ public class XmlNormalizedNodeBodyReader extends AbstractNormalizedNodeBodyReade
                             docRootElm, scQName));
         }
 
-        final NormalizedNode<?, ?> parsed;
-        if (schemaNode instanceof ContainerSchemaNode) {
-            parsed = parserFactory.getContainerNodeParser().parse(
-                    Collections.singletonList(doc.getDocumentElement()), (ContainerSchemaNode) schemaNode);
-        } else if (schemaNode instanceof ListSchemaNode) {
-            parsed = parserFactory.getMapEntryNodeParser().parse(elements, (ListSchemaNode) schemaNode);
-            if (isPost()) {
+        NormalizedNode<?, ?> parsed = null;
+        final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+        final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+
+        if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode
+                || schemaNode instanceof LeafSchemaNode) {
+            final XmlParserStream xmlParser = XmlParserStream.create(writer, pathContext.getSchemaContext(),
+                    schemaNode);
+            xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(
+                    doc.getDocumentElement()))));
+            parsed = resultHolder.getResult();
+            if (schemaNode instanceof  ListSchemaNode && isPost()) {
                 iiToDataList.add(parsed.getIdentifier());
             }
-        } else if (schemaNode instanceof LeafSchemaNode) {
-            parsed = parserFactory.getLeafNodeParser().parse(elements, (LeafSchemaNode) schemaNode);
-        } else {
-            LOG.warn("Unknown schema node extension {} was not parsed", schemaNode.getClass());
-            parsed = null;
         }
 
+        LOG.warn("Unknown schema node extension {} was not parsed", schemaNode.getClass());
+
         final YangInstanceIdentifier fullIIToData = YangInstanceIdentifier.create(Iterables.concat(
                 pathContext.getInstanceIdentifier().getPathArguments(), iiToDataList));
 
-        outIIContext = new InstanceIdentifierContext<>(fullIIToData, pathContext.getSchemaNode(),
-                pathContext.getMountPoint(),
-                pathContext.getSchemaContext());
+        final InstanceIdentifierContext<? extends SchemaNode> outIIContext = new InstanceIdentifierContext<>(
+                fullIIToData, pathContext.getSchemaNode(), pathContext.getMountPoint(), pathContext.getSchemaContext());
 
         return new NormalizedNodeContext(outIIContext, parsed);
     }
index b5138c06cb32de03416dc720f485a5d9208d7245..710a591b3f4607df152d9bd6acef1a453215b02f 100644 (file)
@@ -12,7 +12,9 @@ import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.StringReader;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -20,6 +22,9 @@ import javax.annotation.Nonnull;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.netconf.sal.restconf.impl.PatchContext;
 import org.opendaylight.netconf.sal.restconf.impl.PatchEditOperation;
@@ -34,8 +39,10 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -49,6 +56,7 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
 
 @Provider
 @Consumes({Rfc8040.MediaTypes.PATCH + RestconfConstants.XML})
@@ -73,13 +81,11 @@ public class XmlToPatchBodyReader extends AbstractToPatchBodyReader {
         }
     }
 
-    private static PatchContext parse(final InstanceIdentifierContext<?> pathContext, final Document doc) {
+    private static PatchContext parse(final InstanceIdentifierContext<?> pathContext, final Document doc)
+            throws XMLStreamException, IOException, ParserConfigurationException, SAXException, URISyntaxException {
         final List<PatchEntity> resultCollection = new ArrayList<>();
         final String patchId = doc.getElementsByTagName("patch-id").item(0).getFirstChild().getNodeValue();
         final NodeList editNodes = doc.getElementsByTagName("edit");
-        final DomToNormalizedNodeParserFactory parserFactory =
-                DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER,
-                        pathContext.getSchemaContext());
 
         for (int i = 0; i < editNodes.getLength(); i++) {
             DataSchemaNode schemaNode = (DataSchemaNode) pathContext.getSchemaNode();
@@ -130,13 +136,15 @@ public class XmlToPatchBodyReader extends AbstractToPatchBodyReader {
             }
 
             if (oper.isWithValue()) {
-                final NormalizedNode<?, ?> parsed;
-                if (schemaNode instanceof ContainerSchemaNode) {
-                    parsed = parserFactory.getContainerNodeParser().parse(values, (ContainerSchemaNode) schemaNode);
-                } else if (schemaNode instanceof ListSchemaNode) {
-                    parsed = parserFactory.getMapNodeParser().parse(values, (ListSchemaNode) schemaNode);
-                } else {
-                    parsed = null;
+                NormalizedNode<?, ?> parsed = null;
+                if (schemaNode instanceof  ContainerSchemaNode || schemaNode instanceof ListSchemaNode) {
+                    final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+                    final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+                    final XmlParserStream xmlParser = XmlParserStream.create(writer, pathContext.getSchemaContext(),
+                            schemaNode);
+                    xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(
+                            firstValueElement))));
+                    parsed = resultHolder.getResult();
                 }
 
                 // for lists allow to manipulate with list items through their parent
index 1b29107e3e2eb1e093b8aef0983143847c1710c2..05a29f422a84c726b1f32a69510e2dd1195ffa73 100644 (file)
@@ -11,19 +11,26 @@ package org.opendaylight.controller.md.sal.rest.common;
 import com.google.common.base.Preconditions;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.StringReader;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.controller.sal.rest.impl.test.providers.TestJsonBodyWriter;
 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
 import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -35,7 +42,7 @@ import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
-import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
 
 public class TestRestconfUtils {
 
@@ -80,8 +87,8 @@ public class TestRestconfUtils {
         return null;
     }
 
-    private static NormalizedNode<?, ?> parse(final InstanceIdentifierContext<?> iiContext, final Document doc) {
-        final List<Element> elements = Collections.singletonList(doc.getDocumentElement());
+    private static NormalizedNode<?, ?> parse(final InstanceIdentifierContext<?> iiContext, final Document doc)
+            throws XMLStreamException, IOException, ParserConfigurationException, SAXException, URISyntaxException {
         final SchemaNode schemaNodeContext = iiContext.getSchemaNode();
         DataSchemaNode schemaNode = null;
         if (schemaNodeContext instanceof RpcDefinition) {
@@ -111,16 +118,17 @@ public class TestRestconfUtils {
                 }
             }
         }
-        final DomToNormalizedNodeParserFactory parserFactory = DomToNormalizedNodeParserFactory
-                .getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, iiContext.getSchemaContext());
 
-        if (schemaNode instanceof ContainerSchemaNode) {
-            return parserFactory.getContainerNodeParser().parse(Collections.singletonList(doc.getDocumentElement()),
-                    (ContainerSchemaNode) schemaNode);
-        } else if (schemaNode instanceof ListSchemaNode) {
-            final ListSchemaNode casted = (ListSchemaNode) schemaNode;
-            return parserFactory.getMapEntryNodeParser().parse(elements, casted);
-        } // FIXME : add another DataSchemaNode extensions e.g. LeafSchemaNode
+        final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+        final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+        final XmlParserStream xmlParser = XmlParserStream.create(writer, iiContext.getSchemaContext(), schemaNode);
+
+        if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode) {
+            xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(
+                    doc.getDocumentElement()))));
+            return resultHolder.getResult();
+        }
+        // FIXME : add another DataSchemaNode extensions e.g. LeafSchemaNode
         return null;
     }
 
index 164524b84350d6f3ed8390bafb861672afedbded..00dd603ce6e610a22a587f226a1d8a2f89813ebe 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.controller.sal.restconf.impl.nn.to.json.test;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
-import com.google.common.util.concurrent.UncheckedExecutionException;
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 import java.util.regex.Matcher;
@@ -53,7 +52,7 @@ public class NnToJsonLeafrefType extends AbstractBodyReaderTest {
         validateJson(".*\"lf2\":\\p{Blank}*\"121\".*", json);
     }
 
-    @Test(expected = UncheckedExecutionException.class)
+    @Test(expected = NullPointerException.class)
     public void leafrefToNonExistingLeafTest() throws Exception {
         toJson("/nn-to-json/leafref/xml/data_ref_to_non_existing_leaf.xml");
     }