From: Jaroslav Tóth Date: Thu, 1 Aug 2019 18:42:28 +0000 (+0200) Subject: Fix NPE after invoking of GET on /rests/data X-Git-Tag: release/magnesium~103 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F61%2F83361%2F4;p=netconf.git Fix NPE after invoking of GET on /rests/data - 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 Signed-off-by: Robert Varga --- diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java index 5e21c2c3cf..55f3cd8ee1 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java @@ -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( diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java index a2f2c55e7b..014da28275 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java @@ -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); diff --git a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImplTest.java b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImplTest.java index e98dbf0add..97dfe38202 100644 --- a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImplTest.java +++ b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImplTest.java @@ -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()).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> rootNodes = ((ContainerNode) data).getValue(); + assertEquals(1, rootNodes.size()); + final Collection> 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.