X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fconfig-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fconfignetconfconnector%2Foperations%2Fruntimerpc%2FRuntimeRpc.java;h=21021fec55661f69cd2c1e19325f0dd651e07193;hp=7bdfa277a00418d39b5724267947fcf7e4446a81;hb=c7ec8db7f107b5e265f4e8b2fe3dd0f7b1163b64;hpb=a92d9d6a21a0f6ca8d2153795721f500eaf29ee9 diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java index 7bdfa277a0..21021fec55 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java @@ -11,21 +11,27 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ru import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; + import org.opendaylight.controller.config.util.ConfigRegistryClient; -import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc; -import org.opendaylight.controller.config.yangjmxgenerator.attribute.SimpleTypeResolver; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; +import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribute; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement; -import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.SimpleAttributeMappingStrategy; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.AttributeMappingStrategy; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectMapper; +import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.ObjectXmlWriter; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.InstanceRuntimeRpc; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.ModuleRpcs; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.Rpcs; import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.slf4j.Logger; @@ -34,7 +40,8 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.management.ObjectName; -import javax.management.openmbean.SimpleType; +import javax.management.openmbean.OpenType; + import java.util.Map; public class RuntimeRpc extends AbstractConfigNetconfOperation { @@ -50,10 +57,22 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { this.yangStoreSnapshot = yangStoreSnapshot; } - private String getStringRepresentation(final Object result) { - final SimpleType simpleType = SimpleTypeResolver.getSimpleType(result.getClass().getName()); - final Optional mappedAttributeOpt = new SimpleAttributeMappingStrategy(simpleType).mapAttribute(result); - return mappedAttributeOpt.isPresent() ? mappedAttributeOpt.get() : ""; + private Element toXml(Document doc, Object result, AttributeIfc returnType, String namespace, String elementName) throws NetconfDocumentedException { + AttributeMappingStrategy> mappingStrategy = new ObjectMapper().prepareStrategy(returnType); + Optional mappedAttributeOpt = mappingStrategy.mapAttribute(result); + Preconditions.checkState(mappedAttributeOpt.isPresent(), "Unable to map return value %s as %s", result, returnType.getOpenType()); + + // FIXME: multiple return values defined as leaf-list and list in yang should not be wrapped in output xml element, + // they need to be appended directly under rpc-reply element + // + // Either allow List of Elements to be returned from NetconfOperation or + // pass reference to parent output xml element for netconf operations to + // append result(s) on their own + Element tempParent = XmlUtil.createElement(doc, "output", Optional.of(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0)); + new ObjectXmlWriter().prepareWritingStrategy(elementName, returnType, doc).writeElement(tempParent, namespace, mappedAttributeOpt.get()); + + XmlElement xmlElement = XmlElement.fromDomElement(tempParent); + return xmlElement.getChildElements().size() > 1 ? tempParent : xmlElement.getOnlyChildElement().getDomElement(); } private Object executeOperation(final ConfigRegistryClient configRegistryClient, final ObjectName on, @@ -76,7 +95,13 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { } public NetconfOperationExecution fromXml(final XmlElement xml) throws NetconfDocumentedException { - final String namespace = xml.getNamespace(); + final String namespace; + try { + namespace = xml.getNamespace(); + } catch (MissingNameSpaceException e) { + logger.trace("Can't get namespace from xml element due to {}",e); + throw NetconfDocumentedException.wrap(e); + } final XmlElement contextInstanceElement = xml.getOnlyChildElement(CONTEXT_INSTANCE); final String operationName = xml.getName(); @@ -99,18 +124,26 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { } @Override - public HandlingPriority canHandle(Document message) { - XmlElement requestElement = getRequestElementWithCheck(message); + public HandlingPriority canHandle(Document message) throws NetconfDocumentedException { + XmlElement requestElement = null; + requestElement = getRequestElementWithCheck(message); XmlElement operationElement = requestElement.getOnlyChildElement(); final String netconfOperationName = operationElement.getName(); - final String netconfOperationNamespace = operationElement.getNamespace(); + final String netconfOperationNamespace; + try { + netconfOperationNamespace = operationElement.getNamespace(); + } catch (MissingNameSpaceException e) { + logger.debug("Cannot retrieve netconf operation namespace from message due to {}", e); + return HandlingPriority.CANNOT_HANDLE; + } final Optional contextInstanceElement = operationElement .getOnlyChildElementOptionally(CONTEXT_INSTANCE); - if (contextInstanceElement.isPresent() == false) + if (!contextInstanceElement.isPresent()){ return HandlingPriority.CANNOT_HANDLE; + } final RuntimeRpcElementResolved id = RuntimeRpcElementResolved.fromXpath(contextInstanceElement.get() .getTextContent(), netconfOperationName, netconfOperationNamespace); @@ -146,27 +179,23 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { } @Override - protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { - - // TODO exception handling + protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { // TODO check for namespaces and unknown elements - final NetconfOperationExecution execution = fromXml(xml); logger.debug("Invoking operation {} on {} with arguments {}", execution.operationName, execution.on, execution.attributes); - final Object result = executeOperation(configRegistryClient, execution.on, execution.operationName, + final Object result = executeOperation(getConfigRegistryClient(), execution.on, execution.operationName, execution.attributes); - logger.info("Operation {} called successfully on {} with arguments {} with result {}", execution.operationName, + logger.trace("Operation {} called successfully on {} with arguments {} with result {}", execution.operationName, execution.on, execution.attributes, result); - if (execution.returnType.equals("void")) { - return document.createElement("ok"); + if (execution.isVoid()) { + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); } else { - final Element output = XmlUtil.createTextElement(document, "result", getStringRepresentation(result)); - XmlUtil.addNamespaceAttr(output, execution.namespace); - return output; + return toXml(document, result, execution.returnType, execution.namespace, + execution.returnType.getAttributeYangName()); } } @@ -175,11 +204,11 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { private final ObjectName on; private final String operationName; private final Map attributes; - private final String returnType; + private final AttributeIfc returnType; private final String namespace; public NetconfOperationExecution(final ObjectName on, final String name, - final Map attributes, final String returnType, final String namespace) { + final Map attributes, final AttributeIfc returnType, final String namespace) { this.on = on; this.operationName = name; this.attributes = attributes; @@ -187,6 +216,10 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { this.namespace = namespace; } + boolean isVoid() { + return returnType == VoidAttribute.getInstance(); + } + } private static Map sortAttributes( @@ -195,7 +228,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { for (XmlElement xmlElement : xml.getChildElements()) { final String name = xmlElement.getName(); - if (CONTEXT_INSTANCE.equals(name) == false) { // skip context + if (!CONTEXT_INSTANCE.equals(name)) { // skip context // instance child node // because it // specifies