X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Frestconf%2Fimpl%2FRestconfImpl.java;h=cd860efab75073e13cf0cd2cfd93e12fd7200a5e;hp=b94f6a6166c47f3b1308f7dc4696341fe5ec202b;hb=531621aac4cff9d39cbd8668a53bdeba8a0e6d81;hpb=51e91f6bdcc88c5aa96f956e516d31dbb5e5d5e0 diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java index b94f6a6166..cd860efab7 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java @@ -9,14 +9,18 @@ package org.opendaylight.controller.sal.restconf.impl; import com.google.common.base.Objects; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; import com.google.common.base.Splitter; import com.google.common.base.Strings; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; - +import java.math.BigInteger; import java.net.URI; +import java.net.URISyntaxException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -32,7 +36,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; - import org.apache.commons.lang3.StringUtils; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -63,6 +66,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceI import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException; import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory; import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; import org.opendaylight.yangtools.yang.data.impl.NodeFactory; @@ -87,6 +91,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RestconfImpl implements RestconfService { + private enum UriParameters { PRETTY_PRINT("prettyPrint"), DEPTH("depth"); @@ -103,6 +108,8 @@ public class RestconfImpl implements RestconfService { } } + + private final static RestconfImpl INSTANCE = new RestconfImpl(); private static final int NOTIFICATION_PORT = 8181; @@ -135,13 +142,24 @@ public class RestconfImpl implements RestconfService { private static final String SCOPE_PARAM_NAME = "scope"; + private static final String NETCONF_BASE = "urn:ietf:params:xml:ns:netconf:base:1.0"; + + private static final String NETCONF_BASE_PAYLOAD_NAME = "data"; + + private static final QName NETCONF_BASE_QNAME; + static { try { EVENT_SUBSCRIPTION_AUGMENT_REVISION = new SimpleDateFormat("yyyy-MM-dd").parse("2014-07-08"); + NETCONF_BASE_QNAME = QName.create(QNameModule.create(new URI(NETCONF_BASE), null), NETCONF_BASE_PAYLOAD_NAME ); } catch (ParseException e) { throw new RestconfDocumentedException( "It wasn't possible to convert revision date of sal-remote-augment to date", ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED); + } catch (URISyntaxException e) { + throw new RestconfDocumentedException( + "It wasn't possible to create instance of URI class with "+NETCONF_BASE+" URI", ErrorType.APPLICATION, + ErrorTag.OPERATION_FAILED); } } @@ -205,7 +223,7 @@ public class RestconfImpl implements RestconfService { Set modules = null; DOMMountPoint mountPoint = null; if (identifier.contains(ControllerContext.MOUNT)) { - InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier); + InstanceIdentifierContext mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier); mountPoint = mountPointIdentifier.getMountPoint(); modules = this.controllerContext.getAllModules(mountPoint); } else { @@ -236,7 +254,7 @@ public class RestconfImpl implements RestconfService { Module module = null; DOMMountPoint mountPoint = null; if (identifier.contains(ControllerContext.MOUNT)) { - InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier); + InstanceIdentifierContext mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier); mountPoint = mountPointIdentifier.getMountPoint(); module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision); } else { @@ -267,7 +285,7 @@ public class RestconfImpl implements RestconfService { Set modules = null; DOMMountPoint mountPoint = null; if (identifier.contains(ControllerContext.MOUNT)) { - InstanceIdWithSchemaNode mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier); + InstanceIdentifierContext mountPointIdentifier = this.controllerContext.toMountPointIdentifier(identifier); mountPoint = mountPointIdentifier.getMountPoint(); modules = this.controllerContext.getAllModules(mountPoint); } else { @@ -518,7 +536,7 @@ public class RestconfImpl implements RestconfService { DOMMountPoint mountPoint = null; if (identifier.contains(ControllerContext.MOUNT)) { // mounted RPC call - look up mount instance. - InstanceIdWithSchemaNode mountPointId = controllerContext.toMountPointIdentifier(identifier); + InstanceIdentifierContext mountPointId = controllerContext.toMountPointIdentifier(identifier); mountPoint = mountPointId.getMountPoint(); int startOfRemoteRpcName = identifier.lastIndexOf(ControllerContext.MOUNT) @@ -615,8 +633,8 @@ public class RestconfImpl implements RestconfService { } @Override - public StructuredData readConfigurationData(final String identifier, final UriInfo uriInfo) { - final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier); + public NormalizedNodeContext readConfigurationData(final String identifier, final UriInfo uriInfo) { + final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier); DOMMountPoint mountPoint = iiWithData.getMountPoint(); NormalizedNode data = null; YangInstanceIdentifier normalizedII; @@ -628,12 +646,7 @@ public class RestconfImpl implements RestconfService { normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier()); data = broker.readConfigurationData(normalizedII); } - - final CompositeNode compositeNode = datastoreNormalizedNodeToCompositeNode(data, iiWithData.getSchemaNode()); - final CompositeNode prunedCompositeNode = pruneDataAtDepth(compositeNode, parseDepthParameter(uriInfo)); - - final boolean prettyPrintMode = parsePrettyPrintParameter(uriInfo); - return new StructuredData(prunedCompositeNode, iiWithData.getSchemaNode(), mountPoint, prettyPrintMode); + return new NormalizedNodeContext(iiWithData, data); } @SuppressWarnings("unchecked") @@ -679,8 +692,8 @@ public class RestconfImpl implements RestconfService { } @Override - public StructuredData readOperationalData(final String identifier, final UriInfo info) { - final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier); + public NormalizedNodeContext readOperationalData(final String identifier, final UriInfo info) { + final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier); DOMMountPoint mountPoint = iiWithData.getMountPoint(); NormalizedNode data = null; YangInstanceIdentifier normalizedII; @@ -693,11 +706,7 @@ public class RestconfImpl implements RestconfService { data = broker.readOperationalData(normalizedII); } - final CompositeNode compositeNode = datastoreNormalizedNodeToCompositeNode(data, iiWithData.getSchemaNode()); - final CompositeNode prunedCompositeNode = pruneDataAtDepth(compositeNode, parseDepthParameter(info)); - - final boolean prettyPrintMode = parsePrettyPrintParameter(info); - return new StructuredData(prunedCompositeNode, iiWithData.getSchemaNode(), mountPoint, prettyPrintMode); + return new NormalizedNodeContext(iiWithData, data); } private boolean parsePrettyPrintParameter(final UriInfo info) { @@ -707,16 +716,18 @@ public class RestconfImpl implements RestconfService { @Override public Response updateConfigurationData(final String identifier, final Node payload) { - final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier); + final InstanceIdentifierContext iiWithData = this.controllerContext.toInstanceIdentifier(identifier); validateInput(iiWithData.getSchemaNode(), payload); DOMMountPoint mountPoint = iiWithData.getMountPoint(); + validateTopLevelNodeName(payload, iiWithData.getInstanceIdentifier()); final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint); validateListKeysEqualityInPayloadAndUri(iiWithData, value); final NormalizedNode datastoreNormalizedNode = compositeNodeToDatastoreNormalizedNode(value, iiWithData.getSchemaNode()); + YangInstanceIdentifier normalizedII; if (mountPoint != null) { normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized( @@ -767,6 +778,29 @@ public class RestconfImpl implements RestconfService { return Response.status(Status.OK).build(); } + private void validateTopLevelNodeName(final Node node, + final YangInstanceIdentifier identifier) { + final String payloadName = getName(node); + final Iterator pathArguments = identifier.getReversePathArguments().iterator(); + + //no arguments + if (!pathArguments.hasNext()) { + //no "data" payload + if (!node.getNodeType().equals(NETCONF_BASE_QNAME)) { + throw new RestconfDocumentedException("Instance identifier has to contain at least one path argument", + ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); + } + //any arguments + } else { + final String identifierName = pathArguments.next().getNodeType().getLocalName(); + if (!payloadName.equals(identifierName)) { + throw new RestconfDocumentedException("Payload name (" + payloadName + + ") is different from identifier name (" + identifierName + ")", ErrorType.PROTOCOL, + ErrorTag.MALFORMED_MESSAGE); + } + } + } + /** * Validates whether keys in {@code payload} are equal to values of keys in {@code iiWithData} for list schema node * @@ -774,7 +808,7 @@ public class RestconfImpl implements RestconfService { * if key values or key count in payload and URI isn't equal * */ - private void validateListKeysEqualityInPayloadAndUri(final InstanceIdWithSchemaNode iiWithData, + private void validateListKeysEqualityInPayloadAndUri(final InstanceIdentifierContext iiWithData, final CompositeNode payload) { if (iiWithData.getSchemaNode() instanceof ListSchemaNode) { final List keyDefinitions = ((ListSchemaNode) iiWithData.getSchemaNode()).getKeyDefinition(); @@ -825,7 +859,7 @@ public class RestconfImpl implements RestconfService { ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE); } - InstanceIdWithSchemaNode iiWithData = null; + InstanceIdentifierContext iiWithData = null; CompositeNode value = null; if (this.representsMountPointRootData(payload)) { // payload represents mount point data and URI represents path to the mount point @@ -841,7 +875,7 @@ public class RestconfImpl implements RestconfService { value = this.normalizeNode(payload, iiWithData.getSchemaNode(), iiWithData.getMountPoint()); } else { - final InstanceIdWithSchemaNode incompleteInstIdWithData = this.controllerContext + final InstanceIdentifierContext incompleteInstIdWithData = this.controllerContext .toInstanceIdentifier(identifier); final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode(); DOMMountPoint mountPoint = incompleteInstIdWithData.getMountPoint(); @@ -856,7 +890,7 @@ public class RestconfImpl implements RestconfService { parentSchema, payloadName, module.getNamespace()); value = this.normalizeNode(payload, schemaNode, mountPoint); - iiWithData = addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode); + iiWithData = addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode,incompleteInstIdWithData.getSchemaContext()); } final NormalizedNode datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value, @@ -906,7 +940,7 @@ public class RestconfImpl implements RestconfService { final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(module, payloadName, module.getNamespace()); final CompositeNode value = this.normalizeNode(payload, schemaNode, null); - final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode); + final InstanceIdentifierContext iiWithData = this.addLastIdentifierFromData(null, value, schemaNode,ControllerContext.getInstance().getGlobalSchema()); final NormalizedNode datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value, schemaNode); DOMMountPoint mountPoint = iiWithData.getMountPoint(); YangInstanceIdentifier normalizedII; @@ -932,7 +966,7 @@ public class RestconfImpl implements RestconfService { @Override public Response deleteConfigurationData(final String identifier) { - final InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier(identifier); + final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier); DOMMountPoint mountPoint = iiWithData.getMountPoint(); YangInstanceIdentifier normalizedII; @@ -946,9 +980,13 @@ public class RestconfImpl implements RestconfService { broker.commitConfigurationDataDelete(normalizedII).get(); } } catch (Exception e) { - throw new RestconfDocumentedException("Error creating data", e); + final Optional searchedException = Iterables.tryFind(Throwables.getCausalChain(e), + Predicates.instanceOf(ModifiedNodeDoesNotExistException.class)); + if (searchedException.isPresent()) { + throw new RestconfDocumentedException("Data specified for deleting doesn't exist.", ErrorType.APPLICATION, ErrorTag.DATA_MISSING); + } + throw new RestconfDocumentedException("Error while deleting data", e); } - return Response.status(Status.OK).build(); } @@ -1098,8 +1136,8 @@ public class RestconfImpl implements RestconfService { return module; } - private InstanceIdWithSchemaNode addLastIdentifierFromData(final InstanceIdWithSchemaNode identifierWithSchemaNode, - final CompositeNode data, final DataSchemaNode schemaOfData) { + private InstanceIdentifierContext addLastIdentifierFromData(final InstanceIdentifierContext identifierWithSchemaNode, + final CompositeNode data, final DataSchemaNode schemaOfData, SchemaContext schemaContext) { YangInstanceIdentifier instanceIdentifier = null; if (identifierWithSchemaNode != null) { instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier(); @@ -1122,11 +1160,12 @@ public class RestconfImpl implements RestconfService { YangInstanceIdentifier instance = iiBuilder.toInstance(); DOMMountPoint mountPoint = null; + SchemaContext schemaCtx = null; if (identifierWithSchemaNode != null) { mountPoint = identifierWithSchemaNode.getMountPoint(); } - return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint); + return new InstanceIdentifierContext(instance, schemaOfData, mountPoint,schemaContext); } private HashMap resolveKeysFromData(final ListSchemaNode listNode, final CompositeNode dataNode) { @@ -1514,16 +1553,16 @@ public class RestconfImpl implements RestconfService { "It wasn't possible to translate specified data to datastore readable form.")); } - private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode( - final InstanceIdWithSchemaNode iiWithSchemaNode) { + private InstanceIdentifierContext normalizeInstanceIdentifierWithSchemaNode( + final InstanceIdentifierContext iiWithSchemaNode) { return normalizeInstanceIdentifierWithSchemaNode(iiWithSchemaNode, false); } - private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode( - final InstanceIdWithSchemaNode iiWithSchemaNode, final boolean unwrapLastListNode) { - return new InstanceIdWithSchemaNode(instanceIdentifierToReadableFormForNormalizeNode( + private InstanceIdentifierContext normalizeInstanceIdentifierWithSchemaNode( + final InstanceIdentifierContext iiWithSchemaNode, final boolean unwrapLastListNode) { + return new InstanceIdentifierContext(instanceIdentifierToReadableFormForNormalizeNode( iiWithSchemaNode.getInstanceIdentifier(), unwrapLastListNode), iiWithSchemaNode.getSchemaNode(), - iiWithSchemaNode.getMountPoint()); + iiWithSchemaNode.getMountPoint(),iiWithSchemaNode.getSchemaContext()); } private YangInstanceIdentifier instanceIdentifierToReadableFormForNormalizeNode( @@ -1560,4 +1599,9 @@ public class RestconfImpl implements RestconfService { } return false; } + + public BigInteger getOperationalReceived() { + // TODO Auto-generated method stub + return null; + } }