Bug 8071 - Do not fail on modules with invalid revision during 11/54411/9
authormiroslav.kovac <miroslav.kovac@pantheon.tech>
Thu, 6 Apr 2017 08:47:59 +0000 (10:47 +0200)
committerMiroslav Kovac <miroslav.kovac@pantheon.tech>
Thu, 11 May 2017 12:14:43 +0000 (12:14 +0000)
           resolution of ietf-netconf-yang-library/modules-state node

After parsing xml with invalid revision string it failed instead
of returning only modules with correct revision.

It reads an xml, creates a new xml string using only modules with
correct revision and logs the ones that has wrong revision. New xml
string will be parsed to normalized node.

Change-Id: Ie51163864f3547560840cb7d52ea8762437a6b1e
Signed-off-by: miroslav.kovac <miroslav.kovac@pantheon.tech>
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/LibraryModulesSchemas.java
netconf/sal-netconf-connector/src/test/resources/yang-library.xml

index 9f59dba6957fd06c609249b9be94cf1c5b30efb6..f00668a09328e026104de66c989851af0f70ea2b 100644 (file)
@@ -22,6 +22,7 @@ import com.google.gson.stream.JsonReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.StringWriter;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URI;
@@ -32,6 +33,14 @@ import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
+import java.util.regex.Pattern;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
 import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
@@ -41,6 +50,7 @@ import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransform
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.ModulesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.module.list.Module;
+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.ContainerNode;
@@ -62,6 +72,9 @@ import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 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.xml.sax.SAXException;
 
 /**
@@ -71,7 +84,7 @@ import org.xml.sax.SAXException;
 public class LibraryModulesSchemas implements NetconfDeviceSchemas {
 
     private static final Logger LOG = LoggerFactory.getLogger(LibraryModulesSchemas.class);
-
+    private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})");
     private static final SchemaContext LIBRARY_CONTEXT;
 
     static {
@@ -113,6 +126,7 @@ public class LibraryModulesSchemas implements NetconfDeviceSchemas {
 
     /**
      * Resolves URLs with YANG schema resources from modules-state. Uses basic http authenticaiton
+     *
      * @param url URL pointing to yang library
      * @return Resolved URLs with YANG schema resources for all yang modules from yang library
      */
@@ -306,18 +320,38 @@ public class LibraryModulesSchemas implements NetconfDeviceSchemas {
     }
 
     private static Optional<NormalizedNode<?, ?>> readXml(final InputStream in) {
-        // TODO one module node with bad revision will fail parsing of whole modules-state node
-        // we have to parse them one by one and just ignore modules with bad revisions
-        // See BUG 8071 https://bugs.opendaylight.org/show_bug.cgi?id=8071
         final DomToNormalizedNodeParserFactory parserFactory =
                 DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, LIBRARY_CONTEXT);
-
         try {
+            final DocumentBuilder docBuilder = UntrustedXML.newDocumentBuilder();
+
+            final Document read = docBuilder.parse(in);
+            final Document doc = docBuilder.newDocument();
+            final Element rootElement = doc.createElementNS("urn:ietf:params:xml:ns:yang:ietf-yang-library",
+                    "modules");
+            doc.appendChild(rootElement);
+
+            for (int i = 0; i < read.getElementsByTagName("revision").getLength(); i++) {
+                final String revision = read.getElementsByTagName("revision").item(i).getTextContent();
+                if (DATE_PATTERN.matcher(revision).find() || revision.isEmpty()) {
+                    final Node module = doc.importNode(read.getElementsByTagName("module").item(i), true);
+                    rootElement.appendChild(module);
+                } else {
+                    LOG.warn("Xml contains wrong revision - {} - on module {}", revision,
+                            read.getElementsByTagName("module").item(i).getTextContent());
+                }
+            }
+
+            final Transformer transformer = TransformerFactory.newInstance().newTransformer();
+            final StringWriter sw = new StringWriter();
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+            transformer.transform(new DOMSource(doc), new StreamResult(sw));
             final NormalizedNode<?, ?> parsed =
-                    parserFactory.getContainerNodeParser().parse(Collections.singleton(XmlUtil.readXmlToElement(in)),
+                    parserFactory.getContainerNodeParser()
+                            .parse(Collections.singleton(XmlUtil.readXmlToElement(sw.toString())),
                             (ContainerSchemaNode) LIBRARY_CONTEXT.getDataChildByName(ModulesState.QNAME));
             return Optional.of(parsed);
-        } catch (IOException | SAXException e) {
+        } catch (final SAXException | IOException | TransformerException e) {
             LOG.warn("Unable to parse yang library xml content", e);
         }
 
index c60345093317ca6821214df8d827899ddb540587..b11686c06307a5ab60b06f6176e0c57f70cc7dee 100644 (file)
             http://localhost:8181/yanglib/schemas/module-without-revision/
         </schema>
     </module>
+    <module>
+        <name>module-with-wrong-revision</name>
+        <revision>2014-004-08</revision>
+        <namespace>namespace</namespace>
+        <schema>
+            http://localhost:8181/yanglib/schemas/module-with-revision/2014-04-08
+        </schema>
+    </module>
 </modules>
\ No newline at end of file