Clean up exception handling 46/109146/1
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 2 Dec 2023 09:30:33 +0000 (10:30 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 2 Dec 2023 09:44:13 +0000 (10:44 +0100)
There are a number of places where we allow RestconfDocumentedException
to be thrown, but we are returning a RestconfFuture. Make sure we catch
the exception and propagate it through the future.

JIRA: NETCONF-1157
Change-Id: Ia3a67e9469179302c0a9aabbc420a7a05fc8f08d
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/NetconfRestconfStrategy.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/RestconfStrategy.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/MdsalRestconfServer.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/streams/notif/CreateNotificationStreamRpc.java

index 07e2cf1084e4073f8e9e18804ead704995501985..d35ade73baf5cb01f49afcc86d82ac1298ecc581 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider;
 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
 import org.opendaylight.restconf.api.query.ContentParam;
 import org.opendaylight.restconf.api.query.WithDefaultsParam;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfFuture;
 import org.opendaylight.restconf.common.errors.SettableRestconfFuture;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
@@ -86,8 +87,12 @@ public final class NetconfRestconfStrategy extends RestconfStrategy {
         final var fields = params.fields();
         final List<YangInstanceIdentifier> fieldPaths;
         if (fields != null) {
-            final var tmp = NetconfFieldsTranslator.translate(inference.getEffectiveModelContext(), path.schema(),
-                fields);
+            final List<YangInstanceIdentifier> tmp;
+            try {
+                tmp = NetconfFieldsTranslator.translate(inference.getEffectiveModelContext(), path.schema(), fields);
+            } catch (RestconfDocumentedException e) {
+                return RestconfFuture.failed(e);
+            }
             fieldPaths = tmp == null || tmp.isEmpty() ? null : tmp;
         } else {
             fieldPaths = null;
index a2a9cb6ea78d88de7ecb7b11690a2ac535a64e47..5627de980bbd56860737d38d5896e9bfefbb3a62 100644 (file)
@@ -84,6 +84,7 @@ import org.opendaylight.restconf.server.api.OperationsPostPath;
 import org.opendaylight.restconf.server.api.OperationsPostResult;
 import org.opendaylight.restconf.server.spi.ApiPathNormalizer;
 import org.opendaylight.restconf.server.spi.ApiPathNormalizer.DataPath;
+import org.opendaylight.restconf.server.spi.ApiPathNormalizer.InstanceReference;
 import org.opendaylight.restconf.server.spi.ApiPathNormalizer.OperationPath;
 import org.opendaylight.restconf.server.spi.ApiPathNormalizer.OperationPath.Rpc;
 import org.opendaylight.restconf.server.spi.OperationInput;
@@ -345,7 +346,12 @@ public abstract class RestconfStrategy {
 
     public @NonNull RestconfFuture<DataPutResult> dataPUT(final ApiPath apiPath, final ResourceBody body,
             final Map<String, String> queryParameters) {
-        final var path = pathNormalizer.normalizeDataPath(apiPath);
+        final DataPath path;
+        try {
+            path = pathNormalizer.normalizeDataPath(apiPath);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
 
         final Insert insert;
         try {
@@ -731,7 +737,13 @@ public abstract class RestconfStrategy {
 
     public final @NonNull RestconfFuture<NormalizedNodePayload> dataGET(final ApiPath apiPath,
             final DataGetParams params) {
-        return dataGET(pathNormalizer.normalizeDataPath(apiPath), params);
+        final DataPath path;
+        try {
+            path = pathNormalizer.normalizeDataPath(apiPath);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
+        return dataGET(path, params);
     }
 
     abstract @NonNull RestconfFuture<NormalizedNodePayload> dataGET(DataPath path, DataGetParams params);
@@ -1313,7 +1325,12 @@ public abstract class RestconfStrategy {
         if (apiPath.steps().isEmpty()) {
             return dataCreatePOST(body.toResource(), queryParameters);
         }
-        final var path = pathNormalizer.normalizeDataOrActionPath(apiPath);
+        final InstanceReference path;
+        try {
+            path = pathNormalizer.normalizeDataOrActionPath(apiPath);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         if (path instanceof DataPath dataPath) {
             try (var resourceBody = body.toResource()) {
                 return dataCreatePOST(new DataPostPath(databind, dataPath.inference(), dataPath.instance()),
index 236824c10b319dc45f47ede9a4afe7de551d2943..426a6983bf01eb93f38993639e6fbedb39512341 100644 (file)
@@ -44,6 +44,7 @@ import org.opendaylight.restconf.nb.rfc8040.databind.ResourceBody;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy.StrategyAndPath;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy.StrategyAndTail;
 import org.opendaylight.restconf.server.api.DataGetParams;
 import org.opendaylight.restconf.server.api.DataPatchPath;
@@ -172,7 +173,12 @@ public final class MdsalRestconfServer
 
     @Override
     public RestconfFuture<Empty> dataDELETE(final ApiPath identifier) {
-        final var stratAndPath = localStrategy().resolveStrategyPath(identifier);
+        final StrategyAndPath stratAndPath;
+        try {
+            stratAndPath = localStrategy().resolveStrategyPath(identifier);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         return stratAndPath.strategy().delete(stratAndPath.path().instance());
     }
 
@@ -183,7 +189,12 @@ public final class MdsalRestconfServer
 
     @Override
     public RestconfFuture<NormalizedNodePayload> dataGET(final ApiPath identifier, final DataGetParams params) {
-        final var stratAndTail = localStrategy().resolveStrategy(identifier);
+        final StrategyAndTail stratAndTail;
+        try {
+            stratAndTail = localStrategy().resolveStrategy(identifier);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         return stratAndTail.strategy().dataGET(stratAndTail.tail(), params);
     }
 
@@ -195,7 +206,12 @@ public final class MdsalRestconfServer
 
     @Override
     public RestconfFuture<Empty> dataPATCH(final ApiPath identifier, final ResourceBody body) {
-        final var strategyAndPath = localStrategy().resolveStrategyPath(identifier);
+        final StrategyAndPath strategyAndPath;
+        try {
+            strategyAndPath = localStrategy().resolveStrategyPath(identifier);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         final var strategy = strategyAndPath.strategy();
         final var path = strategyAndPath.path();
         return dataPATCH(strategy, new DataPutPath(strategy.databind(), path.inference(), path.instance()), body);
@@ -220,7 +236,12 @@ public final class MdsalRestconfServer
 
     @Override
     public RestconfFuture<PatchStatusContext> dataPATCH(final ApiPath identifier, final PatchBody body) {
-        final var stratAndPath = localStrategy().resolveStrategyPath(identifier);
+        final StrategyAndPath stratAndPath;
+        try {
+            stratAndPath = localStrategy().resolveStrategyPath(identifier);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         final var strategy = stratAndPath.strategy();
         return dataPATCH(strategy, new DataPatchPath(strategy.databind(), stratAndPath.path().instance()), body);
     }
@@ -246,7 +267,12 @@ public final class MdsalRestconfServer
     @Override
     public RestconfFuture<? extends DataPostResult> dataPOST(final ApiPath identifier, final DataPostBody body,
             final Map<String, String> queryParameters) {
-        final var strategyAndTail = localStrategy().resolveStrategy(identifier);
+        final StrategyAndTail strategyAndTail;
+        try {
+            strategyAndTail = localStrategy().resolveStrategy(identifier);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         return strategyAndTail.strategy().dataPOST(strategyAndTail.tail(), body, queryParameters);
     }
 
@@ -258,7 +284,12 @@ public final class MdsalRestconfServer
     @Override
     public RestconfFuture<DataPutResult> dataPUT(final ApiPath identifier, final ResourceBody body,
              final Map<String, String> queryParameters) {
-        final var strategyAndTail = localStrategy().resolveStrategy(identifier);
+        final StrategyAndTail strategyAndTail;
+        try {
+            strategyAndTail = localStrategy().resolveStrategy(identifier);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         return strategyAndTail.strategy().dataPUT(strategyAndTail.tail(), body, queryParameters);
     }
 
@@ -347,14 +378,24 @@ public final class MdsalRestconfServer
 
     @Override
     public RestconfFuture<OperationsGetResult> operationsGET(final ApiPath operation) {
-        final var strategyAndTail = localStrategy().resolveStrategy(operation);
+        final StrategyAndTail strategyAndTail;
+        try {
+            strategyAndTail = localStrategy().resolveStrategy(operation);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         return strategyAndTail.strategy().operationsGET(strategyAndTail.tail());
     }
 
     @Override
     public RestconfFuture<OperationsPostResult> operationsPOST(final URI restconfURI, final ApiPath apiPath,
             final OperationInputBody body) {
-        final var strategyAndTail = localStrategy().resolveStrategy(apiPath);
+        final StrategyAndTail strategyAndTail;
+        try {
+            strategyAndTail = localStrategy().resolveStrategy(apiPath);
+        } catch (RestconfDocumentedException e) {
+            return RestconfFuture.failed(e);
+        }
         final var strategy = strategyAndTail.strategy();
         return strategy.operationsPOST(restconfURI, strategyAndTail.tail(), body);
     }
index 0c4bc6d547e412296bc2c45f6283b0b4aea91368..f39788a72644a46da1185038c9a843e9127ec686 100644 (file)
@@ -78,15 +78,20 @@ public final class CreateNotificationStreamRpc extends RpcImplementation {
         final var description = new StringBuilder("YANG notifications matching any of {");
         var haveFirst = false;
         for (var qname : qnames) {
-            final var module = modelContext.findModuleStatement(qname.getModule())
-                .orElseThrow(() -> new RestconfDocumentedException(qname + " refers to an unknown module",
+            final var optModule = modelContext.findModuleStatement(qname.getModule());
+            if (optModule.isEmpty()) {
+                return RestconfFuture.failed(new RestconfDocumentedException(qname + " refers to an unknown module",
                     ErrorType.APPLICATION, ErrorTag.INVALID_VALUE));
-            final var stmt = module.findSchemaTreeNode(qname)
-                .orElseThrow(() -> new RestconfDocumentedException(qname + " refers to an unknown notification",
+            }
+            final var module = optModule.orElseThrow();
+            final var optStmt = module.findSchemaTreeNode(qname);
+            if (optStmt.isEmpty()) {
+                return RestconfFuture.failed(new RestconfDocumentedException(
+                    qname + " refers to an unknown notification", ErrorType.APPLICATION, ErrorTag.INVALID_VALUE));
+            }
+            if (!(optStmt.orElseThrow() instanceof NotificationEffectiveStatement)) {
+                return RestconfFuture.failed(new RestconfDocumentedException(qname + " refers to a non-notification",
                     ErrorType.APPLICATION, ErrorTag.INVALID_VALUE));
-            if (!(stmt instanceof NotificationEffectiveStatement)) {
-                throw new RestconfDocumentedException(qname + " refers to a non-notification",
-                    ErrorType.APPLICATION, ErrorTag.INVALID_VALUE);
             }
 
             if (haveFirst) {