Fix NPE after invoking of GET on /rests/data 61/83761/2
authorJaroslav Tóth <jtoth@frinx.io>
Thu, 1 Aug 2019 18:42:28 +0000 (20:42 +0200)
committerRobert Varga <nite@hq.sk>
Tue, 20 Aug 2019 06:38:32 +0000 (06:38 +0000)
- NPE was caused by comparing of identifier with various stream
  paths.
- Resolved by adding identifier != null checks.
- Added unit test.

Change-Id: Ieca8adf0f6686b67e3ddfee53b7f3d47cd1d9f3e
Signed-off-by: Jaroslav Tóth <jtoth@frinx.io>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 17a709f581167067651f0b978d2f6feefa0302a9)

restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImplTest.java

index 2526199ed752b2366bfb890a1273a5701f034d8c..c2dd914c5c8695d09673cfe4d92d0699515a6929 100644 (file)
@@ -149,7 +149,7 @@ public class RestconfDataServiceImpl implements RestconfDataService {
         final NormalizedNode<?, ?> node =
                 ReadDataTransactionUtil.readData(identifier, parameters.getContent(), transactionNode, withDefa,
                         schemaContextRef, uriInfo);
-        if (identifier.contains(STREAM_PATH) && identifier.contains(STREAM_ACCESS_PATH_PART)
+        if (identifier != null && identifier.contains(STREAM_PATH) && identifier.contains(STREAM_ACCESS_PATH_PART)
                 && identifier.contains(STREAM_LOCATION_PATH_PART)) {
             final String value = (String) node.getValue();
             final String streamName = value.substring(
index a2f2c55e7bbbf968f0b2e2f6c930d478ccc30e3a..014da282754f43338e1f5cfe3936659ce0fbdce3 100644 (file)
@@ -270,7 +270,7 @@ public final class ReadDataTransactionUtil {
                                                 final TransactionVarsWrapper transactionNode, final String withDefa,
                                                 final SchemaContextRef schemaContextRef, final UriInfo uriInfo) {
         final SchemaContext schemaContext = schemaContextRef.get();
-        if (identifier.contains(STREAMS_PATH) && !identifier.contains(STREAM_PATH_PART)) {
+        if (identifier != null && identifier.contains(STREAMS_PATH) && !identifier.contains(STREAM_PATH_PART)) {
             createAllYangNotificationStreams(transactionNode, schemaContextRef, uriInfo);
         }
         return readData(content, transactionNode, withDefa, schemaContext);
index e98dbf0adddf7394480785fe97b7f072bfb97121..97dfe382023583083b3809b207a437d931756bcb 100644 (file)
@@ -24,6 +24,7 @@ import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediate
 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -63,14 +64,19 @@ import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef;
 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
@@ -215,6 +221,35 @@ public class RestconfDataServiceImplTest {
         assertEquals(this.buildBaseCont, ((NormalizedNodeContext) response.getEntity()).getData());
     }
 
+    @Test
+    public void testReadRootData() {
+        doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
+        doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(this.buildBaseContConfig))))
+                .when(this.read)
+                .read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY);
+        doReturn(immediateFluentFuture(Optional.of(wrapNodeByDataRootContainer(this.buildBaseContOperational))))
+                .when(this.read)
+                .read(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.EMPTY);
+        final Response response = this.dataService.readData(this.uriInfo);
+        assertNotNull(response);
+        assertEquals(200, response.getStatus());
+
+        final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
+        assertTrue(data instanceof ContainerNode);
+        final Collection<DataContainerChild<? extends PathArgument, ?>> rootNodes = ((ContainerNode) data).getValue();
+        assertEquals(1, rootNodes.size());
+        final Collection<DataContainerChild<? extends PathArgument, ?>> allDataChildren
+                = ((ContainerNode) rootNodes.iterator().next()).getValue();
+        assertEquals(3, allDataChildren.size());
+    }
+
+    private static ContainerNode wrapNodeByDataRootContainer(final DataContainerChild<?, ?> data) {
+        return ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(NodeIdentifier.create(SchemaContext.NAME))
+                .withChild(data)
+                .build();
+    }
+
     /**
      * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
      * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.