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=ae48ca7196904a135429bd9aae88626f947924d1;hp=3834a383db8e94da989f7b1bd4076285cd250935;hb=3b721d88ed1083a463ecb73a6050de4bfedf1a78;hpb=cb5b61610718a37853429c308652bf7a8733a30f 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 3834a383db..ae48ca7196 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 @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.Future; import javax.ws.rs.core.Response; @@ -51,6 +52,8 @@ import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode; import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.data.api.SimpleNode; @@ -673,6 +676,7 @@ public class RestconfImpl implements RestconfService { MountInstance mountPoint = iiWithData.getMountPoint(); final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint); + validateListKeysEqualityInPayloadAndUri(iiWithData, payload); RpcResult status = null; try { @@ -694,6 +698,52 @@ public class RestconfImpl implements RestconfService { return Response.status(Status.INTERNAL_SERVER_ERROR).build(); } + /** + * Validates whether keys in {@code payload} are equal to values of keys in + * {@code iiWithData} for list schema node + * + * @throws RestconfDocumentedException + * if key values or key count in payload and URI isn't equal + * + */ + private void validateListKeysEqualityInPayloadAndUri(final InstanceIdWithSchemaNode iiWithData, + final CompositeNode payload) { + if (iiWithData.getSchemaNode() instanceof ListSchemaNode) { + final List keyDefinitions = ((ListSchemaNode) iiWithData.getSchemaNode()).getKeyDefinition(); + final PathArgument lastPathArgument = iiWithData.getInstanceIdentifier().getLastPathArgument(); + if (lastPathArgument instanceof NodeIdentifierWithPredicates) { + final Map uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument) + .getKeyValues(); + isEqualUriAndPayloadKeyValues(uriKeyValues, payload, keyDefinitions); + } + } + } + + private void isEqualUriAndPayloadKeyValues(final Map uriKeyValues, final CompositeNode payload, + final List keyDefinitions) { + for (QName keyDefinition : keyDefinitions) { + final Object uriKeyValue = uriKeyValues.get(keyDefinition); + // should be caught during parsing URI to InstanceIdentifier + if (uriKeyValue == null) { + throw new RestconfDocumentedException("Missing key " + keyDefinition + " in URI.", + ErrorType.PROTOCOL, ErrorTag.DATA_MISSING); + } + final List> payloadKeyValues = payload.getSimpleNodesByName(keyDefinition.getLocalName()); + if (payloadKeyValues.isEmpty()) { + throw new RestconfDocumentedException("Missing key " + keyDefinition.getLocalName() + + " in the message body.", ErrorType.PROTOCOL, + ErrorTag.DATA_MISSING); + } + + Object payloadKeyValue = payloadKeyValues.iterator().next().getValue(); + if (!uriKeyValue.equals(payloadKeyValue)) { + throw new RestconfDocumentedException("The value '"+uriKeyValue+ "' for key '" + keyDefinition.getLocalName() + + "' specified in the URI doesn't match the value '" + payloadKeyValue + "' specified in the message body. ", + ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); + } + } + } + @Override public Response createConfigurationData(final String identifier, final CompositeNode payload) { if( payload == null ) { @@ -877,7 +927,7 @@ public class RestconfImpl implements RestconfService { broker.registerToListenDataChanges(listener); final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder(); - UriBuilder port = uriBuilder.port(WebSocketServer.PORT); + UriBuilder port = uriBuilder.port(WebSocketServer.getInstance().getPort()); final URI uriToWebsocketServer = port.replacePath(streamName).build(); return Response.status(Status.OK).location(uriToWebsocketServer).build(); @@ -1136,6 +1186,7 @@ public class RestconfImpl implements RestconfService { final DataNodeContainer schema, final MountInstance mountPoint, final QName currentAugment ) { final List> children = compositeNodeBuilder.getValues(); + checkNodeMultiplicityAccordingToSchema(schema,children); for (final NodeWrapper child : children) { final List potentialSchemaNodes = this.controllerContext.findInstanceDataChildrenByName( @@ -1188,9 +1239,32 @@ public class RestconfImpl implements RestconfService { if (!foundKey) { throw new RestconfDocumentedException( - "Missing key in URI \"" + listKey.getLocalName() + - "\" of list \"" + listSchemaNode.getQName().getLocalName() + "\"", - ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE ); + "Missing key '" + listKey.getLocalName() + + "' for list '" + listSchemaNode.getQName().getLocalName() + "' in the message body", + ErrorType.PROTOCOL, ErrorTag.DATA_MISSING ); + } + } + } + } + + private void checkNodeMultiplicityAccordingToSchema(final DataNodeContainer dataNodeContainer, + final List> nodes) { + Map equalNodeNamesToCounts = new HashMap(); + for (NodeWrapper child : nodes) { + Integer count = equalNodeNamesToCounts.get(child.getLocalName()); + equalNodeNamesToCounts.put(child.getLocalName(), count == null ? 1 : ++count); + } + + for (DataSchemaNode childSchemaNode : dataNodeContainer.getChildNodes()) { + if (childSchemaNode instanceof ContainerSchemaNode || childSchemaNode instanceof LeafSchemaNode) { + String localName = childSchemaNode.getQName().getLocalName(); + Integer count = equalNodeNamesToCounts.get(localName); + if (count != null && count > 1) { + throw new RestconfDocumentedException( + "Multiple input data elements were specified for '" + + childSchemaNode.getQName().getLocalName() + + "'. The data for this element type can only be specified once.", + ErrorType.APPLICATION, ErrorTag.BAD_ELEMENT); } } }