Merge changes I6575ddd8,I4b78f51d,I0a0441e6
authorJakub Morvay <jmorvay@cisco.com>
Thu, 20 Jul 2017 15:31:38 +0000 (15:31 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 20 Jul 2017 15:31:38 +0000 (15:31 +0000)
* changes:
  Cleanup Precondtions in singleton
  Cleanup Throwable catches
  Cleanup NetconfDevice

20 files changed:
netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditConfig.java
netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditOperationNormalizedNodeStreamWriter.java [new file with mode: 0644]
netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditOperationStrategyProvider.java [deleted file]
netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/RuntimeRpc.java
netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/FailedNetconfMessage.java [new file with mode: 0644]
netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/NetconfMessage.java
netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/NetconfXMLToMessageDecoder.java
netconf/netconf-netty-util/src/test/java/org/opendaylight/netconf/nettyutil/handler/NetconfXMLToMessageDecoderTest.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/LibraryModulesSchemas.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfDeviceCommunicator.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/util/NetconfMessageTransformUtil.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/NetconfStateSchemasTest.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/NetconfToNotificationTest.java
netconf/tools/netconf-cli/src/main/java/org/opendaylight/netconf/cli/reader/impl/AnyXmlReader.java
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 d1998b2b12e33689847d4a7270c2cd67e96d9293..12e34b5c803333e46bc05dbbc44d44f41dfb84fa 100644 (file)
@@ -11,9 +11,9 @@ package org.opendaylight.netconf.mdsal.connector.ops;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
+import java.io.StringReader;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.Collections;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
@@ -33,6 +33,7 @@ import org.opendaylight.netconf.mdsal.connector.CurrentSchemaContext;
 import org.opendaylight.netconf.mdsal.connector.TransactionProvider;
 import org.opendaylight.netconf.mdsal.connector.ops.DataTreeChangeTracker.DataTreeChange;
 import org.opendaylight.netconf.util.mapping.AbstractSingletonNetconfOperation;
+import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -40,9 +41,10 @@ import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+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.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -93,10 +95,8 @@ public class EditConfig extends AbstractSingletonNetconfOperation {
             final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element).get();
 
             final DataTreeChangeTracker changeTracker = new DataTreeChangeTracker(defaultAction);
-            final DomToNormalizedNodeParserFactory.BuildingStrategyProvider editOperationStrategyProvider =
-                    new EditOperationStrategyProvider(changeTracker);
 
-            parseIntoNormalizedNode(schemaNode, element, editOperationStrategyProvider);
+            parseIntoNormalizedNode(schemaNode, element, changeTracker);
             executeOperations(changeTracker);
         }
 
@@ -206,23 +206,27 @@ public class EditConfig extends AbstractSingletonNetconfOperation {
         }
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private NormalizedNode<?, ?> parseIntoNormalizedNode(final DataSchemaNode schemaNode, final XmlElement element,
-            final DomToNormalizedNodeParserFactory.BuildingStrategyProvider editOperationStrategyProvider) {
-        if (schemaNode instanceof ContainerSchemaNode) {
-            return DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(),
-                            schemaContext.getCurrentContext(), editOperationStrategyProvider)
-                    .getContainerNodeParser()
-                    .parse(Collections.singletonList(element.getDomElement()), (ContainerSchemaNode) schemaNode);
-        } else if (schemaNode instanceof ListSchemaNode) {
-            return DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(),
-                            schemaContext.getCurrentContext(), editOperationStrategyProvider)
-                    .getMapNodeParser()
-                    .parse(Collections.singletonList(element.getDomElement()), (ListSchemaNode) schemaNode);
-        } else {
+            final DataTreeChangeTracker changeTracker) throws DocumentedException {
+        if (!(schemaNode instanceof ContainerSchemaNode) && !(schemaNode instanceof ListSchemaNode)) {
             //this should never happen since edit-config on any other node type should not be possible nor makes sense
             LOG.debug("DataNode from module is not ContainerSchemaNode nor ListSchemaNode, aborting..");
+            throw new UnsupportedOperationException("implement exception if parse fails");
         }
-        throw new UnsupportedOperationException("implement exception if parse fails");
+
+        final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+        final NormalizedNodeStreamWriter writer = new EditOperationNormalizedNodeStreamWriter(resultHolder,
+                changeTracker);
+        final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext.getCurrentContext(), schemaNode);
+        try {
+            xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(element))));
+        } catch (final Exception ex) {
+            throw new NetconfDocumentedException("Error parsing input: " + ex.getMessage(), ex, ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE, ErrorSeverity.ERROR);
+        }
+
+        return resultHolder.getResult();
     }
 
     private Optional<DataSchemaNode> getSchemaNodeFromNamespace(final String namespace, final XmlElement element)
