Bug 7176 - Netconf MD-SAL connector is treating prefixed XML as invalid 83/48483/15
authorAlexis de Talhouët <adetalhouet@inocybe.com>
Fri, 18 Nov 2016 14:59:00 +0000 (09:59 -0500)
committerJakub Morvay <jmorvay@cisco.com>
Wed, 16 Aug 2017 08:16:06 +0000 (08:16 +0000)
Change-Id: I107b8f8076b106016069bec48a25738b08380a2a
Signed-off-by: Alexis de Talhouët <adetalhouet@inocybe.com>
netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditConfig.java
netconf/mdsal-netconf-connector/src/test/java/org/opendaylight/netconf/mdsal/connector/ops/NetconfMDSalMappingTest.java

index f7ad8b5ffa8488495025969958046e0892c3f189..7c86dd26b44b8307ca4e0f08a1619139f4af1359 100644 (file)
@@ -8,8 +8,10 @@
 
 package org.opendaylight.netconf.mdsal.connector.ops;
 
 
 package org.opendaylight.netconf.mdsal.connector.ops;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableMap;
 import java.net.URI;
 import java.net.URISyntaxException;
 import com.google.common.collect.ImmutableMap;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -260,7 +262,7 @@ public class EditConfig extends AbstractSingletonNetconfOperation {
     }
 
     private static Datastore extractTargetParameter(final XmlElement operationElement) throws DocumentedException {
     }
 
     private static Datastore extractTargetParameter(final XmlElement operationElement) throws DocumentedException {
-        final NodeList elementsByTagName = operationElement.getDomElement().getElementsByTagName(TARGET_KEY);
+        final NodeList elementsByTagName = getElementsByTagName(operationElement, TARGET_KEY);
         // Direct lookup instead of using XmlElement class due to performance
         if (elementsByTagName.getLength() == 0) {
             final Map<String, String> errorInfo = ImmutableMap.of("bad-attribute", TARGET_KEY, "bad-element",
         // Direct lookup instead of using XmlElement class due to performance
         if (elementsByTagName.getLength() == 0) {
             final Map<String, String> errorInfo = ImmutableMap.of("bad-attribute", TARGET_KEY, "bad-element",
@@ -278,7 +280,7 @@ public class EditConfig extends AbstractSingletonNetconfOperation {
     }
 
     private static ModifyAction getDefaultOperation(final XmlElement operationElement) throws DocumentedException {
     }
 
     private static ModifyAction getDefaultOperation(final XmlElement operationElement) throws DocumentedException {
-        final NodeList elementsByTagName = operationElement.getDomElement().getElementsByTagName(DEFAULT_OPERATION_KEY);
+        final NodeList elementsByTagName = getElementsByTagName(operationElement, DEFAULT_OPERATION_KEY);
         if (elementsByTagName.getLength() == 0) {
             return ModifyAction.MERGE;
         } else if (elementsByTagName.getLength() > 1) {
         if (elementsByTagName.getLength() == 0) {
             return ModifyAction.MERGE;
         } else if (elementsByTagName.getLength() > 1) {
@@ -303,6 +305,21 @@ public class EditConfig extends AbstractSingletonNetconfOperation {
         return childNode.get();
     }
 
         return childNode.get();
     }
 
+    @VisibleForTesting
+    static NodeList getElementsByTagName(final XmlElement operationElement, final String key) throws
+            DocumentedException {
+        final Element element = operationElement.getDomElement();
+        final NodeList elementsByTagName;
+
+        if (Strings.isNullOrEmpty(element.getPrefix())) {
+            elementsByTagName = element.getElementsByTagName(key);
+        } else {
+            elementsByTagName = element.getElementsByTagNameNS(operationElement.getNamespace(), key);
+        }
+
+        return elementsByTagName;
+    }
+
     @Override
     protected String getOperationName() {
         return OPERATION_NAME;
     @Override
     protected String getOperationName() {
         return OPERATION_NAME;
index 4d53fa3999b22493b98e3703176d2832d09d1cbc..d44bc8482eea020d7e41e88253957f349754aaa7 100644 (file)
@@ -32,9 +32,11 @@ import javax.xml.transform.stream.StreamResult;
 import org.custommonkey.xmlunit.DetailedDiff;
 import org.custommonkey.xmlunit.Diff;
 import org.custommonkey.xmlunit.XMLUnit;
 import org.custommonkey.xmlunit.DetailedDiff;
 import org.custommonkey.xmlunit.Diff;
 import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.cluster.databroker.ConcurrentDOMDataBroker;
 import org.opendaylight.controller.config.util.xml.DocumentedException;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.cluster.databroker.ConcurrentDOMDataBroker;
 import org.opendaylight.controller.config.util.xml.DocumentedException;
@@ -69,12 +71,14 @@ import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 public class NetconfMDSalMappingTest {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfMDSalMappingTest.class);
 
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 public class NetconfMDSalMappingTest {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfMDSalMappingTest.class);
 
+    private static final String TARGET_KEY = "target";
     private static final String RPC_REPLY_ELEMENT = "rpc-reply";
     private static final String DATA_ELEMENT = "data";
     private static final String FILTER_NODE = "filter";
     private static final String RPC_REPLY_ELEMENT = "rpc-reply";
     private static final String DATA_ELEMENT = "data";
     private static final String FILTER_NODE = "filter";
@@ -329,11 +333,11 @@ public class NetconfMDSalMappingTest {
     @Test
     public void testAugmentedContainerReplace() throws Exception {
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_empty_modules_create.xml"),
     @Test
     public void testAugmentedContainerReplace() throws Exception {
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_empty_modules_create.xml"),
-            RPC_REPLY_OK);
+                RPC_REPLY_OK);
         verifyResponse(commit(), RPC_REPLY_OK);
 
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_augmented_container_replace.xml"),
         verifyResponse(commit(), RPC_REPLY_OK);
 
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_augmented_container_replace.xml"),
-            RPC_REPLY_OK);
+                RPC_REPLY_OK);
         verifyResponse(commit(), RPC_REPLY_OK);
 
         deleteDatastore();
         verifyResponse(commit(), RPC_REPLY_OK);
 
         deleteDatastore();
@@ -342,11 +346,11 @@ public class NetconfMDSalMappingTest {
     @Test
     public void testLeafFromAugmentReplace() throws Exception {
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_empty_modules_create.xml"),
     @Test
     public void testLeafFromAugmentReplace() throws Exception {
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_empty_modules_create.xml"),
-            RPC_REPLY_OK);
+                RPC_REPLY_OK);
         verifyResponse(commit(), RPC_REPLY_OK);
 
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_leaf_from_augment_replace.xml"),
         verifyResponse(commit(), RPC_REPLY_OK);
 
         verifyResponse(edit("messages/mapping/editConfigs/editConfig_leaf_from_augment_replace.xml"),
-            RPC_REPLY_OK);
+                RPC_REPLY_OK);
         verifyResponse(commit(), RPC_REPLY_OK);
 
         deleteDatastore();
         verifyResponse(commit(), RPC_REPLY_OK);
 
         deleteDatastore();
@@ -538,6 +542,61 @@ public class NetconfMDSalMappingTest {
         deleteDatastore();
     }
 
         deleteDatastore();
     }
 
+    @Test
+    public void testEditConfigGetElementByTagName() throws Exception {
+        EditConfig editConfig = new EditConfig("test_edit-config", Mockito.mock(CurrentSchemaContext.class),
+                Mockito.mock(TransactionProvider.class));
+
+        String stringWithoutPrefix =
+                "<rpc xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"0\">\n"
+                        + "  <edit-config>\n"
+                        + "    <target>\n"
+                        + "      <candidate/>\n"
+                        + "    </target>\n"
+                        + "  </edit-config>\n"
+                        + "</rpc>";
+        XmlElement xe = getXmlElement(stringWithoutPrefix);
+        NodeList nodeList = editConfig.getElementsByTagName(xe, TARGET_KEY);
+        Assert.assertEquals(1, nodeList.getLength());
+
+        String stringWithPrefix =
+                "<nc:rpc xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"0\">\n"
+                        + "  <nc:edit-config>\n"
+                        + "    <nc:target>\n"
+                        + "      <nc:candidate/>\n"
+                        + "    </nc:target>\n"
+                        + "  </nc:edit-config>\n"
+                        + "</nc:rpc>";
+
+        xe = getXmlElement(stringWithPrefix);
+        nodeList = editConfig.getElementsByTagName(xe, TARGET_KEY);
+        Assert.assertEquals(1, nodeList.getLength());
+
+        String stringWithoutTarget =
+                "<nc:rpc xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"0\">\n"
+                        + "  <nc:edit-config>\n"
+                        + "    <nc:target>\n"
+                        + "    </nc:target>\n"
+                        + "  </nc:edit-config>\n"
+                        + "</nc:rpc>";
+        xe = getXmlElement(stringWithoutTarget);
+
+        try {
+            nodeList = editConfig.getElementsByTagName(xe, TARGET_KEY);
+            XmlElement.fromDomElement((Element) nodeList.item(0)).getOnlyChildElement();
+            Assert.fail("Not specified target, we should fail");
+        } catch (DocumentedException documentedException) {
+            // Ignore
+        }
+
+    }
+
+    private XmlElement getXmlElement(final String elementAsString) throws Exception {
+        Document document = XmlUtil.readXmlToDocument(elementAsString);
+        Element element = document.getDocumentElement();
+        return XmlElement.fromDomElement(element);
+    }
+
     @Test
     public void testReplaceMapEntry() throws Exception {
         verifyResponse(edit("messages/mapping/editConfigs/edit-config-replace-map-entry.xml"), RPC_REPLY_OK);
     @Test
     public void testReplaceMapEntry() throws Exception {
         verifyResponse(edit("messages/mapping/editConfigs/edit-config-replace-map-entry.xml"), RPC_REPLY_OK);