X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-nb-bierman02%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Frestconf%2Fimpl%2FRestconfImpl.java;h=fe3548dcb79b4545265fc0a83489091c7d3363b0;hb=982e75ece2483e413befe3edd8fd90022a644f72;hp=45c161e42f525f26456bf798f7bf112fe567cb93;hpb=b89c4596a05094f6e84d7ccc2589523cae9757c6;p=netconf.git diff --git a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java index 45c161e42f..fe3548dcb7 100644 --- a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java +++ b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java @@ -5,12 +5,10 @@ * 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.sal.restconf.impl; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.CharMatcher; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Predicates; import com.google.common.base.Splitter; @@ -19,7 +17,7 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; -import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FluentFuture; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import java.net.URI; @@ -40,6 +38,7 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; @@ -49,14 +48,15 @@ import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; -import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult; +import org.opendaylight.mdsal.common.api.CommitInfo; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.OptimisticLockFailedException; +import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +import org.opendaylight.mdsal.dom.api.DOMRpcService; +import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult; import org.opendaylight.netconf.sal.rest.api.Draft02; import org.opendaylight.netconf.sal.rest.api.RestconfService; import org.opendaylight.netconf.sal.streams.listeners.ListenerAdapter; @@ -95,9 +95,9 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotE import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; @@ -196,7 +196,7 @@ public final class RestconfImpl implements RestconfService { restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE); Preconditions.checkState(modulesSchemaNode instanceof ContainerSchemaNode); - final DataContainerNodeAttrBuilder moduleContainerBuilder = + final DataContainerNodeBuilder moduleContainerBuilder = Builders.containerBuilder((ContainerSchemaNode) modulesSchemaNode); moduleContainerBuilder.withChild(allModuleMap); @@ -228,7 +228,7 @@ public final class RestconfImpl implements RestconfService { restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE); Preconditions.checkState(modulesSchemaNode instanceof ContainerSchemaNode); - final DataContainerNodeAttrBuilder moduleContainerBuilder = + final DataContainerNodeBuilder moduleContainerBuilder = Builders.containerBuilder((ContainerSchemaNode) modulesSchemaNode); moduleContainerBuilder.withChild(mountPointModulesMap); @@ -296,7 +296,7 @@ public final class RestconfImpl implements RestconfService { restconfModule, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE); Preconditions.checkState(streamsContainerSchemaNode instanceof ContainerSchemaNode); - final DataContainerNodeAttrBuilder streamsContainerBuilder = + final DataContainerNodeBuilder streamsContainerBuilder = Builders.containerBuilder((ContainerSchemaNode) streamsContainerSchemaNode); streamsContainerBuilder.withChild(listStreamsBuilder.build()); @@ -360,7 +360,7 @@ public final class RestconfImpl implements RestconfService { } final ContainerSchemaNode fakeCont = new FakeContainerSchemaNode(fakeRpcSchema); - final DataContainerNodeAttrBuilder containerBuilder = + final DataContainerNodeBuilder containerBuilder = Builders.containerBuilder(fakeCont); for (final LeafSchemaNode leaf : fakeRpcSchema) { @@ -423,6 +423,11 @@ public final class RestconfImpl implements RestconfService { @Override public NormalizedNodeContext invokeRpc(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) { + if (payload == null) { + // no payload specified, reroute this to no payload invokeRpc implementation + return invokeRpc(identifier, "", uriInfo); + } + final SchemaPath type = payload.getInstanceIdentifierContext().getSchemaNode().getPath(); final URI namespace = payload.getInstanceIdentifierContext().getSchemaNode().getQName().getNamespace(); final ListenableFuture response; @@ -815,21 +820,28 @@ public final class RestconfImpl implements RestconfService { } try { - result.getFutureOfPutData().checkedGet(); - return Response.status(result.getStatus()).build(); - } catch (final TransactionCommitFailedException e) { - if (e instanceof OptimisticLockFailedException) { + result.getFutureOfPutData().get(); + } catch (final InterruptedException e) { + LOG.debug("Update failed for {}", identifier, e); + throw new RestconfDocumentedException(e.getMessage(), e); + } catch (final ExecutionException e) { + final TransactionCommitFailedException failure = Throwables.getCauseAs(e, + TransactionCommitFailedException.class); + if (failure instanceof OptimisticLockFailedException) { if (--tries <= 0) { LOG.debug("Got OptimisticLockFailedException on last try - failing {}", identifier); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + throw new RestconfDocumentedException(e.getMessage(), e, failure.getErrorList()); } LOG.debug("Got OptimisticLockFailedException - trying again {}", identifier); - } else { - LOG.debug("Update failed for {}", identifier, e); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + continue; } + + LOG.debug("Update failed for {}", identifier, e); + throw RestconfDocumentedException.decodeAndThrow(e.getMessage(), failure); } + + return Response.status(result.getStatus()).build(); } } @@ -955,7 +967,7 @@ public final class RestconfImpl implements RestconfService { "Point parameter can be used only with 'after' or 'before' values of Insert parameter."); } - CheckedFuture future; + FluentFuture future; if (mountPoint != null) { future = this.broker.commitConfigurationDataPost(mountPoint, normalizedII, payload.getData(), insert, point); @@ -965,12 +977,14 @@ public final class RestconfImpl implements RestconfService { } try { - future.checkedGet(); - } catch (final RestconfDocumentedException e) { - throw e; - } catch (final TransactionCommitFailedException e) { + future.get(); + } catch (final InterruptedException e) { LOG.info("Error creating data {}", uriInfo != null ? uriInfo.getPath() : "", e); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + throw new RestconfDocumentedException(e.getMessage(), e); + } catch (final ExecutionException e) { + LOG.info("Error creating data {}", uriInfo != null ? uriInfo.getPath() : "", e); + throw RestconfDocumentedException.decodeAndThrow(e.getMessage(), Throwables.getCauseAs(e, + TransactionCommitFailedException.class)); } LOG.trace("Successfuly created data."); @@ -1009,7 +1023,7 @@ public final class RestconfImpl implements RestconfService { final DOMMountPoint mountPoint = iiWithData.getMountPoint(); final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier(); - final CheckedFuture future; + final FluentFuture future; if (mountPoint != null) { future = this.broker.commitConfigurationDataDelete(mountPoint, normalizedII); } else { @@ -1017,18 +1031,19 @@ public final class RestconfImpl implements RestconfService { } try { - future.checkedGet(); - } catch (final TransactionCommitFailedException e) { + future.get(); + } catch (final InterruptedException e) { + throw new RestconfDocumentedException(e.getMessage(), e); + } catch (final ExecutionException e) { final Optional searchedException = Iterables.tryFind(Throwables.getCausalChain(e), - Predicates.instanceOf(ModifiedNodeDoesNotExistException.class)); + Predicates.instanceOf(ModifiedNodeDoesNotExistException.class)).toJavaUtil(); if (searchedException.isPresent()) { - throw new RestconfDocumentedException("Data specified for delete doesn't exist.", - ErrorType.APPLICATION, ErrorTag.DATA_MISSING, e); + throw new RestconfDocumentedException("Data specified for delete doesn't exist.", ErrorType.APPLICATION, + ErrorTag.DATA_MISSING, e); } - final String errMsg = "Error while deleting data"; - LOG.info(errMsg, e); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + throw RestconfDocumentedException.decodeAndThrow(e.getMessage(), Throwables.getCauseAs(e, + TransactionCommitFailedException.class)); } return Response.status(Status.OK).build(); @@ -1109,7 +1124,7 @@ public final class RestconfImpl implements RestconfService { if (response != null) { // prepare node with value of location final InstanceIdentifierContext iid = prepareIIDSubsStreamOutput(); - final NormalizedNodeAttrBuilder> builder = + final NormalizedNodeBuilder> builder = ImmutableLeafNodeBuilder.create().withValue(response.toString()); builder.withNodeIdentifier( NodeIdentifier.create(QName.create("subscribe:to:notification", "2016-10-28", "location"))); @@ -1202,7 +1217,7 @@ public final class RestconfImpl implements RestconfService { return uriToWebsocketServerBuilder.replacePath(streamName).build(); } - private String getWsScheme(final UriInfo uriInfo) { + private static String getWsScheme(final UriInfo uriInfo) { URI uri = uriInfo.getAbsolutePath(); if (uri == null) { return "ws"; @@ -1384,11 +1399,11 @@ public final class RestconfImpl implements RestconfService { return listModuleBuilder.build(); } - protected MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode moduleSchemaNode) { + private MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode moduleSchemaNode) { Preconditions.checkArgument(moduleSchemaNode instanceof ListSchemaNode, "moduleSchemaNode has to be of type ListSchemaNode"); final ListSchemaNode listModuleSchemaNode = (ListSchemaNode) moduleSchemaNode; - final DataContainerNodeAttrBuilder moduleNodeValues = + final DataContainerNodeBuilder moduleNodeValues = Builders.mapEntryBuilder(listModuleSchemaNode); List instanceDataChildrenByName = @@ -1398,22 +1413,22 @@ public final class RestconfImpl implements RestconfService { moduleNodeValues .withChild(Builders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue(module.getName()).build()); + final QNameModule qNameModule = module.getQNameModule(); + instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "revision"); final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(revisionSchemaNode instanceof LeafSchemaNode); - final java.util.Optional revision = module.getQNameModule().getRevision(); - if (revision.isPresent()) { - moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode) - .withValue(revision.get().toString()).build()); - } + final java.util.Optional revision = qNameModule.getRevision(); + moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode) + .withValue(revision.map(Revision::toString).orElse("")).build()); instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "namespace"); final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(namespaceSchemaNode instanceof LeafSchemaNode); moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) namespaceSchemaNode) - .withValue(module.getNamespace().toString()).build()); + .withValue(qNameModule.getNamespace().toString()).build()); instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "feature"); @@ -1434,7 +1449,7 @@ public final class RestconfImpl implements RestconfService { Preconditions.checkArgument(streamSchemaNode instanceof ListSchemaNode, "streamSchemaNode has to be of type ListSchemaNode"); final ListSchemaNode listStreamSchemaNode = (ListSchemaNode) streamSchemaNode; - final DataContainerNodeAttrBuilder streamNodeValues = + final DataContainerNodeBuilder streamNodeValues = Builders.mapEntryBuilder(listStreamSchemaNode); List instanceDataChildrenByName = @@ -1455,7 +1470,7 @@ public final class RestconfImpl implements RestconfService { final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(replaySupportSchemaNode instanceof LeafSchemaNode); streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) replaySupportSchemaNode) - .withValue(Boolean.valueOf(true)).build()); + .withValue(Boolean.TRUE).build()); instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "replay-log-creation-time");