diff --git a/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditOperationNormalizedNodeStreamWriter.java b/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditOperationNormalizedNodeStreamWriter.java
new file mode 100644 (file)
index 0000000..7a98342
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.mdsal.connector.ops;
+
+import java.util.ArrayList;
+import java.util.Map;
+import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditConfigInput;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamAttributeWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+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.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+
+final class EditOperationNormalizedNodeStreamWriter extends ImmutableNormalizedNodeStreamWriter
+        implements NormalizedNodeStreamAttributeWriter {
+    private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(), null,
+            XmlNetconfConstants.OPERATION_ATTR_KEY);
+
+    private final DataTreeChangeTracker dataTreeChangeTracker;
+
+    EditOperationNormalizedNodeStreamWriter(final NormalizedNodeResult result,
+            final DataTreeChangeTracker dataTreeChangeTracker) {
+        super(result);
+        this.dataTreeChangeTracker = dataTreeChangeTracker;
+    }
+
+    @Override
+    public void leafNode(final NodeIdentifier name, final Object value, final Map<QName, String> attributes) {
+        super.leafNode(name, value);
+
+        final String operation = attributes.get(OPERATION_ATTRIBUTE);
+        if (operation == null) {
+            return;
+        }
+
+        final ModifyAction action = ModifyAction.fromXmlValue(operation);
+        if (dataTreeChangeTracker.getDeleteOperationTracker() == 0
+                && dataTreeChangeTracker.getRemoveOperationTracker() == 0) {
+            if (!action.equals(dataTreeChangeTracker.peekAction())) {
+                final LeafNode<Object> node = ImmutableNodes.leafNode(name, value);
+                dataTreeChangeTracker.pushPath(name);
+                dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
+                        new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
+                getCurrent().removeChild(dataTreeChangeTracker.popPath());
+            }
+        }
+    }
+
+    @Override
+    public void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
+        super.startLeafSet(name, childSizeHint);
+        dataTreeChangeTracker.pushPath(name);
+    }
+
+    @Override
+    public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) {
+        super.startOrderedLeafSet(name, childSizeHint);
+        dataTreeChangeTracker.pushPath(name);
+    }
+
+    @Override
+    public void leafSetEntryNode(final QName name, final Object value, final Map<QName, String> attributes) {
+        super.leafSetEntryNode(name, value);
+        final String operation = attributes.get(OPERATION_ATTRIBUTE);
+        if (operation == null) {
+            return;
+        }
+
+        ModifyAction action = ModifyAction.fromXmlValue(operation);
+        if (dataTreeChangeTracker.getDeleteOperationTracker() == 0
+                && dataTreeChangeTracker.getRemoveOperationTracker() == 0) {
+            if (!action.equals(dataTreeChangeTracker.peekAction())) {
+                final LeafSetEntryNode<?> node = Builders.leafSetEntryBuilder().withNodeIdentifier(
+                        new NodeWithValue(name, value)).withValue(value).build();
+                dataTreeChangeTracker.pushPath(node.getIdentifier());
+                dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
+                        new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
+                getCurrent().removeChild(dataTreeChangeTracker.popPath());
+            }
+        }
+    }
+
+    @Override
+    public void startContainerNode(final NodeIdentifier name, final int childSizeHint,
+            final Map<QName, String> attributes) {
+        super.startContainerNode(name, childSizeHint);
+        trackDataContainerNode(name, attributes);
+    }
+
+    @Override
+    public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint,
+            final Map<QName, String> attributes) {
+        super.startYangModeledAnyXmlNode(name, childSizeHint);
+        trackDataContainerNode(name, attributes);
+    }
+
+    @Override
+    public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) {
+        super.startUnkeyedList(name, childSizeHint);
+        dataTreeChangeTracker.pushPath(name);
+    }
+
+    @Override
+    public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint,
+            final Map<QName, String> attributes) {
+        super.startUnkeyedListItem(name, childSizeHint);
+        trackDataContainerNode(name, attributes);
+    }
+
+    @Override
+    public void startMapNode(final NodeIdentifier name, final int childSizeHint) {
+        super.startMapNode(name, childSizeHint);
+        dataTreeChangeTracker.pushPath(name);
+    }
+
+    @Override
+    public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) {
+        super.startOrderedMapNode(name, childSizeHint);
+        dataTreeChangeTracker.pushPath(name);
+    }
+
+    @Override
+    public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint,
+            final Map<QName, String> attributes)  {
+        super.startMapEntryNode(identifier, childSizeHint);
+        trackDataContainerNode(identifier, attributes);
+    }
+
+    @Override
+    public void startAugmentationNode(final AugmentationIdentifier identifier) {
+        super.startAugmentationNode(identifier);
+        trackMixinNode(identifier);
+    }
+
+    @Override
+    public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) {
+        super.startChoiceNode(name, childSizeHint);
+        trackMixinNode(name);
+    }
+
+    // for augments and choices
+    private void trackMixinNode(final PathArgument identifier) {
+        dataTreeChangeTracker.pushPath(identifier);
+        dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
+                ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
+    }
+
+    // for containers, (unkeyed) list entries and yang-modeled-anyxmls
+    private void trackDataContainerNode(final PathArgument identifier, final Map<QName, String> attributes) {
+        dataTreeChangeTracker.pushPath(identifier);
+        final String operation = attributes.get(OPERATION_ATTRIBUTE);
+        if (operation != null) {
+            dataTreeChangeTracker.pushAction(ModifyAction.fromXmlValue(operation));
+        } else {
+            dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
+                    ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
+        }
+    }
+
+    @Override
+    @SuppressWarnings({"rawtypes","unchecked"})
+    public void endNode() {
+        final NormalizedNodeContainerBuilder finishedBuilder = getBuilders().peek();
+        final NormalizedNode<PathArgument, ?> product = finishedBuilder.build();
+        super.endNode();
+
+        // for augments, choices, containers, (unkeyed) list entries and yang-modeled-anyxmls
+        if (finishedBuilder instanceof DataContainerNodeBuilder) {
+            final ModifyAction currentAction = dataTreeChangeTracker.popAction();
+
+            //if we know that we are going to delete a parent node just complete the entire subtree
+            if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
+                    || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
+                dataTreeChangeTracker.popPath();
+            } else {
+                //if parent and current actions don't match create a DataTreeChange and add it to the change list
+                //don't add a new child to the parent node
+                if (!currentAction.equals(dataTreeChangeTracker.peekAction())) {
+                    dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(product,
+                            currentAction, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
+                    if (getCurrent() instanceof NormalizedNodeResultBuilder) {
+                        dataTreeChangeTracker.popPath();
+                        return;
+                    }
+                    getCurrent().removeChild(dataTreeChangeTracker.popPath());
+                } else {
+                    dataTreeChangeTracker.popPath();
+                    return;
+                }
+            }
+        }
+
+        // for (ordered) leaf-lists, (ordered) lists and unkeyed lists
+        if (finishedBuilder instanceof CollectionNodeBuilder) {
+            dataTreeChangeTracker.popPath();
+        }
+    }
+}
diff --git a/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditOperationStrategyProvider.java b/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditOperationStrategyProvider.java
deleted file mode 100644 (file)
index a29e37d..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.netconf.mdsal.connector.ops;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditConfigInput;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ExtensibleParser;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
-
-class EditOperationStrategyProvider extends DomToNormalizedNodeParserFactory.BuildingStrategyProvider {
-
-    private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(), null,
-            XmlNetconfConstants.OPERATION_ATTR_KEY);
-
-    private final DataTreeChangeTracker changeTracker;
-
-    EditOperationStrategyProvider(final DataTreeChangeTracker changeTracker) {
-        this.changeTracker = changeTracker;
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifier, LeafNode<?>> forLeaf() {
-        return new NetconfOperationLeafStrategy(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifier, ContainerNode> forContainer() {
-        return new NetconfOperationContainerStrategy<>(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifier, MapNode> forMap() {
-        return new NetconfOperationCollectionStrategy<>(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> forLeafSetEntry() {
-        return new NetconfOperationLeafSetEntryStrategy(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifierWithPredicates, MapEntryNode> forMapEntry() {
-        return new NetconfOperationContainerStrategy<>(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifier, OrderedMapNode> forOrderedList() {
-        return new NetconfOperationCollectionStrategy<>(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifier, UnkeyedListEntryNode> forUnkeyedListEntry() {
-        return new NetconfOperationContainerStrategy<>(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifier, UnkeyedListNode> forUnkeyedList() {
-        return new NetconfOperationCollectionStrategy<>(changeTracker);
-    }
-
-    @Override
-    protected ExtensibleParser.BuildingStrategy<NodeIdentifier, ChoiceNode> forChoice() {
-        return new NetconfOperationContainerStrategy<>(changeTracker);
-    }
-
-    @Override
-    public ExtensibleParser.BuildingStrategy<AugmentationIdentifier, AugmentationNode> forAugmentation() {
-        return new NetconfOperationContainerStrategy<>(changeTracker);
-    }
-
-    private static class NetconfOperationCollectionStrategy<N extends NormalizedNode<NodeIdentifier, ?>>
-            implements ExtensibleParser.BuildingStrategy<NodeIdentifier, N> {
-        private final DataTreeChangeTracker changeTracker;
-
-        NetconfOperationCollectionStrategy(final DataTreeChangeTracker changeTracker) {
-            this.changeTracker = changeTracker;
-        }
-
-        @Nullable
-        @Override
-        public N build(final NormalizedNodeBuilder<NodeIdentifier, ?, N> builder) {
-            changeTracker.popPath();
-            return builder.build();
-        }
-
-        @Override
-        public void prepareAttributes(
-                final Map<QName, String> attributes,
-                final NormalizedNodeBuilder<NodeIdentifier, ?, N> containerBuilder) {
-            changeTracker.pushPath(containerBuilder.build().getIdentifier());
-        }
-    }
-
-    public static final class NetconfOperationLeafStrategy
-            implements ExtensibleParser.BuildingStrategy<NodeIdentifier, LeafNode<?>> {
-
-        private final DataTreeChangeTracker dataTreeChangeTracker;
-
-        NetconfOperationLeafStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
-            this.dataTreeChangeTracker = dataTreeChangeTracker;
-        }
-
-        @Nullable
-        @Override
-        public LeafNode<?> build(
-                final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> builder) {
-            LeafNode<?> node = builder.build();
-            String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
-            if (operation == null) {
-                return node;
-            }
-
-            if (builder instanceof AttributesBuilder<?>) {
-                ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
-            }
-
-            node = builder.build();
-
-            ModifyAction action = ModifyAction.fromXmlValue(operation);
-            if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
-                    || dataTreeChangeTracker .getRemoveOperationTracker() > 0) {
-                return node;
-            }
-
-            if (action.equals(dataTreeChangeTracker.peekAction())) {
-                return node;
-            }
-
-            dataTreeChangeTracker.pushPath(node.getIdentifier());
-            dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
-                new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
-            dataTreeChangeTracker.popPath();
-            return null;
-        }
-
-        @Override
-        public void prepareAttributes(
-                final Map<QName, String> attributes,
-                final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> containerBuilder) {
-            // Noop
-        }
-    }
-
-    public static final class NetconfOperationLeafSetEntryStrategy
-            implements ExtensibleParser.BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> {
-
-        private final DataTreeChangeTracker dataTreeChangeTracker;
-
-        NetconfOperationLeafSetEntryStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
-            this.dataTreeChangeTracker = dataTreeChangeTracker;
-        }
-
-        @Nullable
-        @Override
-        public LeafSetEntryNode<?> build(final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> builder) {
-            LeafSetEntryNode<?> node = builder.build();
-            String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
-            if (operation == null) {
-                return node;
-            }
-
-            if (builder instanceof AttributesBuilder<?>) {
-                ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
-            }
-
-            node = builder.build();
-
-            ModifyAction action = ModifyAction.fromXmlValue(operation);
-            if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
-                    || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
-                return node;
-            }
-
-            if (action.equals(dataTreeChangeTracker.peekAction())) {
-                return node;
-            }
-
-            dataTreeChangeTracker.pushPath(node.getIdentifier());
-            dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
-                new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
-            dataTreeChangeTracker.popPath();
-            return null;
-        }
-
-        @Override
-        public void prepareAttributes(
-                final Map<QName, String> attributes,
-                final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> containerBuilder) {
-        }
-    }
-
-    public static final class NetconfOperationContainerStrategy<P extends PathArgument, N
-            extends DataContainerNode<P>> implements ExtensibleParser.BuildingStrategy<P, N> {
-
-        private final DataTreeChangeTracker dataTreeChangeTracker;
-
-        NetconfOperationContainerStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
-            this.dataTreeChangeTracker = dataTreeChangeTracker;
-        }
-
-        @Nullable
-        @Override
-        public N build(final NormalizedNodeBuilder<P, ?, N> builder) {
-            if (builder instanceof AttributesBuilder<?>) {
-                ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
-            }
-
-            final N node = builder.build();
-            final ModifyAction currentAction = dataTreeChangeTracker.popAction();
-
-            //if we know that we are going to delete a parent node just complete the entire subtree
-            if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
-                    || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
-                dataTreeChangeTracker.popPath();
-                return node;
-            }
-
-            if (currentAction.equals(dataTreeChangeTracker.peekAction())) {
-                dataTreeChangeTracker.popPath();
-                return node;
-            }
-
-            //if parent and current actions dont match create a DataTreeChange and add it to the change list
-            //dont add a new child to the parent node
-            dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node,
-                currentAction, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
-            dataTreeChangeTracker.popPath();
-            return null;
-        }
-
-        @Override
-        public void prepareAttributes(final Map<QName, String> attributes,
-                                      final NormalizedNodeBuilder<P, ?, N> containerBuilder) {
-            dataTreeChangeTracker.pushPath(containerBuilder.build().getIdentifier());
-            final String operation = attributes.get(OPERATION_ATTRIBUTE);
-            if (operation != null) {
-                dataTreeChangeTracker.pushAction(ModifyAction.fromXmlValue(operation));
-            } else {
-                dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
-                        ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
-            }
-        }
-    }
-}
index 2b18e2c2c569e1624a51ddaf15e5f8e1f959827d..18923edb7b4d21f81a82918d2d441889495c3e02 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Optional;
 import com.google.common.base.Throwables;
 import com.google.common.util.concurrent.CheckedFuture;
 import java.io.IOException;
+import java.io.StringReader;
 import java.net.URI;
 import java.util.Collection;
 import java.util.Collections;
@@ -31,19 +32,22 @@ import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.netconf.api.NetconfDocumentedException;
 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.netconf.mdsal.connector.CurrentSchemaContext;
 import org.opendaylight.netconf.util.mapping.AbstractSingletonNetconfOperation;
+import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
+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.SchemaOrderedNormalizedNodeWriter;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
@@ -254,12 +258,26 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation {
      * @param input   input container schema node, or null if rpc does not take any input
      * @return parsed rpc into normalized node, or null if input schema is null
      */
+    @SuppressWarnings("checkstyle:IllegalCatch")
     @Nullable
-    private NormalizedNode<?, ?> rpcToNNode(final XmlElement element, @Nullable final ContainerSchemaNode input) {
-        return input.getChildNodes().isEmpty() ? null : DomToNormalizedNodeParserFactory
-                .getInstance(DomUtils.defaultValueCodecProvider(), schemaContext.getCurrentContext())
-                .getContainerNodeParser()
-                .parse(Collections.singletonList(element.getDomElement()), input);
+    private NormalizedNode<?, ?> rpcToNNode(final XmlElement element, @Nullable final ContainerSchemaNode input)
+            throws DocumentedException {
+        if (input.getChildNodes().isEmpty()) {
+            return null;
+        }
+
+        final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+        final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+        final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext.getCurrentContext(), input);
+
+        try {
+            xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(element))));
+        } catch (final Exception ex) {
+            throw new NetconfDocumentedException("Error parsing input: " + ex.getMessage(), ex, ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE, ErrorSeverity.ERROR);
+        }
+
+        return resultHolder.getResult();
     }
 
 }
diff --git a/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/FailedNetconfMessage.java b/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/FailedNetconfMessage.java
new file mode 100644 (file)
index 0000000..e7a1cad
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017 Bell Canada. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.api;
+
+/**
+ * FailedNetconfMessage represents a wrapper around NetconfMessage.
+ */
+public class FailedNetconfMessage extends NetconfMessage {
+
+    private Throwable exception;
+
+    public FailedNetconfMessage(final Throwable exception) {
+        this.exception = exception;
+    }
+
+    public Throwable getException() {
+        return this.exception;
+    }
+}
index 957c0475a50d3143860f924e7b9f3f5919aefa22..a60a880bf4d70cd04963e502f3e95476e98a6bb2 100644 (file)
@@ -41,6 +41,11 @@ public class NetconfMessage {
 
     private final Document doc;
 
+    public NetconfMessage() {
+        // Required for FailedNetconfMessage
+        this.doc = null;
+    }
+
     public NetconfMessage(final Document doc) {
         this.doc = doc;
     }
index 68dba39d63bccae8f2e18280116e722e317d9258..60a8dd1fb0265312c26a53924eee515943564aa2 100644 (file)
@@ -16,10 +16,12 @@ import io.netty.handler.codec.ByteToMessageDecoder;
 import java.io.IOException;
 import java.util.List;
 import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 
 public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToMessageDecoder.class);
@@ -68,7 +70,16 @@ public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
             }
         }
         if (in.isReadable()) {
-            out.add(new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in))));
+            NetconfMessage msg;
+
+            try {
+                msg = new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in)));
+            } catch (SAXParseException exception) {
+                LOG.error("Failed to parse received message", exception);
+                msg = new FailedNetconfMessage(exception);
+            }
+
+            out.add(msg);
         } else {
             LOG.debug("No more content in incoming buffer.");
         }
