X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Fmdsal-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fmdsal%2Fconnector%2Fops%2FRuntimeRpc.java;h=8159382c36b04eaeae6fc1718906e76727e608f1;hb=45ef57fef0b7a0951ac3ed4b0a249225071fcd2c;hp=3321b269fbfed5e387e1f87598f5393ce553b80d;hpb=36c274dc2aaca6705604ff05bef9653dfb86ba2a;p=netconf.git diff --git a/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/RuntimeRpc.java b/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/RuntimeRpc.java index 3321b269fb..8159382c36 100644 --- a/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/RuntimeRpc.java +++ b/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/RuntimeRpc.java @@ -5,56 +5,54 @@ * 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 com.google.common.base.Optional; -import com.google.common.base.Throwables; -import com.google.common.util.concurrent.CheckedFuture; import java.io.IOException; -import java.net.URI; -import java.util.Collection; -import java.util.Collections; +import java.net.URISyntaxException; import java.util.Map; -import javax.annotation.Nullable; +import java.util.Optional; +import java.util.concurrent.ExecutionException; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.dom.DOMResult; -import org.opendaylight.controller.config.util.xml.DocumentedException; -import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorSeverity; -import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorTag; -import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorType; -import org.opendaylight.controller.config.util.xml.XmlElement; -import org.opendaylight.controller.config.util.xml.XmlMappingConstants; -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 javax.xml.transform.dom.DOMSource; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +import org.opendaylight.mdsal.dom.api.DOMRpcService; +import org.opendaylight.netconf.api.DocumentedException; +import org.opendaylight.netconf.api.NetconfDocumentedException; +import org.opendaylight.netconf.api.xml.XmlElement; import org.opendaylight.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.netconf.api.xml.XmlUtil; 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.yang.common.ErrorSeverity; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.common.ErrorType; +import org.opendaylight.yangtools.yang.common.XMLNamespace; 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.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter; +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; import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; +import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Attr; 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; public class RuntimeRpc extends AbstractSingletonNetconfOperation { @@ -79,10 +77,10 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { @Override protected HandlingPriority canHandle(final String netconfOperationName, final String namespace) { - final URI namespaceURI = createNsUri(namespace); - final Optional module = getModule(namespaceURI); + final XMLNamespace namespaceURI = createNsUri(namespace); + final Optional module = getModule(namespaceURI); - if (!module.isPresent()) { + if (module.isEmpty()) { LOG.debug("Cannot handle rpc: {}, {}", netconfOperationName, namespace); return HandlingPriority.CANNOT_HANDLE; } @@ -97,26 +95,24 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { throw new UnsupportedOperationException("Runtime rpc does not have a stable name"); } - private static URI createNsUri(final String namespace) { + private static XMLNamespace createNsUri(final String namespace) { // May throw IllegalArgumentException, but that should never happen, as the namespace comes from parsed XML - return URI.create(namespace); + return XMLNamespace.of(namespace); } //this returns module with the newest revision if more then 1 module with same namespace is found - private Optional getModule(final URI namespaceURI) { - return Optional.fromNullable( - schemaContext.getCurrentContext().findModuleByNamespaceAndRevision(namespaceURI, null)); + private Optional getModule(final XMLNamespace namespace) { + return schemaContext.getCurrentContext().findModules(namespace).stream().findFirst(); } - private static Optional getRpcDefinitionFromModule(final Module module, final URI namespaceURI, + private static Optional getRpcDefinitionFromModule(final Module module, final XMLNamespace namespace, final String name) { for (final RpcDefinition rpcDef : module.getRpcs()) { - if (rpcDef.getQName().getNamespace().equals(namespaceURI) - && rpcDef.getQName().getLocalName().equals(name)) { + if (rpcDef.getQName().getNamespace().equals(namespace) && rpcDef.getQName().getLocalName().equals(name)) { return Optional.of(rpcDef); } } - return Optional.absent(); + return Optional.empty(); } @Override @@ -129,14 +125,14 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { netconfOperationNamespace = operationElement.getNamespace(); } catch (final DocumentedException e) { LOG.debug("Cannot retrieve netconf operation namespace from message due to ", e); - throw new DocumentedException("Cannot retrieve netconf operation namespace from message", + throw new DocumentedException("Cannot retrieve netconf operation namespace from message", e, ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE, ErrorSeverity.ERROR); } - final URI namespaceURI = createNsUri(netconfOperationNamespace); - final Optional moduleOptional = getModule(namespaceURI); + final XMLNamespace namespaceURI = createNsUri(netconfOperationNamespace); + final Optional moduleOptional = getModule(namespaceURI); - if (!moduleOptional.isPresent()) { + if (moduleOptional.isEmpty()) { throw new DocumentedException("Unable to find module in Schema Context with namespace and name : " + namespaceURI + " " + netconfOperationName + schemaContext.getCurrentContext(), ErrorType.APPLICATION, ErrorTag.BAD_ELEMENT, ErrorSeverity.ERROR); @@ -145,7 +141,7 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { final Optional rpcDefinitionOptional = getRpcDefinitionFromModule(moduleOptional.get(), namespaceURI, netconfOperationName); - if (!rpcDefinitionOptional.isPresent()) { + if (rpcDefinitionOptional.isEmpty()) { throw new DocumentedException( "Unable to find RpcDefinition with namespace and name : " + namespaceURI + " " + netconfOperationName, @@ -153,20 +149,19 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { } final RpcDefinition rpcDefinition = rpcDefinitionOptional.get(); - final SchemaPath schemaPath = SchemaPath.create(Collections.singletonList(rpcDefinition.getQName()), true); - final NormalizedNode inputNode = rpcToNNode(operationElement, rpcDefinition.getInput()); + final ContainerNode inputNode = rpcToNNode(operationElement, rpcDefinition); - final CheckedFuture rpcFuture = rpcService.invokeRpc(schemaPath, inputNode); + final DOMRpcResult result; try { - final DOMRpcResult result = rpcFuture.checkedGet(); - if (result.getResult() == null) { - return XmlUtil.createElement(document, XmlNetconfConstants.OK, - Optional.of(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0)); - } - return (Element) transformNormalizedNode(document, result.getResult(), rpcDefinition.getOutput().getPath()); - } catch (final DOMRpcException e) { + result = rpcService.invokeRpc(rpcDefinition.getQName(), inputNode).get(); + } catch (final InterruptedException | ExecutionException e) { throw DocumentedException.wrap(e); } + if (result.getResult() == null) { + return XmlUtil.createElement(document, XmlNetconfConstants.OK, + Optional.of(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0)); + } + return transformNormalizedNode(document, result.getResult(), rpcDefinition.getOutput().getPath()); } @Override @@ -181,7 +176,7 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { final Map attributes = requestElement.getAttributes(); final Element response = handle(document, operationElement, subsequentOperation); - final Element rpcReply = XmlUtil.createElement(document, XmlMappingConstants.RPC_REPLY_KEY, + final Element rpcReply = XmlUtil.createElement(document, XmlNetconfConstants.RPC_REPLY_KEY, Optional.of(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0)); if (XmlElement.fromDomElement(response).hasNamespace()) { @@ -204,9 +199,9 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { return document; } - private Node transformNormalizedNode(final Document document, final NormalizedNode data, - final SchemaPath rpcOutputPath) { - final DOMResult result = new DOMResult(document.createElement(XmlMappingConstants.RPC_REPLY_KEY)); + private Element transformNormalizedNode(final Document document, final NormalizedNode data, + final SchemaPath rpcOutputPath) { + final DOMResult result = new DOMResult(document.createElement(XmlNetconfConstants.RPC_REPLY_KEY)); final XMLStreamWriter xmlWriter = getXmlStreamWriter(result); @@ -224,7 +219,7 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { LOG.warn("Error while closing streams", e); } - return result.getNode(); + return (Element) result.getNode(); } private static XMLStreamWriter getXmlStreamWriter(final DOMResult result) { @@ -238,12 +233,11 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { private static void writeRootElement(final XMLStreamWriter xmlWriter, final SchemaOrderedNormalizedNodeWriter nnWriter, final ContainerNode data) { try { - final Collection> value = data.getValue(); - nnWriter.write(value); + nnWriter.write(data.body()); nnWriter.flush(); xmlWriter.flush(); } catch (XMLStreamException | IOException e) { - Throwables.propagate(e); + throw new RuntimeException(e); } } @@ -251,15 +245,24 @@ public class RuntimeRpc extends AbstractSingletonNetconfOperation { * Parses xml element rpc input into normalized node or null if rpc does not take any input. * * @param element rpc xml element - * @param input input container schema node, or null if rpc does not take any input + * @param rpcDefinition 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 */ - @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 @Nullable ContainerNode rpcToNNode(final XmlElement element, + final RpcDefinition rpcDefinition) throws DocumentedException { + final NormalizedNodeResult resultHolder = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder); + final XmlParserStream xmlParser = XmlParserStream.create(writer, SchemaInferenceStack.of( + schemaContext.getCurrentContext(), + Absolute.of(rpcDefinition.getQName(), rpcDefinition.getInput().getQName())).toInference()); + try { + xmlParser.traverse(new DOMSource(element.getDomElement())); + } catch (final XMLStreamException | URISyntaxException | IOException | SAXException ex) { + throw new NetconfDocumentedException("Error parsing input: " + ex.getMessage(), ex, ErrorType.PROTOCOL, + DocumentedException.MALFORMED_MESSAGE, ErrorSeverity.ERROR); + } + + return (ContainerNode) resultHolder.getResult(); + } }