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%2FEditConfig.java;h=28f8857aaeed01a1a1f66a34c382739897ce2ce7;hb=455dd29862158b2c1bfab4235860e8acec638065;hp=7c86dd26b44b8307ca4e0f08a1619139f4af1359;hpb=f597da23057c39e38a38fda0038f2388506c0a14;p=netconf.git diff --git a/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditConfig.java b/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditConfig.java index 7c86dd26b4..28f8857aae 100644 --- a/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditConfig.java +++ b/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditConfig.java @@ -8,48 +8,34 @@ package org.opendaylight.netconf.mdsal.connector.ops; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableMap; -import java.net.URI; -import java.net.URISyntaxException; import java.util.List; import java.util.ListIterator; -import java.util.Map; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -import javax.xml.transform.dom.DOMSource; -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.XmlUtil; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; -import org.opendaylight.netconf.api.NetconfDocumentedException; +import org.opendaylight.netconf.api.DocumentedException; +import org.opendaylight.netconf.api.DocumentedException.ErrorSeverity; +import org.opendaylight.netconf.api.DocumentedException.ErrorTag; +import org.opendaylight.netconf.api.DocumentedException.ErrorType; +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.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.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.ModifyAction; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; 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.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; -import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.slf4j.Logger; @@ -58,28 +44,25 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; -public class EditConfig extends AbstractSingletonNetconfOperation { +public final class EditConfig extends AbstractEdit { private static final Logger LOG = LoggerFactory.getLogger(EditConfig.class); private static final String OPERATION_NAME = "edit-config"; - private static final String CONFIG_KEY = "config"; - private static final String TARGET_KEY = "target"; private static final String DEFAULT_OPERATION_KEY = "default-operation"; - private final CurrentSchemaContext schemaContext; private final TransactionProvider transactionProvider; public EditConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) { - super(netconfSessionIdForReporting); - this.schemaContext = schemaContext; + super(netconfSessionIdForReporting, schemaContext); this.transactionProvider = transactionProvider; } @Override protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws DocumentedException { - final Datastore targetDatastore = extractTargetParameter(operationElement); + final XmlElement targetElement = extractTargetElement(operationElement, OPERATION_NAME); + final Datastore targetDatastore = Datastore.valueOf(targetElement.getName()); if (targetDatastore == Datastore.running) { throw new DocumentedException("edit-config on running datastore is not supported", ErrorType.PROTOCOL, @@ -89,15 +72,14 @@ public class EditConfig extends AbstractSingletonNetconfOperation { final ModifyAction defaultAction = getDefaultOperation(operationElement); - final XmlElement configElement = getElement(operationElement, CONFIG_KEY); + final XmlElement configElement = getConfigElement(operationElement); for (final XmlElement element : configElement.getChildElements()) { final String ns = element.getNamespace(); - final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element).get(); - + final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element); final DataTreeChangeTracker changeTracker = new DataTreeChangeTracker(defaultAction); - - parseIntoNormalizedNode(schemaNode, element, changeTracker); + parseIntoNormalizedNode(schemaNode, element, + new EditOperationNormalizedNodeStreamWriter(new NormalizedNodeResult(), changeTracker)); executeOperations(changeTracker); } @@ -129,15 +111,15 @@ public class EditConfig extends AbstractSingletonNetconfOperation { case CREATE: try { final Optional> readResult = - rwtx.read(LogicalDatastoreType.CONFIGURATION, path).checkedGet(); + rwtx.read(LogicalDatastoreType.CONFIGURATION, path).get(); if (readResult.isPresent()) { throw new DocumentedException("Data already exists, cannot execute CREATE operation", ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS, ErrorSeverity.ERROR); } mergeParentMixin(rwtx, path, changeData); rwtx.put(LogicalDatastoreType.CONFIGURATION, path, changeData); - } catch (final ReadFailedException e) { - LOG.warn("Read from datastore failed when trying to read data for create operation", change, e); + } catch (final InterruptedException | ExecutionException e) { + LOG.warn("Read from datastore failed when trying to read data for create operation {}", change, e); } break; case REPLACE: @@ -147,14 +129,14 @@ public class EditConfig extends AbstractSingletonNetconfOperation { case DELETE: try { final Optional> readResult = - rwtx.read(LogicalDatastoreType.CONFIGURATION, path).checkedGet(); + rwtx.read(LogicalDatastoreType.CONFIGURATION, path).get(); if (!readResult.isPresent()) { throw new DocumentedException("Data is missing, cannot execute DELETE operation", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR); } rwtx.delete(LogicalDatastoreType.CONFIGURATION, path); - } catch (final ReadFailedException e) { - LOG.warn("Read from datastore failed when trying to read data for delete operation", change, e); + } catch (final InterruptedException | ExecutionException e) { + LOG.warn("Read from datastore failed when trying to read data for delete operation {}", change, e); } break; case REMOVE: @@ -166,7 +148,7 @@ public class EditConfig extends AbstractSingletonNetconfOperation { } private void mergeParentMixin(final DOMDataReadWriteTransaction rwtx, final YangInstanceIdentifier path, - final NormalizedNode change) { + final NormalizedNode change) { final YangInstanceIdentifier parentNodeYid = path.getParent(); if (change instanceof MapEntryNode) { final SchemaNode schemaNode = SchemaContextUtil.findNodeInSchemaContext( @@ -207,78 +189,6 @@ public class EditConfig extends AbstractSingletonNetconfOperation { } } - @SuppressWarnings("checkstyle:IllegalCatch") - private NormalizedNode parseIntoNormalizedNode(final DataSchemaNode schemaNode, final XmlElement element, - 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"); - } - - final NormalizedNodeResult resultHolder = new NormalizedNodeResult(); - final NormalizedNodeStreamWriter writer = new EditOperationNormalizedNodeStreamWriter(resultHolder, - changeTracker); - final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext.getCurrentContext(), schemaNode); - try { - xmlParser.traverse(new DOMSource(element.getDomElement())); - } 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 getSchemaNodeFromNamespace(final String namespace, final XmlElement element) - throws DocumentedException { - Optional dataSchemaNode = Optional.absent(); - try { - // returns module with newest revision since findModuleByNamespace returns a set of modules and we only - // need the newest one - final Module module = - schemaContext.getCurrentContext().findModuleByNamespaceAndRevision(new URI(namespace), null); - if (module == null) { - // no module is present with this namespace - throw new NetconfDocumentedException("Unable to find module by namespace: " + namespace, - ErrorType.APPLICATION, ErrorTag.UNKNOWN_NAMESPACE, ErrorSeverity.ERROR); - } - final DataSchemaNode schemaNode = - module.getDataChildByName(QName.create(module.getQNameModule(), element.getName())); - if (schemaNode != null) { - dataSchemaNode = Optional.of(schemaNode); - } else { - throw new DocumentedException( - "Unable to find node with namespace: " + namespace + "in module: " + module.toString(), - ErrorType.APPLICATION, - ErrorTag.UNKNOWN_NAMESPACE, - ErrorSeverity.ERROR); - } - } catch (final URISyntaxException e) { - LOG.debug("Unable to create URI for namespace : {}", namespace); - } - - return dataSchemaNode; - } - - private static Datastore extractTargetParameter(final XmlElement operationElement) throws DocumentedException { - final NodeList elementsByTagName = getElementsByTagName(operationElement, TARGET_KEY); - // Direct lookup instead of using XmlElement class due to performance - if (elementsByTagName.getLength() == 0) { - final Map errorInfo = ImmutableMap.of("bad-attribute", TARGET_KEY, "bad-element", - OPERATION_NAME); - throw new DocumentedException("Missing target element", ErrorType.PROTOCOL, ErrorTag.MISSING_ATTRIBUTE, - ErrorSeverity.ERROR, errorInfo); - } else if (elementsByTagName.getLength() > 1) { - throw new DocumentedException("Multiple target elements", ErrorType.RPC, ErrorTag.UNKNOWN_ATTRIBUTE, - ErrorSeverity.ERROR); - } else { - final XmlElement targetChildNode = - XmlElement.fromDomElement((Element) elementsByTagName.item(0)).getOnlyChildElement(); - return Datastore.valueOf(targetChildNode.getName()); - } - } - private static ModifyAction getDefaultOperation(final XmlElement operationElement) throws DocumentedException { final NodeList elementsByTagName = getElementsByTagName(operationElement, DEFAULT_OPERATION_KEY); if (elementsByTagName.getLength() == 0) { @@ -292,34 +202,6 @@ public class EditConfig extends AbstractSingletonNetconfOperation { } - private static XmlElement getElement(final XmlElement operationElement, final String elementName) - throws DocumentedException { - final Optional childNode = operationElement.getOnlyChildElementOptionally(elementName); - if (!childNode.isPresent()) { - throw new DocumentedException(elementName + " element is missing", - ErrorType.PROTOCOL, - ErrorTag.MISSING_ELEMENT, - ErrorSeverity.ERROR); - } - - return childNode.get(); - } - - @VisibleForTesting - static NodeList getElementsByTagName(final XmlElement operationElement, final String key) throws - DocumentedException { - final Element element = operationElement.getDomElement(); - final NodeList elementsByTagName; - - if (Strings.isNullOrEmpty(element.getPrefix())) { - elementsByTagName = element.getElementsByTagName(key); - } else { - elementsByTagName = element.getElementsByTagNameNS(operationElement.getNamespace(), key); - } - - return elementsByTagName; - } - @Override protected String getOperationName() { return OPERATION_NAME;