index ea5bd62df6c6991ab5455486f52475bb658519f5..8600253f36c0ff39506fb5b4c6e7434195577f43 100644 (file)
@@ -9,11 +9,13 @@
 package org.opendaylight.netconf.nettyutil.handler;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.google.common.collect.Lists;
 import io.netty.buffer.Unpooled;
 import java.util.ArrayList;
 import org.junit.Test;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
 import org.xml.sax.SAXParseException;
 
 public class NetconfXMLToMessageDecoderTest {
@@ -57,12 +59,15 @@ public class NetconfXMLToMessageDecoderTest {
         assertEquals(1, out.size());
     }
 
-    @Test(expected = SAXParseException.class)
+    @Test
     public void testDecodeGibberish() throws Exception {
         /* Test that we reject inputs where we cannot find the xml start '<' character */
         final ArrayList<Object> out = Lists.newArrayList();
         new NetconfXMLToMessageDecoder().decode(null, Unpooled.wrappedBuffer("\r\n?xml version>".getBytes()), out);
         assertEquals(1, out.size());
+        assertTrue(FailedNetconfMessage.class.isInstance(out.get(0)));
+        assertTrue(((FailedNetconfMessage) out.get(0))
+                .getException().getClass().isAssignableFrom(SAXParseException.class));
     }
 
     @Test
index f00668a09328e026104de66c989851af0f70ea2b..8a4ea7efd7284c1c66cecb14fa3edc8e2a193eaf 100644 (file)
@@ -22,7 +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.io.StringReader;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URI;
@@ -35,12 +35,6 @@ 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;
@@ -61,12 +55,10 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 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.transform.dom.parser.DomToNormalizedNodeParserFactory;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
@@ -75,7 +67,6 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
 
 /**
  * Holds URLs with YANG schema resources for all yang modules reported in
@@ -319,9 +310,8 @@ public class LibraryModulesSchemas implements NetconfDeviceSchemas {
                 ? Optional.of(resultHolder.getResult()) : Optional.<NormalizedNode<?, ?>>absent();
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private static Optional<NormalizedNode<?, ?>> readXml(final InputStream in) {
-        final DomToNormalizedNodeParserFactory parserFactory =
-                DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, LIBRARY_CONTEXT);
         try {
             final DocumentBuilder docBuilder = UntrustedXML.newDocumentBuilder();
 
@@ -342,16 +332,16 @@ public class LibraryModulesSchemas implements NetconfDeviceSchemas {
                 }
             }
 
-            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(sw.toString())),
-                            (ContainerSchemaNode) LIBRARY_CONTEXT.getDataChildByName(ModulesState.QNAME));
+            final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+            final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+            final XmlParserStream xmlParser = XmlParserStream.create(writer, LIBRARY_CONTEXT,
+                    LIBRARY_CONTEXT.getDataChildByName(ModulesState.QNAME));
+
+            xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(
+                    doc.getDocumentElement(), false))));
+            final NormalizedNode<?, ?> parsed = resultHolder.getResult();
             return Optional.of(parsed);
-        } catch (final SAXException | IOException | TransformerException e) {
+        } catch (final Exception e) {
             LOG.warn("Unable to parse yang library xml content", e);
         }
 
index 83ee068eb65e77c9e76ba6f434946e89408823d5..b55b42f669418683cdbabff42ee349b96cbc6ac6 100644 (file)
@@ -24,6 +24,7 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import org.opendaylight.controller.config.util.xml.XmlElement;
 import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
 import org.opendaylight.netconf.api.NetconfDocumentedException;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.api.NetconfTerminationReason;
@@ -291,6 +292,11 @@ public class NetconfDeviceCommunicator
 
         if (request != null) {
 
+            if (FailedNetconfMessage.class.isInstance(message)) {
+                request.future.set(NetconfMessageTransformUtil.toRpcResult((FailedNetconfMessage) message));
+                return;
+            }
+
             LOG.debug("{}: Message received {}", id, message);
 
             if (LOG.isTraceEnabled()) {
@@ -401,6 +407,10 @@ public class NetconfDeviceCommunicator
     }
 
     private static boolean isNotification(final NetconfMessage message) {
+        if (message.getDocument() == null) {
+            // We have no message, which mean we have a FailedNetconfMessage
+            return false;
+        }
         final XmlElement xmle = XmlElement.fromDomDocument(message.getDocument());
         return XmlNetconfConstants.NOTIFICATION_ELEMENT_NAME.equals(xmle.getName()) ;
     }
index 734abb7978b910f0d5c3bf0ca4a069926674026c..89d9c19850ec9c51121677d4843bccb9983dfe89 100644 (file)
@@ -16,6 +16,7 @@ import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 import java.io.IOException;
+import java.io.StringReader;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -26,6 +27,7 @@ import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.dom.DOMResult;
 import org.opendaylight.controller.config.util.xml.MissingNameSpaceException;
 import org.opendaylight.controller.config.util.xml.XmlElement;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.controller.md.sal.dom.api.DOMEvent;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
@@ -34,13 +36,16 @@ import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.netconf.sal.connect.util.MessageCounter;
+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;
 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.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+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.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
@@ -61,7 +66,8 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
     private final MessageCounter counter;
     private final Map<QName, RpcDefinition> mappedRpcs;
     private final Multimap<QName, NotificationDefinition> mappedNotifications;
-    private final DomToNormalizedNodeParserFactory parserFactory;
+
+    private final boolean strictParsing;
 
     public NetconfMessageTransformer(final SchemaContext schemaContext, final boolean strictParsing) {
         this(schemaContext, strictParsing, BaseSchema.BASE_NETCONF_CTX);
@@ -71,14 +77,14 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
                                      final BaseSchema baseSchema) {
         this.counter = new MessageCounter();
         this.schemaContext = schemaContext;
-        parserFactory = DomToNormalizedNodeParserFactory
-                .getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, schemaContext, strictParsing);
         mappedRpcs = Maps.uniqueIndex(schemaContext.getOperations(), SchemaNode::getQName);
         mappedNotifications = Multimaps.index(schemaContext.getNotifications(),
             node -> node.getQName().withoutRevision());
         this.baseSchema = baseSchema;
+        this.strictParsing = strictParsing;
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     @Override
     public synchronized DOMNotification toNotification(final NetconfMessage message) {
         final Map.Entry<Date, XmlElement> stripped = NetconfMessageTransformUtil.stripNotification(message);
@@ -103,9 +109,14 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
         final Element element = stripped.getValue().getDomElement();
         final ContainerNode content;
         try {
-            content = parserFactory.getContainerNodeParser().parse(Collections.singleton(element),
-                notificationAsContainerSchemaNode);
-        } catch (IllegalArgumentException e) {
+            final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+            final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+            final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext,
+                    notificationAsContainerSchemaNode, strictParsing);
+
+            xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(element))));
+            content = (ContainerNode) resultHolder.getResult();
+        } catch (final Exception e) {
             throw new IllegalArgumentException(String.format("Failed to parse notification %s", element), e);
         }
         return new NetconfDeviceNotification(content, stripped.getKey());
@@ -169,7 +180,7 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
                 || rpc.getNamespace().equals(NetconfMessageTransformUtil.CREATE_SUBSCRIPTION_RPC_QNAME.getNamespace());
     }
 
-
+    @SuppressWarnings("checkstyle:IllegalCatch")
     @Override
     public synchronized DOMRpcResult toRpcResult(final NetconfMessage message, final SchemaPath rpc) {
         final NormalizedNode<?, ?> normalizedNode;
@@ -181,9 +192,14 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
             final ContainerNode dataNode;
 
             try {
-                dataNode =
-                        parserFactory.getContainerNodeParser().parse(Collections.singleton(xmlData), schemaForDataRead);
-            } catch (IllegalArgumentException e) {
+                final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+                final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+                final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext, schemaForDataRead,
+                        strictParsing);
+
+                xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(xmlData))));
+                dataNode = (ContainerNode) resultHolder.getResult();
+            } catch (final Exception e) {
                 throw new IllegalArgumentException(String.format("Failed to parse data response %s", xmlData), e);
             }
 
@@ -216,9 +232,14 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
             } else {
                 final Element element = message.getDocument().getDocumentElement();
                 try {
-                    normalizedNode = parserFactory.getContainerNodeParser().parse(Collections.singleton(element),
-                        rpcDefinition.getOutput());
-                } catch (IllegalArgumentException e) {
+                    final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+                    final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+                    final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext,
+                            rpcDefinition.getOutput(), strictParsing);
+
+                    xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(element))));
+                    normalizedNode = resultHolder.getResult();
+                } catch (final Exception e) {
                     throw new IllegalArgumentException(String.format("Failed to parse RPC response %s", element), e);
                 }
             }
index 4cc4110653118a2b684b2aa0c42e132ae0e0219f..80566edcf3013418db90864b59ba9a1666e9612b 100644 (file)
@@ -28,6 +28,7 @@ import javax.xml.transform.dom.DOMSource;
 import org.opendaylight.controller.config.util.xml.DocumentedException;
 import org.opendaylight.controller.config.util.xml.XmlElement;
 import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
 import org.opendaylight.netconf.api.NetconfDocumentedException;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.notifications.NetconfNotification;
@@ -41,6 +42,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.not
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -404,4 +406,16 @@ public class NetconfMessageTransformUtil {
             }
         }
     }
+
+    public static RpcResult<NetconfMessage> toRpcResult(final FailedNetconfMessage message) {
+        return RpcResultBuilder.<NetconfMessage>failed()
+                .withRpcError(
+                        toRpcError(
+                                new NetconfDocumentedException(
+                                        message.getException().getMessage(),
+                                        DocumentedException.ErrorType.APPLICATION,
+                                        DocumentedException.ErrorTag.MALFORMED_MESSAGE,
+                                        DocumentedException.ErrorSeverity.ERROR)))
+                .build();
+    }
 }
index fd2ea869c72a2a0db4dec51d226ecf29f5d46d92..3c8cac318136b4e89618db2fd952c8ad383c19ae 100644 (file)
@@ -33,7 +33,6 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException;
@@ -46,22 +45,22 @@ 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.netconf.monitoring.rev101004.NetconfState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
+import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-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.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+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.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
 
 public class NetconfStateSchemasTest {
 
@@ -84,13 +83,14 @@ public class NetconfStateSchemasTest {
         final DataSchemaNode schemasNode =
                 ((ContainerSchemaNode) schemaContext
                         .getDataChildByName(NetconfState.QNAME)).getDataChildByName(Schemas.QNAME);
-        final Document schemasXml =
-                XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/netconf-state.schemas.payload.xml"));
-        final ToNormalizedNodeParser<Element, ContainerNode, ContainerSchemaNode> containerNodeParser =
-                DomToNormalizedNodeParserFactory
-                    .getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, schemaContext, false).getContainerNodeParser();
-        compositeNodeSchemas = containerNodeParser
-                .parse(Collections.singleton(schemasXml.getDocumentElement()), (ContainerSchemaNode) schemasNode);
+
+        final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+        final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+        final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext, schemasNode, false);
+
+        xmlParser.parse(UntrustedXML.createXMLStreamReader(getClass().getResourceAsStream(
+                "/netconf-state.schemas.payload.xml")));
+        compositeNodeSchemas = (ContainerNode) resultHolder.getResult();
 
     }
 
index 20502f45e982088b2f74d0cb588c5273ee204e64..0b37a87e9320b6cd3c07dc244e45cbb5e7f92df6 100644 (file)
@@ -66,7 +66,7 @@ public class NetconfToNotificationTest {
         return context;
     }
 
-    @Test(expected =  IllegalStateException.class)
+    @Test(expected =  IllegalArgumentException.class)
     public void testMostRecentWrongYangModel() throws Exception {
         final SchemaContext schemaContext = getNotificationSchemaContext(getClass(), true);
         messageTransformer = new NetconfMessageTransformer(schemaContext, true);
index cdc30830639381fb1865eac27873ae4c97ef2267..b625a9afb44843e458d60336e27e458692ccc45c 100644 (file)
@@ -12,26 +12,26 @@ import static org.opendaylight.netconf.cli.io.IOUtil.listType;
 
 import com.google.common.base.Optional;
 import java.io.IOException;
+import java.io.StringReader;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.netconf.cli.io.BaseConsoleContext;
 import org.opendaylight.netconf.cli.io.ConsoleContext;
 import org.opendaylight.netconf.cli.io.ConsoleIO;
 import org.opendaylight.netconf.cli.reader.AbstractReader;
 import org.opendaylight.netconf.cli.reader.ReadingException;
+import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+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.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
 
 public class AnyXmlReader extends AbstractReader<AnyXmlSchemaNode> {
 
@@ -69,16 +69,16 @@ public class AnyXmlReader extends AbstractReader<AnyXmlSchemaNode> {
         return newNodes;
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private Optional<DataContainerChild<?, ?>> tryParse(final String rawValue, final AnyXmlSchemaNode schemaNode) {
         try {
-            final Document dom = XmlUtil.readXmlToDocument(rawValue);
-            return Optional.of(
-                    DomToNormalizedNodeParserFactory
-                            .getInstance(DomUtils.defaultValueCodecProvider(), getSchemaContext())
-                            .getAnyXmlNodeParser()
-                            .parse(Collections.singletonList(dom.getDocumentElement()), schemaNode)
-            );
-        } catch (SAXException | IOException e) {
+            final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+            final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
+            final XmlParserStream xmlParser = XmlParserStream.create(writer, getSchemaContext(), schemaNode);
+
+            xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(rawValue)));
+            return Optional.of((DataContainerChild<?, ?>) resultHolder.getResult());
+        } catch (final Exception e) {
             // TODO log
             return Optional.absent();
         }
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");
     }