Enforce non-null input on RPCs 39/89139/4
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 20 Apr 2020 08:41:40 +0000 (10:41 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 20 Apr 2020 09:35:31 +0000 (11:35 +0200)
RPC invocations should never have a null input, rather an empty
container.

JIRA: MDSAL-303
Change-Id: I3cb019bdbd05ccc6a1d3f7e83d2220d9882ddaff
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/RpcServiceAdapter.java
dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMRpcImplementation.java
dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMRpcService.java
dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMRpcRouter.java
dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/TestUtils.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/ForwardingDOMRpcImplementation.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/ForwardingDOMRpcService.java

index a66aab8a9a02a5b4927b51e34ec5bcdddac717de..107284fd991be9fba983fa57c36883d83e5f9d2c 100644 (file)
@@ -80,13 +80,9 @@ class RpcServiceAdapter implements InvocationHandler {
 
     @Override
     @SuppressWarnings("checkstyle:hiddenField")
-    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
-
+    public Object invoke(final Object proxy, final Method method, final Object[] args) {
         final RpcInvocationStrategy rpc = rpcNames.get(method);
         if (rpc != null) {
-            if (method.getParameterCount() == 0) {
-                return rpc.invokeEmpty();
-            }
             if (args.length != 1) {
                 throw new IllegalArgumentException("Input must be provided.");
             }
@@ -130,16 +126,12 @@ class RpcServiceAdapter implements InvocationHandler {
 
         abstract ContainerNode serialize(DataObject input);
 
-        final ListenableFuture<RpcResult<?>> invokeEmpty() {
-            return invoke0(rpcName, null);
-        }
-
         final SchemaPath getRpcName() {
             return rpcName;
         }
 
         ListenableFuture<RpcResult<?>> invoke0(final SchemaPath schemaPath, final ContainerNode input) {
-            final ListenableFuture<DOMRpcResult> result = delegate.invokeRpc(schemaPath, input);
+            final ListenableFuture<? extends DOMRpcResult> result = delegate.invokeRpc(schemaPath, input);
             if (ENABLE_CODEC_SHORTCUT && result instanceof BindingRpcFutureAware) {
                 return ((BindingRpcFutureAware) result).getBindingFuture();
             }
@@ -148,7 +140,8 @@ class RpcServiceAdapter implements InvocationHandler {
         }
 
         private ListenableFuture<RpcResult<?>> transformFuture(final SchemaPath rpc,
-                final ListenableFuture<DOMRpcResult> domFuture, final BindingNormalizedNodeSerializer resultCodec) {
+                final ListenableFuture<? extends DOMRpcResult> domFuture,
+                final BindingNormalizedNodeSerializer resultCodec) {
             return Futures.transform(domFuture, input -> {
                 final NormalizedNode<?, ?> domData = input.getResult();
                 final DataObject bindingResult;
index a0d6b112895f7d996079d8528a523e7bb178fbe1..357cb3bf21831d517af354d046ffe444e4eea8a9 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.mdsal.dom.api;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 /**
@@ -26,10 +25,10 @@ public interface DOMRpcImplementation {
      * @return A {@link ListenableFuture} which will return either a result structure,
      *         or report a subclass of {@link DOMRpcException} reporting a transport
      *         error.
+     * @throws NullPointerException if any argument is null
      */
-    // FIXME: 6.0.0: do not allow null input
-    @NonNull ListenableFuture<DOMRpcResult> invokeRpc(@NonNull DOMRpcIdentifier rpc,
-            @Nullable NormalizedNode<?, ?> input);
+    @NonNull ListenableFuture<? extends DOMRpcResult> invokeRpc(@NonNull DOMRpcIdentifier rpc,
+            @NonNull NormalizedNode<?, ?> input);
 
     /**
      * Return the relative invocation cost of this implementation. Default implementation return 0.
index 67e87fff370a37e3294dcc449a6f7f5198ffdfc6..a6b103cb4338f84ad74ec3c3f3d416adb78c8f8e 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.mdsal.dom.api;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -30,8 +29,8 @@ public interface DOMRpcService extends DOMService {
      * @return A {@link ListenableFuture} which will return either a result structure, or report a subclass
      *         of {@link DOMRpcException} reporting a transport error.
      */
-    // FIXME: 6.0.0: do not allow null input
-    @NonNull ListenableFuture<DOMRpcResult> invokeRpc(@NonNull SchemaPath type, @Nullable NormalizedNode<?, ?> input);
+    @NonNull ListenableFuture<? extends DOMRpcResult> invokeRpc(@NonNull SchemaPath type,
+            @NonNull NormalizedNode<?, ?> input);
 
     /**
      * Register a {@link DOMRpcAvailabilityListener} with this service to receive notifications
index 22264a6a089f008a5275b21e168b534f889ff201..f1fa5a70de1cf0f8a4bb03f6a4af3ea049732181 100644 (file)
@@ -401,7 +401,7 @@ public final class DOMRpcRouter extends AbstractRegistration
                     new DOMActionNotAvailableException("No implementation of Action %s available", type));
             }
 
-            return OperationInvocation.invoke(entry, type, path, input);
+            return OperationInvocation.invoke(entry, type, path, requireNonNull(input));
         }
     }
 
@@ -435,14 +435,15 @@ public final class DOMRpcRouter extends AbstractRegistration
 
     private final class RpcServiceFacade implements DOMRpcService {
         @Override
-        public ListenableFuture<DOMRpcResult> invokeRpc(final SchemaPath type, final NormalizedNode<?, ?> input) {
+        public ListenableFuture<? extends DOMRpcResult> invokeRpc(final SchemaPath type,
+                final NormalizedNode<?, ?> input) {
             final AbstractDOMRpcRoutingTableEntry entry = (AbstractDOMRpcRoutingTableEntry) routingTable.getEntry(type);
             if (entry == null) {
                 return Futures.immediateFailedFuture(
                     new DOMRpcImplementationNotAvailableException("No implementation of RPC %s available", type));
             }
 
-            return OperationInvocation.invoke(entry, input);
+            return OperationInvocation.invoke(entry, requireNonNull(input));
         }
 
         @Override
@@ -497,7 +498,7 @@ public final class DOMRpcRouter extends AbstractRegistration
             return entry.getImplementations(path).get(0).invokeAction(type, path, input);
         }
 
-        static ListenableFuture<DOMRpcResult> invoke(final AbstractDOMRpcRoutingTableEntry entry,
+        static ListenableFuture<? extends DOMRpcResult> invoke(final AbstractDOMRpcRoutingTableEntry entry,
                 final NormalizedNode<?, ?> input) {
             if (entry instanceof UnknownDOMRpcRoutingTableEntry) {
                 return Futures.immediateFailedFuture(
@@ -513,8 +514,8 @@ public final class DOMRpcRouter extends AbstractRegistration
                 new DOMRpcImplementationNotAvailableException("Unsupported RPC entry."));
         }
 
-        private static ListenableFuture<DOMRpcResult> invokeRoutedRpc(final RoutedDOMRpcRoutingTableEntry entry,
-                final NormalizedNode<?, ?> input) {
+        private static ListenableFuture<? extends DOMRpcResult> invokeRoutedRpc(
+                final RoutedDOMRpcRoutingTableEntry entry, final NormalizedNode<?, ?> input) {
             final Optional<NormalizedNode<?, ?>> maybeKey = NormalizedNodes.findNode(input,
                 entry.getRpcId().getContextReference());
 
@@ -559,8 +560,8 @@ public final class DOMRpcRouter extends AbstractRegistration
                     entry.getType()));
         }
 
-        private static ListenableFuture<DOMRpcResult> invokeGlobalRpc(final GlobalDOMRpcRoutingTableEntry entry,
-                final NormalizedNode<?, ?> input) {
+        private static ListenableFuture<? extends DOMRpcResult> invokeGlobalRpc(
+                final GlobalDOMRpcRoutingTableEntry entry, final NormalizedNode<?, ?> input) {
             return entry.getImplementations(YangInstanceIdentifier.empty()).get(0).invokeRpc(entry.getRpcId(), input);
         }
     }
index 2ca4de66ef5bc42d8bcbaaad1667a4feea70606b..8fc8dbf454d90c2e425ff32e9444f3b0902b22dc 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.mdsal.dom.broker;
 
+import static java.util.Objects.requireNonNull;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode;
 
 import com.google.common.util.concurrent.FluentFuture;
@@ -67,13 +68,14 @@ abstract class TestUtils {
     private static final class TestRpcImplementation implements DOMRpcImplementation {
         private final FluentFuture<DOMRpcResult> unknownRpc;
 
-        private TestRpcImplementation() {
+        TestRpcImplementation() {
             unknownRpc = FluentFutures.immediateFailedFluentFuture(
                     new DOMRpcImplementationNotAvailableException(EXCEPTION_TEXT));
         }
 
         @Override
         public FluentFuture<DOMRpcResult> invokeRpc(final DOMRpcIdentifier rpc, final NormalizedNode<?, ?> input) {
+            requireNonNull(input);
             return unknownRpc;
         }
     }
index 95af1e33e83ad9f77685649142e1f8ce0e3e85ad..311864f45a8f8fd4a4fc0c08e246145e6633d078 100644 (file)
@@ -24,7 +24,8 @@ public abstract class ForwardingDOMRpcImplementation extends ForwardingObject im
     protected abstract @NonNull DOMRpcImplementation delegate();
 
     @Override
-    public ListenableFuture<DOMRpcResult> invokeRpc(final DOMRpcIdentifier type, final NormalizedNode<?, ?> input) {
+    public ListenableFuture<? extends DOMRpcResult> invokeRpc(final DOMRpcIdentifier type,
+            final NormalizedNode<?, ?> input) {
         return delegate().invokeRpc(type, input);
     }
 }
index dad96e49bea85d7c3263cba5931488d9fec0b0c4..e1f51292eeebc0301334216f8c331df0e0dc6651 100644 (file)
@@ -25,7 +25,7 @@ public abstract class ForwardingDOMRpcService extends ForwardingObject implement
     protected abstract @NonNull DOMRpcService delegate();
 
     @Override
-    public ListenableFuture<DOMRpcResult> invokeRpc(final SchemaPath type, final NormalizedNode<?, ?> input) {
+    public ListenableFuture<? extends DOMRpcResult> invokeRpc(final SchemaPath type, final NormalizedNode<?, ?> input) {
         return delegate().invokeRpc(type, input);
     }