summaryrefslogtreecommitdiffstats
path: root/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter
diff options
context:
space:
mode:
authorwaqas.ikram <waqas.ikram@est.tech>2020-04-08 15:48:21 +0100
committerwaqas.ikram <waqas.ikram@est.tech>2020-04-09 15:57:53 +0100
commit12bfb7b86a783f63b8072ac67462202d59173940 (patch)
tree9c7699f462510d0fee349d28a577233a9cbfb23b /adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter
parent35121d207a7408414c2e46ba8afd76fb492101b1 (diff)
Refactor SOL003 Adapter to organize its modules
based on functions Change-Id: I10b2376a552272ac3b405b2dae718adcb7e1e489 Issue-ID: SO-2771 Signed-off-by: waqas.ikram <waqas.ikram@est.tech>
Diffstat (limited to 'adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter')
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/pom.xml109
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/ConversionServiceConfiguration.java55
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/PackageManagementConstants.java39
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/AbstractPkgNotificationConverter.java56
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgChangeNotificationConverter.java79
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgOnboardingNotificationConverter.java69
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/VnfPkgInfoConverter.java198
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/sol003/etsicatalog/PkgmSubscriptionRequestConverter.java198
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/AbstractServiceProviderConfiguration.java49
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java72
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java32
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java187
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java281
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogSubscriptionServiceProvider.java55
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java113
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmHttpServiceProviderConfiguration.java49
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderConfiguration.java154
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/AbstractNotificationServiceProvider.java59
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/BasicAuthNotificationServiceProvider.java68
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationManager.java137
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProvider.java51
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProviderFactory.java67
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthNotificationServiceProvider.java103
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthTokenResponse.java56
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/SubscriptionManager.java209
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/TlsNotificationServiceProvider.java57
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/AbstractCacheServiceProvider.java47
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheManagerConfiguration.java50
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheNotFoundException.java37
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProvider.java74
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProviderImpl.java119
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationController.java131
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java176
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionController.java172
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/AuthenticationTypeNotSupportedException.java44
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/ConversionFailedException.java44
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerBadRequestException.java43
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerRequestFailureException.java43
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiSubscriptionNotificationControllerExceptionHandler.java112
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/InternalServerErrorException.java43
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/NotificationTypeNotSupportedException.java44
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java94
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionNotFoundException.java43
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgBadRequestException.java43
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgConflictException.java43
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgNotFoundException.java43
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationControllerTest.java602
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementControllerTest.java677
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionControllerTest.java403
-rwxr-xr-xadapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/TestApplication.java38
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/application.yaml61
-rw-r--r--adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/requests/SubscriptionRequest.json45
52 files changed, 5873 insertions, 0 deletions
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/pom.xml b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/pom.xml
new file mode 100644
index 0000000000..f24ad64db4
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/pom.xml
@@ -0,0 +1,109 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.so.adapters</groupId>
+ <artifactId>etsi-sol003-package-management</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>etsi-sol003-package-management-adapter</artifactId>
+ <name>ETSI SOL003 VNF Package Management Adapter</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <so.log.level>DEBUG</so.log.level>
+ </systemPropertyVariables>
+ <rerunFailingTestsCount>2</rerunFailingTestsCount>
+ <parallel>suites</parallel>
+ <useUnlimitedThreads>false</useUnlimitedThreads>
+ <threadCount>1</threadCount>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.so</groupId>
+ <artifactId>common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.so.adapters</groupId>
+ <artifactId>etsi-sol003-adapter-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.so.adapters</groupId>
+ <artifactId>etsi-sol003-package-management-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.so.adapters</groupId>
+ <artifactId>etsi-sol003-package-management-ext-clients</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.inject</groupId>
+ <artifactId>jersey-hk2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/ConversionServiceConfiguration.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/ConversionServiceConfiguration.java
new file mode 100644
index 0000000000..fa9bc3e9c9
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/ConversionServiceConfiguration.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter;
+
+import org.onap.so.adapters.vnfmadapter.common.VnfmAdapterUrlProvider;
+import org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003.PkgChangeNotificationConverter;
+import org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003.PkgOnboardingNotificationConverter;
+import org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003.VnfPkgInfoConverter;
+import org.onap.so.adapters.vnfmadapter.converters.sol003.etsicatalog.PkgmSubscriptionRequestConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.core.convert.support.DefaultConversionService;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class ConversionServiceConfiguration {
+
+ private final VnfmAdapterUrlProvider vnfmAdapterUrlProvider;
+
+ @Autowired
+ public ConversionServiceConfiguration(final VnfmAdapterUrlProvider vnfmAdapterUrlProvider) {
+ this.vnfmAdapterUrlProvider = vnfmAdapterUrlProvider;
+ }
+
+ @Bean
+ public ConversionService conversionService() {
+ final DefaultConversionService service = new DefaultConversionService();
+ service.addConverter(new VnfPkgInfoConverter(vnfmAdapterUrlProvider));
+ service.addConverter(new PkgmSubscriptionRequestConverter());
+ service.addConverter(new PkgChangeNotificationConverter());
+ service.addConverter(new PkgOnboardingNotificationConverter());
+ return service;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/PackageManagementConstants.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/PackageManagementConstants.java
new file mode 100644
index 0000000000..cf3c6c5ac6
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/PackageManagementConstants.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter;
+
+/**
+ * ETSI SOL003 VNF Package Management Adapter constants
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+public class PackageManagementConstants {
+
+ public static final String APPLICATION_ZIP = "application/zip";
+
+ /**
+ * Name of the subscription cache
+ */
+ public static final String PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE = "PackageManagementSubscriptionCache";
+
+ private PackageManagementConstants() {}
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/AbstractPkgNotificationConverter.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/AbstractPkgNotificationConverter.java
new file mode 100644
index 0000000000..221ec8d3a0
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/AbstractPkgNotificationConverter.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003;
+
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgmLinks;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinks;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinksVnfPackage;
+
+/**
+ * A base class that can be extended by classes for converting Etsi Catalog Manager Pkg Notification classes. Provides
+ * common methods that will be useful to those classes.
+ *
+ * @author andrew.a.lamb@est.tech
+ */
+abstract public class AbstractPkgNotificationConverter {
+
+ protected URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinks convert(
+ final PkgmLinks pkgmLinks) {
+ final URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinksVnfPackage linksVnfPackage =
+ new URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinksVnfPackage();
+ if (pkgmLinks.getVnfPackage() != null) {
+ linksVnfPackage.setHref(pkgmLinks.getVnfPackage().getHref());
+ }
+
+ final URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinksVnfPackage linksSubscription =
+ new URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinksVnfPackage();
+ if (pkgmLinks.getSubscription() != null) {
+ linksSubscription.setHref(pkgmLinks.getSubscription().getHref());
+ }
+
+ final URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinks links =
+ new URIisprovidedbytheclientwhencreatingthesubscriptionVnfPackageOnboardingNotificationLinks();
+ links.setVnfPackage(linksVnfPackage);
+ links.setSubscription(linksSubscription);
+ return links;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgChangeNotificationConverter.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgChangeNotificationConverter.java
new file mode 100644
index 0000000000..04b304e93b
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgChangeNotificationConverter.java
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgChangeNotification;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.VnfPackageChangeNotification;
+import org.slf4j.Logger;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Service;
+
+/**
+ * Converter to convert from an Etsi Catalog Manager {@link PkgChangeNotification} Object to its equivalent SOL003
+ * {@link VnfPackageChangeNotification} Object
+ *
+ * @author andrew.a.lamb@est.tech
+ */
+@Service
+public class PkgChangeNotificationConverter extends AbstractPkgNotificationConverter
+ implements Converter<PkgChangeNotification, VnfPackageChangeNotification> {
+ private static final Logger logger = getLogger(PkgChangeNotificationConverter.class);
+
+ /**
+ * Convert a {@link PkgChangeNotification} Object to an {@link VnfPackageChangeNotification} Object
+ *
+ * @param pkgChangeNotification The PkgChangeNotification Object to Convert
+ * @return The Converted VnfPackageChangeNotification Object
+ */
+ @Override
+ public VnfPackageChangeNotification convert(final PkgChangeNotification pkgChangeNotification) {
+ logger.info("Converting PkgChangeNotification\n{}", pkgChangeNotification.toString());
+ final VnfPackageChangeNotification vnfPackageChangeNotification = new VnfPackageChangeNotification();
+ vnfPackageChangeNotification.setId(pkgChangeNotification.getId());
+
+ if (pkgChangeNotification.getNotificationType() != null) {
+ vnfPackageChangeNotification.setNotificationType(VnfPackageChangeNotification.NotificationTypeEnum
+ .fromValue(pkgChangeNotification.getNotificationType().getValue()));
+ }
+
+ vnfPackageChangeNotification.setSubscriptionId(pkgChangeNotification.getSubscriptionId());
+ vnfPackageChangeNotification.setTimeStamp(pkgChangeNotification.getTimeStamp());
+ vnfPackageChangeNotification.setVnfPkgId(pkgChangeNotification.getVnfPkgId());
+
+ vnfPackageChangeNotification.setVnfdId(pkgChangeNotification.getVnfdId());
+
+ if (pkgChangeNotification.getChangeType() != null) {
+ vnfPackageChangeNotification.setChangeType(VnfPackageChangeNotification.ChangeTypeEnum
+ .fromValue(pkgChangeNotification.getChangeType().getValue()));
+ }
+
+ if (pkgChangeNotification.getOperationalState() != null) {
+ vnfPackageChangeNotification.setOperationalState(VnfPackageChangeNotification.OperationalStateEnum
+ .fromValue(pkgChangeNotification.getOperationalState().getValue()));
+ }
+
+ vnfPackageChangeNotification.setLinks(convert((pkgChangeNotification.getLinks())));
+
+ return vnfPackageChangeNotification;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgOnboardingNotificationConverter.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgOnboardingNotificationConverter.java
new file mode 100644
index 0000000000..9828972fd0
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/PkgOnboardingNotificationConverter.java
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgOnboardingNotification;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.VnfPackageOnboardingNotification;
+import org.slf4j.Logger;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Service;
+
+/**
+ * Converter to convert from an Etsi Catalog Manager {@link PkgOnboardingNotification} Object to its equivalent SOL003
+ * {@link VnfPackageOnboardingNotification} Object
+ *
+ * @author andrew.a.lamb@est.tech
+ */
+@Service
+public class PkgOnboardingNotificationConverter extends AbstractPkgNotificationConverter
+ implements Converter<PkgOnboardingNotification, VnfPackageOnboardingNotification> {
+ private static final Logger logger = getLogger(PkgOnboardingNotificationConverter.class);
+
+ /**
+ * Convert a {@link PkgOnboardingNotification} Object to an {@link VnfPackageOnboardingNotification} Object
+ *
+ * @param pkgOnboardingNotification The PkgOnboardingNotification Object to Convert
+ * @return The Converted VnfPackageOnboardingNotification Object
+ */
+ @Override
+ public VnfPackageOnboardingNotification convert(final PkgOnboardingNotification pkgOnboardingNotification) {
+ logger.info("Converting PkgChangeNotification\n{}", pkgOnboardingNotification.toString());
+ final VnfPackageOnboardingNotification vnfPackageOnboardingNotification =
+ new VnfPackageOnboardingNotification();
+ vnfPackageOnboardingNotification.setId(pkgOnboardingNotification.getId());
+
+ if (pkgOnboardingNotification.getNotificationType() != null) {
+ vnfPackageOnboardingNotification.setNotificationType(VnfPackageOnboardingNotification.NotificationTypeEnum
+ .fromValue(pkgOnboardingNotification.getNotificationType().getValue()));
+ }
+
+ vnfPackageOnboardingNotification.setSubscriptionId(pkgOnboardingNotification.getSubscriptionId());
+ vnfPackageOnboardingNotification.setTimeStamp(pkgOnboardingNotification.getTimeStamp());
+ vnfPackageOnboardingNotification.setVnfPkgId(pkgOnboardingNotification.getVnfPkgId());
+ vnfPackageOnboardingNotification.setVnfdId(pkgOnboardingNotification.getVnfdId());
+
+ vnfPackageOnboardingNotification.setLinks(convert((pkgOnboardingNotification.getLinks())));
+
+ return vnfPackageOnboardingNotification;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/VnfPkgInfoConverter.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/VnfPkgInfoConverter.java
new file mode 100644
index 0000000000..dc25a6fbea
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/VnfPkgInfoConverter.java
@@ -0,0 +1,198 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.onap.so.adapters.vnfmadapter.common.VnfmAdapterUrlProvider;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.Checksum;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VNFPKGMLinkSerializer;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPackageArtifactInfo;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPackageSoftwareImageInfo;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPkgInfo;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse2001;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesAdditionalArtifacts;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesChecksum;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesLinks;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesLinksSelf;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesSoftwareImages;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Service;
+
+/**
+ * Converter to convert from an Etsi Catalog Manager {@link VnfPkgInfo} Object to its equivalent SOL003 Object
+ * {@link InlineResponse2001} Object
+ *
+ * @author andrew.a.lamb@est.tech
+ */
+@Service
+public class VnfPkgInfoConverter implements Converter<VnfPkgInfo, InlineResponse2001> {
+ private static final Logger logger = LoggerFactory.getLogger(VnfPkgInfoConverter.class);
+ private final VnfmAdapterUrlProvider vnfmAdapterUrlProvider;
+
+ public VnfPkgInfoConverter(final VnfmAdapterUrlProvider vnfmAdapterUrlProvider) {
+ this.vnfmAdapterUrlProvider = vnfmAdapterUrlProvider;
+ }
+
+ /**
+ * Convert a {@link VnfPkgInfo} Object to an {@link InlineResponse2001} Object
+ *
+ * @param vnfPkgInfo The VnfPkgInfo Object to Convert
+ * @return The Converted InlineResponse2001 Object
+ */
+ @Override
+ public InlineResponse2001 convert(final VnfPkgInfo vnfPkgInfo) {
+ if (vnfPkgInfo == null) {
+ logger.error("No VnfPkgInfo Object Provided for Conversion. (Null object received, returning Null)");
+ return null;
+ }
+ final InlineResponse2001 response = new InlineResponse2001();
+ response.setId(vnfPkgInfo.getId());
+ response.setVnfdId(vnfPkgInfo.getVnfdId());
+ response.setVnfProvider(vnfPkgInfo.getVnfProvider());
+ response.setVnfProductName(vnfPkgInfo.getVnfProductName());
+ response.setVnfSoftwareVersion(vnfPkgInfo.getVnfSoftwareVersion());
+ response.setVnfdVersion(vnfPkgInfo.getVnfdVersion());
+ response.setChecksum(convertChecksumToVnfPackagesChecksum(vnfPkgInfo.getChecksum()));
+ response.setSoftwareImages(
+ convertVnfPackageSoftwareImageInfoListToVnfPackagesSoftwareImagesList(vnfPkgInfo.getSoftwareImages()));
+ response.setAdditionalArtifacts(convertVnfPackageArtifactInfoListToVnfPackagesAdditionalArtifactsList(
+ vnfPkgInfo.getAdditionalArtifacts()));
+
+ if (vnfPkgInfo.getOnboardingState() != null) {
+ response.setOnboardingState(
+ InlineResponse2001.OnboardingStateEnum.fromValue(vnfPkgInfo.getOnboardingState().getValue()));
+ }
+
+ if (vnfPkgInfo.getOperationalState() != null) {
+ response.setOperationalState(
+ InlineResponse2001.OperationalStateEnum.fromValue(vnfPkgInfo.getOperationalState().getValue()));
+ }
+
+ response.setUserDefinedData((vnfPkgInfo.getUserDefinedData()));
+
+ if (vnfPkgInfo.getLinks() != null) {
+ response.setLinks(getVnfPackagesLinks(vnfPkgInfo.getLinks(), vnfPkgInfo.getId()));
+ }
+
+ return response;
+ }
+
+ private VnfPackagesChecksum convertChecksumToVnfPackagesChecksum(final Checksum checksum) {
+ final VnfPackagesChecksum vnfPackagesChecksum = new VnfPackagesChecksum();
+ if (checksum != null) {
+ vnfPackagesChecksum.setAlgorithm(checksum.getAlgorithm());
+ vnfPackagesChecksum.setHash(checksum.getHash());
+ }
+ return vnfPackagesChecksum;
+ }
+
+ private List<VnfPackagesSoftwareImages> convertVnfPackageSoftwareImageInfoListToVnfPackagesSoftwareImagesList(
+ final List<VnfPackageSoftwareImageInfo> vnfPackageSoftwareImageInfoList) {
+ final List<VnfPackagesSoftwareImages> vnfPackagesSoftwareImages = new ArrayList<>();
+ if (vnfPackageSoftwareImageInfoList != null) {
+ for (final VnfPackageSoftwareImageInfo vnfPackageSoftwareImageInfo : vnfPackageSoftwareImageInfoList) {
+ final VnfPackagesSoftwareImages softwareImage =
+ convertVnfPackageSoftwareImageInfoToVnfPackagesSoftwareImages(vnfPackageSoftwareImageInfo);
+ vnfPackagesSoftwareImages.add(softwareImage);
+ }
+ }
+ return vnfPackagesSoftwareImages;
+ }
+
+ private VnfPackagesSoftwareImages convertVnfPackageSoftwareImageInfoToVnfPackagesSoftwareImages(
+ final VnfPackageSoftwareImageInfo vnfPackageSoftwareImageInfo) {
+ final VnfPackagesSoftwareImages vnfPackagesSoftwareImages = new VnfPackagesSoftwareImages();
+ vnfPackagesSoftwareImages.setId(vnfPackageSoftwareImageInfo.getId());
+ vnfPackagesSoftwareImages.setName(vnfPackageSoftwareImageInfo.getName());
+ vnfPackagesSoftwareImages.setProvider(vnfPackageSoftwareImageInfo.getProvider());
+ vnfPackagesSoftwareImages.setVersion(vnfPackageSoftwareImageInfo.getVersion());
+ vnfPackagesSoftwareImages
+ .setChecksum(convertChecksumToVnfPackagesChecksum(vnfPackageSoftwareImageInfo.getChecksum()));
+ if (vnfPackageSoftwareImageInfo.getContainerFormat() != null) {
+ vnfPackagesSoftwareImages.setContainerFormat(VnfPackagesSoftwareImages.ContainerFormatEnum
+ .fromValue(vnfPackageSoftwareImageInfo.getContainerFormat().getValue()));
+ }
+
+ if (vnfPackageSoftwareImageInfo.getDiskFormat() != null) {
+ vnfPackagesSoftwareImages.setDiskFormat(VnfPackagesSoftwareImages.DiskFormatEnum
+ .fromValue(vnfPackageSoftwareImageInfo.getDiskFormat().getValue()));
+ }
+
+ vnfPackagesSoftwareImages.setCreatedAt(vnfPackageSoftwareImageInfo.getCreatedAt());
+ vnfPackagesSoftwareImages.setMinDisk(vnfPackageSoftwareImageInfo.getMinDisk());
+ vnfPackagesSoftwareImages.setMinRam(vnfPackageSoftwareImageInfo.getMinRam());
+ vnfPackagesSoftwareImages.setSize(vnfPackageSoftwareImageInfo.getSize());
+ vnfPackagesSoftwareImages.setUserMetadata(vnfPackageSoftwareImageInfo.getUserMetadata());
+ vnfPackagesSoftwareImages.setImagePath(vnfPackageSoftwareImageInfo.getImagePath());
+ return vnfPackagesSoftwareImages;
+ }
+
+ private List<VnfPackagesAdditionalArtifacts> convertVnfPackageArtifactInfoListToVnfPackagesAdditionalArtifactsList(
+ final List<VnfPackageArtifactInfo> vnfPackageArtifactInfoList) {
+ if (vnfPackageArtifactInfoList != null) {
+ final List<VnfPackagesAdditionalArtifacts> additionalArtifacts = new ArrayList<>();
+ for (final VnfPackageArtifactInfo artifactInfo : vnfPackageArtifactInfoList) {
+ final VnfPackagesAdditionalArtifacts artifact =
+ convertVnfPackageArtifactInfoToVnfPackagesAdditionalArtifacts(artifactInfo);
+ additionalArtifacts.add(artifact);
+ }
+ return additionalArtifacts;
+ }
+ return null;
+ }
+
+ private VnfPackagesAdditionalArtifacts convertVnfPackageArtifactInfoToVnfPackagesAdditionalArtifacts(
+ final VnfPackageArtifactInfo vnfPackageArtifactInfo) {
+ final VnfPackagesAdditionalArtifacts vnfPackagesAdditionalArtifacts = new VnfPackagesAdditionalArtifacts();
+ vnfPackagesAdditionalArtifacts.setArtifactPath(vnfPackageArtifactInfo.getArtifactPath());
+ vnfPackagesAdditionalArtifacts
+ .setChecksum(convertChecksumToVnfPackagesChecksum(vnfPackageArtifactInfo.getChecksum()));
+ vnfPackagesAdditionalArtifacts.setMetadata(vnfPackageArtifactInfo.getMetadata());
+ return vnfPackagesAdditionalArtifacts;
+ }
+
+ private VnfPackagesLinks getVnfPackagesLinks(final VNFPKGMLinkSerializer links, final String vnfPkgId) {
+ final VnfPackagesLinks vnfPackagesLinks = new VnfPackagesLinks();
+
+ if (links.getSelf() != null) {
+ vnfPackagesLinks.setSelf(getVnfPackagesLinksSelf(vnfmAdapterUrlProvider.getVnfPackageUrl(vnfPkgId)));
+ }
+
+ if (links.getVnfd() != null) {
+ vnfPackagesLinks.setVnfd(getVnfPackagesLinksSelf(vnfmAdapterUrlProvider.getVnfPackageVnfdUrl(vnfPkgId)));
+ }
+
+ if (links.getPackageContent() != null) {
+ vnfPackagesLinks.setPackageContent(
+ getVnfPackagesLinksSelf(vnfmAdapterUrlProvider.getVnfPackageContentUrl(vnfPkgId)));
+ }
+
+ return vnfPackagesLinks;
+ }
+
+ private VnfPackagesLinksSelf getVnfPackagesLinksSelf(final String href) {
+ return new VnfPackagesLinksSelf().href(href);
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/sol003/etsicatalog/PkgmSubscriptionRequestConverter.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/sol003/etsicatalog/PkgmSubscriptionRequestConverter.java
new file mode 100644
index 0000000000..7defa4b278
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/sol003/etsicatalog/PkgmSubscriptionRequestConverter.java
@@ -0,0 +1,198 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.converters.sol003.etsicatalog;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.Version;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfProducts;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfProductsProviders;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilter1;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilter1.NotificationTypesEnum;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilter1.OperationalStateEnum;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilter1.UsageStateEnum;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilterVersions;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilterVnfProducts;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilterVnfProductsFromProviders;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Service;
+
+/**
+ * Converter to convert from an Etsi Catalog Manager {@link PkgmSubscriptionRequest} Object to its equivalent ETSI
+ * Catalog Manager Object
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Service
+public class PkgmSubscriptionRequestConverter implements
+ Converter<PkgmSubscriptionRequest, org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest> {
+
+ @Override
+ public org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest convert(
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+ final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest =
+ new org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest();
+
+ etsiCatalogManagerSubscriptionRequest
+ .setFilter(getPkgmNotificationsFilter(pkgmSubscriptionRequest.getFilter()));
+
+ return etsiCatalogManagerSubscriptionRequest;
+ }
+
+
+ private org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter getPkgmNotificationsFilter(
+ final SubscriptionsFilter1 sol003SubscriptionsFilter) {
+ final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter etsiCatalogManagerFilters =
+ new org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter();
+
+ if (sol003SubscriptionsFilter.getNotificationTypes() != null) {
+ etsiCatalogManagerFilters.setNotificationTypes(
+ getPkgmNotificationsFilterNotificationTypes(sol003SubscriptionsFilter.getNotificationTypes()));
+ }
+
+ etsiCatalogManagerFilters.setVnfProductsFromProviders(
+ getVnfProductsProviders(sol003SubscriptionsFilter.getVnfProductsFromProviders()));
+
+ etsiCatalogManagerFilters.setVnfdId(getVnfdIds(sol003SubscriptionsFilter.getVnfdId()));
+
+ etsiCatalogManagerFilters.setVnfPkgId(getVnfPkgIds(sol003SubscriptionsFilter.getVnfPkgId()));
+
+ etsiCatalogManagerFilters
+ .setOperationalState(getOperationalState(sol003SubscriptionsFilter.getOperationalState()));
+
+ etsiCatalogManagerFilters.setUsageState(getUsageState(sol003SubscriptionsFilter.getUsageState()));
+
+ return etsiCatalogManagerFilters;
+ }
+
+
+ private List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.UsageStateEnum> getUsageState(
+ final List<UsageStateEnum> usageStates) {
+ if (usageStates != null) {
+ final List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.UsageStateEnum> etsiCatalogUsageStates =
+ new ArrayList<>();
+ usageStates.stream().forEach(state -> {
+ etsiCatalogUsageStates.add(
+ org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.UsageStateEnum
+ .fromValue(state.getValue()));
+ });
+ return etsiCatalogUsageStates;
+ }
+ return Collections.emptyList();
+ }
+
+
+ private List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.OperationalStateEnum> getOperationalState(
+ final List<OperationalStateEnum> operationalStates) {
+ if (operationalStates != null) {
+ final List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.OperationalStateEnum> etsiCatalogOperationalStates =
+ new ArrayList<>();
+ operationalStates.forEach(state -> {
+ etsiCatalogOperationalStates.add(
+ org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.OperationalStateEnum
+ .fromValue(state.getValue()));
+ });
+
+ return etsiCatalogOperationalStates;
+ }
+ return Collections.emptyList();
+ }
+
+ private List<String> getVnfPkgIds(final List<String> vnfPkgId) {
+ if (vnfPkgId != null) {
+ final List<String> etsiCatalogManagerVnfPkgId = new ArrayList<>();
+ vnfPkgId.forEach(type -> {
+ etsiCatalogManagerVnfPkgId.add(type);
+ });
+ return etsiCatalogManagerVnfPkgId;
+ }
+ return Collections.emptyList();
+ }
+
+ private List<String> getVnfdIds(final List<String> vnfdId) {
+ if (vnfdId != null) {
+ final List<String> etsiCatalogManagerVnfdId = new ArrayList<>();
+ vnfdId.forEach(type -> {
+ etsiCatalogManagerVnfdId.add(type);
+ });
+ return etsiCatalogManagerVnfdId;
+ }
+ return Collections.emptyList();
+ }
+
+ private List<VnfProductsProviders> getVnfProductsProviders(
+ final List<SubscriptionsFilterVnfProductsFromProviders> filterProductsFromProvider) {
+
+ if (filterProductsFromProvider != null && !filterProductsFromProvider.isEmpty()) {
+ final List<VnfProductsProviders> etsiCatalogManagerVnfProductsProviders = new ArrayList<>();
+ filterProductsFromProvider.forEach(vnfProduct -> {
+ etsiCatalogManagerVnfProductsProviders
+ .add(new VnfProductsProviders().vnfProvider(vnfProduct.getVnfProvider())
+ .vnfProducts(getVnfProducts(vnfProduct.getVnfProducts())));
+ });
+ return etsiCatalogManagerVnfProductsProviders;
+ }
+ return Collections.emptyList();
+ }
+
+ private List<VnfProducts> getVnfProducts(final List<SubscriptionsFilterVnfProducts> sol003VnfProducts) {
+ if (sol003VnfProducts != null) {
+ final List<VnfProducts> etsiCatalogManagerVnfProductsList = new ArrayList<>();
+ sol003VnfProducts.forEach(vnfProduct -> {
+ etsiCatalogManagerVnfProductsList.add(new VnfProducts().vnfProductName(vnfProduct.getVnfProductName())
+ .versions(getVersion(vnfProduct.getVersions())));
+ });
+ return etsiCatalogManagerVnfProductsList;
+ }
+ return Collections.emptyList();
+ }
+
+ private List<Version> getVersion(final List<SubscriptionsFilterVersions> sol003FilterVersions) {
+ if (sol003FilterVersions != null && !sol003FilterVersions.isEmpty()) {
+ final List<Version> etsiCatalogVersionList = new ArrayList<>();
+ sol003FilterVersions.forEach(vnfFilterVersion -> {
+ etsiCatalogVersionList.add(new Version().vnfSoftwareVersion(vnfFilterVersion.getVnfSoftwareVersion())
+ .vnfdVersions(vnfFilterVersion.getVnfdVersions()));
+ });
+ return etsiCatalogVersionList;
+ }
+ return Collections.emptyList();
+ }
+
+ private List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.NotificationTypesEnum> getPkgmNotificationsFilterNotificationTypes(
+ final List<NotificationTypesEnum> notificationTypes) {
+
+ if (notificationTypes != null && !notificationTypes.isEmpty()) {
+ final List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.NotificationTypesEnum> etsiCatalogNotificationTypes =
+ new ArrayList<>();
+ notificationTypes.forEach(type -> etsiCatalogNotificationTypes.add(
+ org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.NotificationTypesEnum
+ .fromValue(type.getValue())));
+ return etsiCatalogNotificationTypes;
+ }
+ return Collections.emptyList();
+ }
+
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/AbstractServiceProviderConfiguration.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/AbstractServiceProviderConfiguration.java
new file mode 100644
index 0000000000..7b6faf2876
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/AbstractServiceProviderConfiguration.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.extclients;
+
+import java.util.Iterator;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.JSON;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.GsonHttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+import com.google.gson.Gson;
+
+/**
+ * A base class that can be extended by classes for configuring HttpRestServiceProvider classes. Provides common methods
+ * that will be useful to some such classes.
+ *
+ * @author gareth.roper@est.tech
+ */
+public abstract class AbstractServiceProviderConfiguration {
+
+ public void setGsonMessageConverter(final RestTemplate restTemplate) {
+ final Iterator<HttpMessageConverter<?>> iterator = restTemplate.getMessageConverters().iterator();
+ while (iterator.hasNext()) {
+ if (iterator.next() instanceof MappingJackson2HttpMessageConverter) {
+ iterator.remove();
+ }
+ }
+ final Gson gson = new JSON().getGson();
+ restTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java
new file mode 100644
index 0000000000..9e12b536c9
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
+
+import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse2001;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface EtsiCatalogPackageManagementServiceProvider {
+
+ /**
+ * GET Package Content, from VNF Package.
+ *
+ * @param vnfPkgId The ID of the VNF Package from which the "package_content" will be retrieved.
+ * @return The Package Content of a VNF Package ("vnfPkgId").
+ */
+ Optional<byte[]> getVnfPackageContent(final String vnfPkgId);
+
+ /**
+ * GET VNF packages information from ETSI Catalog. Will return zero or more VNF package representations.
+ *
+ * @return An Array of all VNF packages retrieved from the ETSI Catalog.
+ */
+ Optional<InlineResponse2001[]> getVnfPackages();
+
+ /**
+ * GET specific VNF package information from ETSI Catalog.
+ *
+ * @param vnfPkgId The ID of the VNF Package that you want to query.
+ * @return The VNF package retrieved from the ETSI Catalog
+ */
+ Optional<InlineResponse2001> getVnfPackage(final String vnfPkgId);
+
+ /**
+ * GET specific VNF package VNFD from ETSI Catalog.
+ *
+ * @param vnfPkgId The ID of the VNF Package that you want to query.
+ * @return The VNF package retrieved from the ETSI Catalog
+ */
+ Optional<byte[]> getVnfPackageVnfd(final String vnfPkgId);
+
+ /**
+ * GET Package Artifact, from VNF Package.
+ *
+ * @param vnfPkgId The ID of the VNF Package from which the artifact will be retrieved.
+ * @param artifactPath Sequence of one or more path segments representing the path of the artifact within the VNF
+ * Package, e.g., foo/bar/run.sh
+ * @return The Package Artifact of a VNF Package ("vnfPkgId", "artifactPath").
+ */
+ Optional<byte[]> getVnfPackageArtifact(final String vnfPkgId, final String artifactPath);
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java
new file mode 100644
index 0000000000..61db82f38c
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
+
+/**
+ * Provides methods for invoking REST calls to the ETSI Catalog Manager.
+ *
+ * @author gareth.roper@est.tech
+ */
+public interface EtsiCatalogServiceProvider
+ extends EtsiCatalogSubscriptionServiceProvider, EtsiCatalogPackageManagementServiceProvider {
+
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java
new file mode 100644
index 0000000000..fc44a6ec6f
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java
@@ -0,0 +1,187 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.logging.filter.spring.SpringClientPayloadFilter;
+import org.onap.so.adapters.vnfmadapter.extclients.AbstractServiceProviderConfiguration;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.onap.so.configuration.rest.HttpClientConnectionConfiguration;
+import org.onap.so.logging.jaxrs.filter.SOSpringClientFilter;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.onap.so.rest.service.HttpRestServiceProviderImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.GsonHttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * Configures the HttpRestServiceProvider to make REST calls to the ETSI Catalog Manager
+ *
+ * @author gareth.roper@est.tech
+ */
+
+@Configuration
+public class EtsiCatalogServiceProviderConfiguration extends AbstractServiceProviderConfiguration {
+
+ public static final String ETSI_CATALOG_REST_TEMPLATE_BEAN = "etsiCatalogRestTemplate";
+
+ public static final String ETSI_CATALOG_SERVICE_PROVIDER_BEAN = "etsiCatalogServiceProvider";
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(EtsiCatalogServiceProviderConfiguration.class);
+
+ private final HttpClientConnectionConfiguration clientConnectionConfiguration;
+
+ @Value("${etsi-catalog-manager.http.client.ssl.trust-store:#{null}}")
+ private Resource trustStore;
+ @Value("${etsi-catalog-manager.http.client.ssl.trust-store-password:#{null}}")
+ private String trustStorePassword;
+
+ @Autowired
+ public EtsiCatalogServiceProviderConfiguration(
+ final HttpClientConnectionConfiguration clientConnectionConfiguration) {
+ this.clientConnectionConfiguration = clientConnectionConfiguration;
+ }
+
+ @Bean
+ @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
+ public RestTemplate etsiCatalogRestTemplate() {
+ final RestTemplate restTemplate = new RestTemplate();
+ restTemplate.getInterceptors().add(new SOSpringClientFilter());
+ restTemplate.getInterceptors().add((new SpringClientPayloadFilter()));
+ return restTemplate;
+ }
+
+ @Bean
+ @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN)
+ public HttpRestServiceProvider etsiCatalogHttpRestServiceProvider(
+ @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN) final RestTemplate restTemplate) {
+ setGsonMessageConverter(restTemplate);
+
+ final HttpClientBuilder httpClientBuilder = getHttpClientBuilder();
+ if (trustStore != null) {
+ try {
+ LOGGER.debug("Setting up HttpComponentsClientHttpRequestFactory with SSL Context");
+ LOGGER.debug("Setting client trust-store: {}", trustStore.getURL());
+ LOGGER.debug("Creating SSLConnectionSocketFactory with AllowAllHostsVerifier ... ");
+ final SSLContext sslContext = new SSLContextBuilder()
+ .loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray()).build();
+ final SSLConnectionSocketFactory sslConnectionSocketFactory =
+ new SSLConnectionSocketFactory(sslContext, AllowAllHostsVerifier.INSTANCE);
+ httpClientBuilder.setSSLSocketFactory(sslConnectionSocketFactory);
+ final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
+ .<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
+ .register("https", sslConnectionSocketFactory).build();
+
+ httpClientBuilder.setConnectionManager(getConnectionManager(socketFactoryRegistry));
+ } catch (final KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException
+ | IOException exception) {
+ LOGGER.error("Error reading truststore, TLS connection will fail.", exception);
+ }
+
+ } else {
+ LOGGER.debug("Setting connection manager without SSL ConnectionSocketFactory ...");
+ httpClientBuilder.setConnectionManager(getConnectionManager());
+ }
+
+ final HttpComponentsClientHttpRequestFactory factory =
+ new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
+ restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(factory));
+
+ return new HttpRestServiceProviderImpl(restTemplate, new BasicHttpHeadersProvider().getHttpHeaders());
+ }
+
+ private PoolingHttpClientConnectionManager getConnectionManager(
+ final Registry<ConnectionSocketFactory> socketFactoryRegistry) {
+ return new PoolingHttpClientConnectionManager(socketFactoryRegistry, null, null, null,
+ clientConnectionConfiguration.getTimeToLiveInMins(), TimeUnit.MINUTES);
+ }
+
+ private PoolingHttpClientConnectionManager getConnectionManager() {
+ return new PoolingHttpClientConnectionManager(clientConnectionConfiguration.getTimeToLiveInMins(),
+ TimeUnit.MINUTES);
+ }
+
+ private HttpClientBuilder getHttpClientBuilder() {
+ return HttpClientBuilder.create().setMaxConnPerRoute(clientConnectionConfiguration.getMaxConnectionsPerRoute())
+ .setMaxConnTotal(clientConnectionConfiguration.getMaxConnections())
+ .setDefaultRequestConfig(getRequestConfig());
+ }
+
+ private RequestConfig getRequestConfig() {
+ return RequestConfig.custom().setSocketTimeout(clientConnectionConfiguration.getSocketTimeOutInMiliSeconds())
+ .setConnectTimeout(clientConnectionConfiguration.getConnectionTimeOutInMilliSeconds()).build();
+ }
+
+ private static final class AllowAllHostsVerifier implements HostnameVerifier {
+
+ private static final AllowAllHostsVerifier INSTANCE = new AllowAllHostsVerifier();
+
+ @Override
+ public boolean verify(final String hostname, final SSLSession session) {
+ LOGGER.debug("Skipping hostname verification ...");
+ return true;
+ }
+
+ }
+
+ public void setGsonMessageConverter(final RestTemplate restTemplate) {
+ final Iterator<HttpMessageConverter<?>> iterator = restTemplate.getMessageConverters().iterator();
+ while (iterator.hasNext()) {
+ if (iterator.next() instanceof MappingJackson2HttpMessageConverter) {
+ iterator.remove();
+ }
+ }
+ final Gson gson = new GsonBuilder().create();
+ restTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java
new file mode 100644
index 0000000000..6651bc136e
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java
@@ -0,0 +1,281 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
+
+import static org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_SERVICE_PROVIDER_BEAN;
+import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.NsdmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPkgInfo;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse2001;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.EtsiCatalogManagerBadRequestException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.EtsiCatalogManagerRequestFailureException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.SubscriptionNotFoundException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.VnfPkgBadRequestException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.VnfPkgConflictException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.VnfPkgNotFoundException;
+import org.onap.so.rest.exceptions.HttpResouceNotFoundException;
+import org.onap.so.rest.exceptions.InvalidRestRequestException;
+import org.onap.so.rest.exceptions.RestProcessingException;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+/**
+ * Provides the implementations of the REST Requests to the ETSI Catalog Manager.
+ *
+ * @author gareth.roper@est.tech
+ */
+@Service
+public class EtsiCatalogServiceProviderImpl implements EtsiCatalogServiceProvider {
+ private static final Logger logger = LoggerFactory.getLogger(EtsiCatalogServiceProviderImpl.class);
+
+ private final HttpRestServiceProvider httpServiceProvider;
+ private final EtsiCatalogUrlProvider etsiCatalogUrlProvider;
+ private final ConversionService conversionService;
+
+ @Autowired
+ public EtsiCatalogServiceProviderImpl(final EtsiCatalogUrlProvider etsiCatalogUrlProvider,
+ @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN) final HttpRestServiceProvider httpServiceProvider,
+ final ConversionService conversionService) {
+ this.etsiCatalogUrlProvider = etsiCatalogUrlProvider;
+ this.httpServiceProvider = httpServiceProvider;
+ this.conversionService = conversionService;
+ }
+
+ @Override
+ public Optional<byte[]> getVnfPackageContent(final String vnfPkgId)
+ throws EtsiCatalogManagerRequestFailureException {
+ final String vnfRequestUrl = etsiCatalogUrlProvider.getVnfPackageContentUrl(vnfPkgId);
+ final String vnfRequestName = "getVnfPackageContent";
+ return requestVnfElement(vnfPkgId, vnfRequestUrl, vnfRequestName);
+ }
+
+ @Override
+ public Optional<byte[]> getVnfPackageArtifact(final String vnfPkgId, final String artifactPath) {
+ try {
+ final ResponseEntity<byte[]> response = httpServiceProvider.getHttpResponse(
+ etsiCatalogUrlProvider.getVnfPackageArtifactUrl(vnfPkgId, artifactPath), byte[].class);
+ logger.info("getVnfPackageArtifact Request to ETSI Catalog Manager Status Code: {}",
+ response.getStatusCodeValue());
+ if (response.getStatusCode().is2xxSuccessful()) {
+ return Optional.ofNullable(response.getBody());
+ }
+ } catch (final HttpResouceNotFoundException httpResouceNotFoundException) {
+ logger.error("Caught HttpResouceNotFoundException", httpResouceNotFoundException);
+ throw new VnfPkgNotFoundException("No Vnf Package Artifact found with vnfPkgId: \"" + vnfPkgId
+ + "\" and artifactPath: \"" + artifactPath + "\".");
+ } catch (final RestProcessingException restProcessingException) {
+ logger.error("Caught RestProcessingException with Status Code: {}", restProcessingException.getStatusCode(),
+ restProcessingException);
+ if (restProcessingException.getStatusCode() == HttpStatus.CONFLICT.value()) {
+ throw new VnfPkgConflictException("A conflict occurred with the state of the resource,\n"
+ + "due to the attribute: onboardingState not being set to ONBOARDED.");
+ }
+ }
+ throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.");
+ }
+
+ @Override
+ public Optional<InlineResponse2001[]> getVnfPackages() {
+ try {
+ final ResponseEntity<VnfPkgInfo[]> response =
+ httpServiceProvider.getHttpResponse(etsiCatalogUrlProvider.getVnfPackagesUrl(), VnfPkgInfo[].class);
+ logger.info("getVnfPackages Request to ETSI Catalog Manager Status Code: {}",
+ response.getStatusCodeValue());
+ if (response.getStatusCode().is2xxSuccessful()) {
+ if (response.hasBody()) {
+ final VnfPkgInfo[] vnfPackages = response.getBody();
+ assert (vnfPackages != null);
+ final InlineResponse2001[] responses = new InlineResponse2001[vnfPackages.length];
+ for (int index = 0; index < vnfPackages.length; index++) {
+ if (conversionService.canConvert(vnfPackages[index].getClass(), InlineResponse2001.class)) {
+ final InlineResponse2001 inlineResponse2001 =
+ conversionService.convert(vnfPackages[index], InlineResponse2001.class);
+ if (inlineResponse2001 != null) {
+ responses[index] = inlineResponse2001;
+ }
+ } else {
+ logger.error("Unable to find Converter for response class: {}",
+ vnfPackages[index].getClass());
+ }
+ }
+ return Optional.of(responses);
+ }
+ logger.error("Received response without body ...");
+ }
+ logger.error("Unexpected status code received {}", response.getStatusCode());
+ return Optional.empty();
+ } catch (final InvalidRestRequestException invalidRestRequestException) {
+ logger.error("Caught InvalidRestRequestException", invalidRestRequestException);
+ throw new VnfPkgBadRequestException("Error: Bad Request Received");
+ } catch (final HttpResouceNotFoundException httpResouceNotFoundException) {
+ logger.error("Caught HttpResouceNotFoundException", httpResouceNotFoundException);
+ throw new VnfPkgNotFoundException("No Vnf Packages found");
+ } catch (final RestProcessingException restProcessingException) {
+ logger.error("Caught RestProcessingException with Status Code: {}", restProcessingException.getStatusCode(),
+ restProcessingException);
+ throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.");
+ }
+ }
+
+ @Override
+ public Optional<InlineResponse2001> getVnfPackage(final String vnfPkgId) {
+ try {
+ final ResponseEntity<VnfPkgInfo> response = httpServiceProvider
+ .getHttpResponse(etsiCatalogUrlProvider.getVnfPackageUrl(vnfPkgId), VnfPkgInfo.class);
+ logger.info("getVnfPackage Request for vnfPkgId {} to ETSI Catalog Manager Status Code: {}", vnfPkgId,
+ response.getStatusCodeValue());
+ if (response.getStatusCode().is2xxSuccessful()) {
+ if (response.hasBody()) {
+ final VnfPkgInfo vnfPkgInfo = response.getBody();
+ if (conversionService.canConvert(vnfPkgInfo.getClass(), InlineResponse2001.class)) {
+ return Optional.ofNullable(conversionService.convert(vnfPkgInfo, InlineResponse2001.class));
+ }
+ logger.error("Unable to find Converter for response class: {}", vnfPkgInfo.getClass());
+ }
+ logger.error("Received response without body ....");
+ }
+ return Optional.empty();
+ } catch (final InvalidRestRequestException invalidRestRequestException) {
+ logger.error("Caught InvalidRestRequestException", invalidRestRequestException);
+ throw new VnfPkgBadRequestException("Error: Bad Request Received");
+ } catch (final HttpResouceNotFoundException httpResouceNotFoundException) {
+ logger.error("Caught HttpResouceNotFoundException", httpResouceNotFoundException);
+ throw new VnfPkgNotFoundException("No Vnf Package found with vnfPkgId: " + vnfPkgId);
+ } catch (final RestProcessingException restProcessingException) {
+ logger.error("Caught RestProcessingException with Status Code: {}", restProcessingException.getStatusCode(),
+ restProcessingException);
+ throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.");
+ }
+ }
+
+ @Override
+ public Optional<byte[]> getVnfPackageVnfd(final String vnfPkgId) {
+ final String vnfRequestUrl = etsiCatalogUrlProvider.getVnfPackageVnfdUrl(vnfPkgId);
+ final String vnfRequestName = "getVnfPackageVnfd";
+ return requestVnfElement(vnfPkgId, vnfRequestUrl, vnfRequestName);
+ }
+
+ @Override
+ public Optional<PkgmSubscription> postSubscription(
+ final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest) {
+ try {
+ final ResponseEntity<PkgmSubscription> responseEntity =
+ httpServiceProvider.postHttpRequest(etsiCatalogManagerSubscriptionRequest,
+ etsiCatalogUrlProvider.getSubscriptionUrl(), PkgmSubscription.class);
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ if (responseEntity.hasBody()) {
+ return Optional.of(responseEntity.getBody());
+ }
+ logger.error("Received response without body on postSubscription");
+ }
+ logger.error("Unexpected Status Code Received on postSubscription: {}", responseEntity.getStatusCode());
+ return Optional.empty();
+ } catch (final InvalidRestRequestException invalidRestRequestException) {
+ logger.error("Caught InvalidRestRequestException", invalidRestRequestException);
+ throw new EtsiCatalogManagerBadRequestException(
+ "Bad Request Received on postSubscription call to ETSI Catalog Manager.");
+ } catch (final RestProcessingException restProcessingException) {
+ logger.error("Caught RestProcessingException with Status Code: {}", restProcessingException.getStatusCode(),
+ restProcessingException);
+ throw new EtsiCatalogManagerRequestFailureException(
+ "Internal Server Error Occurred. On postSubscription with StatusCode: "
+ + restProcessingException.getStatusCode());
+ }
+ }
+
+ @Override
+ public boolean deleteSubscription(final String subscriptionId) {
+ try {
+ final ResponseEntity<Void> responseEntity = httpServiceProvider
+ .deleteHttpRequest(etsiCatalogUrlProvider.getSubscriptionUrl() + "/" + subscriptionId, Void.class);
+
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ logger.info("Subscription with ID: {} has been successfully deleted from the ETSI Catalog Manager",
+ subscriptionId);
+ return true;
+ }
+ logger.error("Unexpected Status Code Received on deleteSubscription: {}", responseEntity.getStatusCode());
+ return false;
+ } catch (final HttpResouceNotFoundException resouceNotFoundException) {
+ final String message = "Unable to find subscription in ETSI Catalog Manager using id: " + subscriptionId;
+ logger.error(message);
+ throw new SubscriptionNotFoundException(message);
+ } catch (final InvalidRestRequestException invalidRestRequestException) {
+ logger.error("Caught InvalidRestRequestException on deleteSubscription call to ETSI Catalog Manager.",
+ invalidRestRequestException);
+ throw new EtsiCatalogManagerBadRequestException(
+ "Bad Request Received on deleteSubscription call to ETSI Catalog Manager.");
+ }
+ }
+
+ @Override
+ public Optional<NsdmSubscription> getSubscription(final String subscriptionId) {
+ try {
+ final ResponseEntity<NsdmSubscription> responseEntity = httpServiceProvider.getHttpResponse(
+ etsiCatalogUrlProvider.getSubscriptionUrl() + "/" + subscriptionId, NsdmSubscription.class);
+
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ logger.debug("Found subscription with ID: {} in ETSI Catalog Manager", subscriptionId);
+ return Optional.ofNullable(responseEntity.getBody());
+ }
+ logger.error("Unexpected Status Code Received on getting subscription from ETSI Catalog Manager: {}",
+ responseEntity.getStatusCode());
+ } catch (final HttpResouceNotFoundException resouceNotFoundException) {
+ logger.error("Unable to find subscription in ETSI Catalog Manager using id: {}", subscriptionId);
+ return Optional.empty();
+ } catch (final RestProcessingException | InvalidRestRequestException exception) {
+ logger.error("Unable to query ETSI Catalog Manager for subscription using id: {}", subscriptionId,
+ exception);
+ }
+ throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.");
+ }
+
+ private Optional<byte[]> requestVnfElement(final String vnfPkgId, final String vnfRequestUrl,
+ final String vnfRequestName) {
+ try {
+ final ResponseEntity<byte[]> response = httpServiceProvider.getHttpResponse(vnfRequestUrl, byte[].class);
+ logger.info("{} Request to ETSI Catalog Manager Status Code: {}", vnfRequestName,
+ response.getStatusCodeValue());
+ if (response.getStatusCode() == HttpStatus.OK) {
+ return Optional.ofNullable(response.getBody());
+ }
+ } catch (final HttpResouceNotFoundException httpResouceNotFoundException) {
+ logger.error("Caught HttpResouceNotFoundException", httpResouceNotFoundException);
+ throw new VnfPkgNotFoundException("No Vnf Package found with vnfPkgId: " + vnfPkgId);
+ } catch (final RestProcessingException restProcessingException) {
+ logger.error("Caught RestProcessingException with Status Code: {}", restProcessingException.getStatusCode(),
+ restProcessingException);
+ if (restProcessingException.getStatusCode() == HttpStatus.CONFLICT.value()) {
+ throw new VnfPkgConflictException("A conflict occurred with the state of the resource,\n"
+ + "due to the attribute: onboardingState not being set to ONBOARDED.");
+ }
+ }
+ throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.");
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogSubscriptionServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogSubscriptionServiceProvider.java
new file mode 100644
index 0000000000..ed04ad7746
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogSubscriptionServiceProvider.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
+
+import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.NsdmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface EtsiCatalogSubscriptionServiceProvider {
+
+ /**
+ * POST the SubscriptionRequest Object.
+ *
+ * @return The ETSI Catalog Manager's PkgmSubscription object.
+ */
+ Optional<PkgmSubscription> postSubscription(
+ final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest);
+
+ /**
+ * Get the Subscription from ETSI Catalog.
+ *
+ * @param subscriptionId Subscription ID
+ * @return The Subscription {@link NsdmSubscription} from ETSI Catalog
+ */
+ Optional<NsdmSubscription> getSubscription(final String subscriptionId);
+
+ /**
+ * DELETE the SubscriptionRequest Object.
+ *
+ * @return A Boolean representing if the delete was successful or not.
+ */
+ boolean deleteSubscription(final String subscriptionId);
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java
new file mode 100644
index 0000000000..3b4c4c3066
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * Provides the URLs for the REST Requests to the ETSI Catalog Manager.
+ *
+ * @author gareth.roper@est.tech
+ */
+@Service
+public class EtsiCatalogUrlProvider {
+
+ private static final Logger logger = getLogger(EtsiCatalogUrlProvider.class);
+
+ @Value("${etsi-catalog-manager.vnfpkgm.endpoint}")
+ private String etsiCatalogManagerEndpoint;
+
+ public EtsiCatalogUrlProvider() {}
+
+ /**
+ * Get the URL for retrieving the Package Content from the ETSI Catalog.".
+ *
+ * @param vnfPkgId The ID of the VNF Package
+ * @return the URL for the GET operation
+ */
+ public String getVnfPackageContentUrl(final String vnfPkgId) {
+ final String url = etsiCatalogManagerEndpoint + "/vnf_packages/" + vnfPkgId + "/package_content";
+ logger.info("getEtsiCatalogVnfPackageContentUrl: {}", url);
+ return url;
+ }
+
+ /**
+ * Get the URL for retrieving VNF packages information from ETSI Catalog.".
+ *
+ * @return the URL for the GET operation
+ */
+ public String getVnfPackagesUrl() {
+ final String url = etsiCatalogManagerEndpoint + "/vnf_packages";
+ logger.info("getEtsiCatalogVnfPackagesEndpoint: {}", url);
+ return url;
+ }
+
+ /**
+ * Get the URL for retrieving specific VNF package information from the ETSI Catalog.".
+ *
+ * @param vnfPkgId The ID of the VNF Package
+ * @return the URL for the GET operation
+ */
+ public String getVnfPackageUrl(final String vnfPkgId) {
+ final String url = etsiCatalogManagerEndpoint + "/vnf_packages/" + vnfPkgId;
+ logger.info("getEtsiCatalogVnfPackageEndpoint: {}", url);
+ return url;
+ }
+
+ /**
+ * Get the URL for retrieving VNF Package Artifacts
+ *
+ * @param vnfPkgId The ID of the VNF Package
+ * @param artifactPath The path to the Artifact
+ * @return the URL for the GET operation
+ */
+ public String getVnfPackageArtifactUrl(final String vnfPkgId, final String artifactPath) {
+ final String url = etsiCatalogManagerEndpoint + "/vnf_packages/" + vnfPkgId + "/artifacts/" + artifactPath;
+ logger.info("getVnfPackageArtifactUrl: {}", url);
+ return url;
+ }
+
+ /**
+ * Get the URL for retrieving VNF packages vnfd from ETSI Catalog.
+ *
+ * @param vnfPkgId The ID of the VNF Package
+ * @return the URL for the GET operation
+ */
+ public String getVnfPackageVnfdUrl(final String vnfPkgId) {
+ final String url = etsiCatalogManagerEndpoint + "/vnf_packages/" + vnfPkgId + "/vnfd";
+ logger.info("getEtsiCatalogVnfPackageVnfd: {}", url);
+ return url;
+ }
+
+ /**
+ * Get the URL for posting/retrieving a Subscription
+ *
+ * @return the URL for the operation
+ */
+ public String getSubscriptionUrl() {
+ final String url = etsiCatalogManagerEndpoint + "/subscriptions";
+ logger.info("getSubscriptionNotificationUrl: {}", url);
+ return url;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmHttpServiceProviderConfiguration.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmHttpServiceProviderConfiguration.java
new file mode 100644
index 0000000000..9ed17e4379
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmHttpServiceProviderConfiguration.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.extclients.vnfm;
+
+import static org.onap.so.client.RestTemplateConfig.CONFIGURABLE_REST_TEMPLATE;
+import org.onap.so.adapters.vnfmadapter.extclients.AbstractServiceProviderConfiguration;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.onap.so.rest.service.HttpRestServiceProviderImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Configuration
+public class VnfmHttpServiceProviderConfiguration extends AbstractServiceProviderConfiguration {
+ public static final String VNFM_ADAPTER_HTTP_SERVICE_PROVIDER_BEAN = "vnfmAdapterHttpServiceProvider";
+
+ @Bean
+ @Qualifier(VNFM_ADAPTER_HTTP_SERVICE_PROVIDER_BEAN)
+ public HttpRestServiceProvider vnfmAdapterHttpRestServiceProvider(
+ @Autowired @Qualifier(CONFIGURABLE_REST_TEMPLATE) RestTemplate restTemplate) {
+ setGsonMessageConverter(restTemplate);
+ return new HttpRestServiceProviderImpl(restTemplate, new BasicHttpHeadersProvider().getHttpHeaders());
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderConfiguration.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderConfiguration.java
new file mode 100644
index 0000000000..eaaa8d8544
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderConfiguration.java
@@ -0,0 +1,154 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.extclients.vnfm;
+
+import static org.onap.so.client.RestTemplateConfig.CONFIGURABLE_REST_TEMPLATE;
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.net.ssl.SSLContext;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrVnfm;
+import org.onap.so.adapters.vnfmadapter.extclients.AbstractServiceProviderConfiguration;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.onap.so.rest.service.HttpRestServiceProviderImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.security.oauth2.client.OAuth2RestTemplate;
+import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Configures the HttpRestServiceProvider for REST call to a VNFM.
+ */
+@Configuration
+public class VnfmServiceProviderConfiguration extends AbstractServiceProviderConfiguration {
+
+ private static final Logger logger = LoggerFactory.getLogger(VnfmServiceProviderConfiguration.class);
+ private Map<String, HttpRestServiceProvider> mapOfVnfmIdToHttpRestServiceProvider = new ConcurrentHashMap<>();
+
+ @Value("${http.client.ssl.trust-store:#{null}}")
+ private Resource trustStore;
+ @Value("${http.client.ssl.trust-store-password:#{null}}")
+ private String trustStorePassword;
+
+ @Value("${server.ssl.key-store:#{null}}")
+ private Resource keyStoreResource;
+ @Value("${server.ssl.key--store-password:#{null}}")
+ private String keyStorePassword;
+
+ /**
+ * This property is only intended to be temporary until the AAI schema is updated to support setting the endpoint
+ */
+ @Value("${vnfmadapter.temp.vnfm.oauth.endpoint:#{null}}")
+ private String oauthEndpoint;
+
+ @Qualifier(CONFIGURABLE_REST_TEMPLATE)
+ @Autowired()
+ private RestTemplate defaultRestTemplate;
+
+ public HttpRestServiceProvider getHttpRestServiceProvider(final EsrVnfm vnfm) {
+ if (!mapOfVnfmIdToHttpRestServiceProvider.containsKey(vnfm.getVnfmId())) {
+ mapOfVnfmIdToHttpRestServiceProvider.put(vnfm.getVnfmId(), createHttpRestServiceProvider(vnfm));
+ }
+ return mapOfVnfmIdToHttpRestServiceProvider.get(vnfm.getVnfmId());
+ }
+
+ private HttpRestServiceProvider createHttpRestServiceProvider(final EsrVnfm vnfm) {
+ final RestTemplate restTemplate = createRestTemplate(vnfm);
+ setGsonMessageConverter(restTemplate);
+ if (trustStore != null) {
+ setTrustStore(restTemplate);
+ }
+ return new HttpRestServiceProviderImpl(restTemplate, new BasicHttpHeadersProvider().getHttpHeaders());
+ }
+
+ private RestTemplate createRestTemplate(final EsrVnfm vnfm) {
+ if (vnfm != null) {
+ for (final EsrSystemInfo esrSystemInfo : vnfm.getEsrSystemInfoList().getEsrSystemInfo()) {
+ if (!StringUtils.isEmpty(esrSystemInfo.getUserName())
+ && !StringUtils.isEmpty(esrSystemInfo.getPassword())) {
+ return createOAuth2RestTemplate(esrSystemInfo);
+ }
+ }
+ }
+ return defaultRestTemplate;
+ }
+
+ private OAuth2RestTemplate createOAuth2RestTemplate(final EsrSystemInfo esrSystemInfo) {
+ logger.debug("Getting OAuth2RestTemplate ...");
+ final ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
+ resourceDetails.setId(UUID.randomUUID().toString());
+ resourceDetails.setClientId(esrSystemInfo.getUserName());
+ resourceDetails.setClientSecret(esrSystemInfo.getPassword());
+ resourceDetails.setAccessTokenUri(
+ oauthEndpoint == null ? esrSystemInfo.getServiceUrl().replace("vnflcm/v1", "oauth/token")
+ : oauthEndpoint);
+ resourceDetails.setGrantType("client_credentials");
+ return new OAuth2RestTemplate(resourceDetails);
+ }
+
+ private void setTrustStore(final RestTemplate restTemplate) {
+ SSLContext sslContext;
+ try {
+ if (keyStoreResource != null) {
+ KeyStore keystore = KeyStore.getInstance("pkcs12");
+ keystore.load(keyStoreResource.getInputStream(), keyStorePassword.toCharArray());
+ sslContext =
+ new SSLContextBuilder().loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray())
+ .loadKeyMaterial(keystore, keyStorePassword.toCharArray()).build();
+ } else {
+ sslContext = new SSLContextBuilder()
+ .loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray()).build();
+ }
+ logger.info("Setting truststore: {}", trustStore.getURL());
+ final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
+ final HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
+ final HttpComponentsClientHttpRequestFactory factory =
+ new HttpComponentsClientHttpRequestFactory(httpClient);
+ restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(factory));
+ } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException
+ | IOException | UnrecoverableKeyException exception) {
+ logger.error("Error reading truststore, TLS connection to VNFM will fail.", exception);
+ }
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/AbstractNotificationServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/AbstractNotificationServiceProvider.java
new file mode 100644
index 0000000000..d6b7ae7201
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/AbstractNotificationServiceProvider.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.onap.so.adapters.vnfmadapter.extclients.vnfm.VnfmHttpServiceProviderConfiguration.VNFM_ADAPTER_HTTP_SERVICE_PROVIDER_BEAN;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.codec.binary.Base64;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+/**
+ * A base class that can be extended by classes for providing notification services. Provides common methods that will
+ * be useful to those classes.
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+public abstract class AbstractNotificationServiceProvider {
+
+ @Autowired
+ @Qualifier(VNFM_ADAPTER_HTTP_SERVICE_PROVIDER_BEAN)
+ private HttpRestServiceProvider httpRestServiceProvider;
+
+ protected HttpRestServiceProvider getHttpRestServiceProvider() {
+ return httpRestServiceProvider;
+ }
+
+ protected BasicHttpHeadersProvider getBasicHttpHeadersProviderWithBasicAuth(final String username,
+ final String password) {
+ final byte[] encodedAuth = getBasicAuth(username, password);
+ final String authHeader = "Basic " + new String(encodedAuth);
+ return new BasicHttpHeadersProvider(authHeader);
+ }
+
+ protected byte[] getBasicAuth(final String username, final String password) {
+ final String auth = username + ":" + password;
+ return Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/BasicAuthNotificationServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/BasicAuthNotificationServiceProvider.java
new file mode 100644
index 0000000000..4bed300a08
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/BasicAuthNotificationServiceProvider.java
@@ -0,0 +1,68 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication.AuthTypeEnum;
+import org.onap.so.configuration.rest.HttpHeadersProvider;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.slf4j.Logger;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+/**
+ * Implementation of a NotificationServiceProvider which supports Basic Authentication
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@Service
+public class BasicAuthNotificationServiceProvider extends AbstractNotificationServiceProvider
+ implements NotificationServiceProvider {
+
+ private static final Logger logger = getLogger(BasicAuthNotificationServiceProvider.class);
+
+ @Override
+ public boolean send(final Object notification, final SubscriptionsAuthentication subscriptionsAuthentication,
+ final String callbackUri) {
+ logger.info("Sending notification to uri: {}", callbackUri);
+ final HttpHeadersProvider httpHeadersProvider =
+ getBasicHttpHeadersProviderWithBasicAuth(subscriptionsAuthentication.getParamsBasic().getUserName(),
+ subscriptionsAuthentication.getParamsBasic().getPassword());
+ final HttpRestServiceProvider httpRestServiceProvider = getHttpRestServiceProvider();
+
+ final ResponseEntity<Void> responseEntity = httpRestServiceProvider.postHttpRequest(notification, callbackUri,
+ httpHeadersProvider.getHttpHeaders(), Void.class);
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ logger.info("Notification sent successfully.");
+ return true;
+ }
+
+ logger.error("Failed to send notification.");
+ return false;
+ }
+
+ @Override
+ public AuthTypeEnum getAuthType() {
+ return AuthTypeEnum.BASIC;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationManager.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationManager.java
new file mode 100644
index 0000000000..ad85abe053
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationManager.java
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import java.util.List;
+import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgChangeNotification;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgOnboardingNotification;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication.AuthTypeEnum;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.VnfPackageChangeNotification;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.VnfPackageOnboardingNotification;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.AuthenticationTypeNotSupportedException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.ConversionFailedException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.NotificationTypeNotSupportedException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.SubscriptionNotFoundException;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.stereotype.Service;
+
+/**
+ * Manages package management subscription notifications to the VNFMs
+ *
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ *
+ */
+@Service
+public class NotificationManager {
+
+ private static final Logger logger = getLogger(NotificationManager.class);
+ private final ConversionService conversionService;
+ private final SubscriptionManager subscriptionManager;
+ private final NotificationServiceProviderFactory notificationServiceProviderFactory;
+
+ @Autowired
+ public NotificationManager(final SubscriptionManager subscriptionManager, final ConversionService conversionService,
+ final NotificationServiceProviderFactory notificationServiceProviderFactory) {
+ this.subscriptionManager = subscriptionManager;
+ this.conversionService = conversionService;
+ this.notificationServiceProviderFactory = notificationServiceProviderFactory;
+ }
+
+ /**
+ * Process a subscription notification. Checks for a subscription request stored in the adapter and if there is, it
+ * sends the notification to the subscribed vnfm.
+ *
+ * @param notification the notification to send to the vnfm
+ * @param subscriptionId the id of the subscription request
+ * @return true if the notification is successfully sent
+ */
+ public boolean processSubscriptionNotification(final Object notification, final String subscriptionId) {
+ final Optional<PkgmSubscriptionRequest> optionalSubscription =
+ subscriptionManager.getSubscriptionRequest(subscriptionId);
+ if (optionalSubscription.isPresent()) {
+ final PkgmSubscriptionRequest subscriptionRequest = optionalSubscription.get();
+ return notifyVnfm(subscriptionRequest, notification);
+ }
+ final String errorMessage = "No subscription found with subscriptionId " + subscriptionId
+ + ". Unable to forward notification to subscriber.";
+ logger.error(errorMessage);
+ throw new SubscriptionNotFoundException(errorMessage);
+ }
+
+ private boolean notifyVnfm(final PkgmSubscriptionRequest subscriptionRequest, final Object notification) {
+ if (!(notification instanceof PkgOnboardingNotification) && !(notification instanceof PkgChangeNotification)) {
+ final String errorMessage =
+ "An error occurred. Notification type not supported for: " + notification.getClass();
+ logger.error(errorMessage);
+ throw new NotificationTypeNotSupportedException(errorMessage);
+ }
+
+ final SubscriptionsAuthentication subscriptionsAuthentication = subscriptionRequest.getAuthentication();
+ final AuthTypeEnum authType = getAuthType(subscriptionsAuthentication.getAuthType());
+ final NotificationServiceProvider sender = notificationServiceProviderFactory.getNotificationSender(authType);
+
+ final Object vnfmNotificationObject = convertEtsiCatalogNotification(notification);
+
+ if (sender.send(vnfmNotificationObject, subscriptionsAuthentication, subscriptionRequest.getCallbackUri())) {
+ logger.info("Notification delivered successfully {}", notification);
+ return true;
+ }
+
+ logger.error("Failed to deliver notification.");
+ return false;
+ }
+
+ private SubscriptionsAuthentication.AuthTypeEnum getAuthType(final List<AuthTypeEnum> authTypes) {
+ if (authTypes.contains(SubscriptionsAuthentication.AuthTypeEnum.TLS_CERT)) {
+ return SubscriptionsAuthentication.AuthTypeEnum.TLS_CERT;
+ }
+ if (authTypes.contains(SubscriptionsAuthentication.AuthTypeEnum.OAUTH2_CLIENT_CREDENTIALS)) {
+ return SubscriptionsAuthentication.AuthTypeEnum.OAUTH2_CLIENT_CREDENTIALS;
+ }
+ if (authTypes.contains(SubscriptionsAuthentication.AuthTypeEnum.BASIC)) {
+ return SubscriptionsAuthentication.AuthTypeEnum.BASIC;
+ }
+ final String errorMessage =
+ "An error occurred. No supported authentication type provided in subscription request.";
+ logger.error(errorMessage);
+ throw new AuthenticationTypeNotSupportedException(errorMessage);
+ }
+
+ private Object convertEtsiCatalogNotification(final Object etsiCatalogNotification) {
+ logger.info("Converting notification:\n {}", etsiCatalogNotification);
+ if (conversionService.canConvert(etsiCatalogNotification.getClass(), VnfPackageOnboardingNotification.class)) {
+ return conversionService.convert(etsiCatalogNotification, VnfPackageOnboardingNotification.class);
+ } else if (conversionService.canConvert(etsiCatalogNotification.getClass(),
+ VnfPackageChangeNotification.class)) {
+ return conversionService.convert(etsiCatalogNotification, VnfPackageChangeNotification.class);
+ }
+ final String errorMessage = "An error occurred. Unable to convert provided notification object.";
+ logger.error(errorMessage + "\n" + etsiCatalogNotification);
+ throw new ConversionFailedException(errorMessage);
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProvider.java
new file mode 100644
index 0000000000..87a293456f
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProvider.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication.AuthTypeEnum;
+
+/**
+ * Interface which lays out requirements for a Notification Service Provider
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+public interface NotificationServiceProvider {
+
+ /**
+ * Method to send a notification to a uri, given the subscription authentication
+ *
+ * @param notification The notification to send
+ * @param subscriptionsAuthentication Object containing the authentication details
+ * @param callbackUri The uri to send the notification to
+ * @return true if notification is delivered successfully, otherwise false
+ */
+ boolean send(final Object notification, final SubscriptionsAuthentication subscriptionsAuthentication,
+ final String callbackUri);
+
+ /**
+ * Method to get the supported authorization type of the service provider
+ *
+ * @return the supported AuthTypeEnum
+ */
+ AuthTypeEnum getAuthType();
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProviderFactory.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProviderFactory.java
new file mode 100644
index 0000000000..256e6f4da5
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/NotificationServiceProviderFactory.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication.AuthTypeEnum;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.AuthenticationTypeNotSupportedException;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Factory to provide a notification services
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@Component
+public class NotificationServiceProviderFactory {
+
+ private static final Logger logger = getLogger(NotificationServiceProviderFactory.class);
+ private static final Map<AuthTypeEnum, NotificationServiceProvider> CACHE = new HashMap<>();
+
+ @Autowired
+ public NotificationServiceProviderFactory(final List<NotificationServiceProvider> services) {
+ for (final NotificationServiceProvider notificationServiceProvider : services) {
+ logger.debug("Adding {} of type {} to cache", notificationServiceProvider.getClass().getCanonicalName(),
+ notificationServiceProvider.getAuthType());
+ CACHE.put(notificationServiceProvider.getAuthType(), notificationServiceProvider);
+ }
+ }
+
+ /**
+ * Get a notification service for a given authorization type
+ *
+ * @param type the type of authentication required
+ * @return the notification service
+ */
+ public NotificationServiceProvider getNotificationSender(final AuthTypeEnum type) {
+ final NotificationServiceProvider service = CACHE.get(type);
+ if (service == null) {
+ throw new AuthenticationTypeNotSupportedException("Unknown type: " + type);
+ }
+ return service;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthNotificationServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthNotificationServiceProvider.java
new file mode 100644
index 0000000000..bbb41e8515
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthNotificationServiceProvider.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication.AuthTypeEnum;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.InternalServerErrorException;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.onap.so.configuration.rest.HttpHeadersProvider;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.slf4j.Logger;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ *
+ */
+@Service
+public class OAuthNotificationServiceProvider extends AbstractNotificationServiceProvider
+ implements NotificationServiceProvider {
+
+ private static final Logger logger = getLogger(OAuthNotificationServiceProvider.class);
+
+ @Override
+ public boolean send(final Object notification, final SubscriptionsAuthentication subscriptionsAuthentication,
+ final String callbackUri) {
+ logger.info("Sending notification to uri: {}", callbackUri);
+ final String token = getAccessToken(subscriptionsAuthentication);
+
+ if (token == null) {
+ logger.error("Failed to get access token");
+ return false;
+ }
+
+ final HttpHeadersProvider httpHeadersProvider = getHttpHeadersProvider(token);
+ final HttpRestServiceProvider httpRestServiceProvider = getHttpRestServiceProvider();
+ final ResponseEntity<Void> responseEntity = httpRestServiceProvider.postHttpRequest(notification, callbackUri,
+ httpHeadersProvider.getHttpHeaders(), Void.class);
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ logger.info("Notification sent successfully.");
+ return true;
+ }
+
+ logger.error("Failed to send notification.");
+ return false;
+ }
+
+ @Override
+ public AuthTypeEnum getAuthType() {
+ return AuthTypeEnum.OAUTH2_CLIENT_CREDENTIALS;
+ }
+
+ private BasicHttpHeadersProvider getHttpHeadersProvider(final String token) {
+ final String authHeader = "Bearer " + token;
+ return new BasicHttpHeadersProvider(authHeader);
+ }
+
+ private String getAccessToken(final SubscriptionsAuthentication subscriptionsAuthentication) {
+ logger.info("Requesting Access Token.");
+
+ final String tokenEndpoint = subscriptionsAuthentication.getParamsOauth2ClientCredentials().getTokenEndpoint();
+
+ final HttpHeadersProvider httpHeadersProvider = getBasicHttpHeadersProviderWithBasicAuth(
+ subscriptionsAuthentication.getParamsOauth2ClientCredentials().getClientId(),
+ subscriptionsAuthentication.getParamsOauth2ClientCredentials().getClientPassword());
+
+ final HttpRestServiceProvider httpRestServiceProvider = getHttpRestServiceProvider();
+ final ResponseEntity<OAuthTokenResponse> responseEntity = httpRestServiceProvider.postHttpRequest(null,
+ tokenEndpoint, httpHeadersProvider.getHttpHeaders(), OAuthTokenResponse.class);
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ if (responseEntity.getBody() != null) {
+ logger.info("Returning Access Token.");
+ return responseEntity.getBody().getAccessToken();
+ }
+ }
+
+ final String errorMessage = "An error occurred. Unable to retrieve OAuth Token from VNFM for notification.";
+ logger.error(errorMessage);
+ throw new InternalServerErrorException(errorMessage);
+ }
+
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthTokenResponse.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthTokenResponse.java
new file mode 100644
index 0000000000..146641cc7c
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/OAuthTokenResponse.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import java.io.Serializable;
+import javax.xml.bind.annotation.XmlElement;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+public class OAuthTokenResponse implements Serializable {
+
+ private static final long serialVersionUID = -6455742984985959926L;
+
+ @XmlElement(name = "access_token")
+ @SerializedName("access_token")
+ private String accessToken;
+
+ /**
+ * Get the Accees Token
+ *
+ * @return the Access Token
+ */
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ /**
+ * Set the Access Token
+ *
+ * @param accessToken
+ */
+ public void setAccessToken(final String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/SubscriptionManager.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/SubscriptionManager.java
new file mode 100644
index 0000000000..e45a175a2d
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/SubscriptionManager.java
@@ -0,0 +1,209 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.SubscriptionAuthentication.AuthTypeEnum.BASIC;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.net.URI;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.onap.so.adapters.vnfmadapter.common.VnfmAdapterUrlProvider;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.EtsiCatalogServiceProvider;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.BasicAuth;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.NsdmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse201;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsLinks;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesLinksSelf;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache.PackageManagementCacheServiceProvider;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.ConversionFailedException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.InternalServerErrorException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.SubscriptionNotFoundException;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.stereotype.Service;
+
+/**
+ * Manages package management subscriptions from the VNFMs
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Service
+public class SubscriptionManager {
+
+ private static final Logger logger = getLogger(SubscriptionManager.class);
+ private final PackageManagementCacheServiceProvider packageManagementCacheServiceProvider;
+ private final ConversionService conversionService;
+ private final EtsiCatalogServiceProvider etsiCatalogServiceProvider;
+ private final VnfmAdapterUrlProvider vnfmAdapterUrlProvider;
+
+ @Autowired
+ public SubscriptionManager(final PackageManagementCacheServiceProvider packageManagementCacheServiceProvider,
+ final ConversionService conversionService, final EtsiCatalogServiceProvider etsiCatalogServiceProvider,
+ final VnfmAdapterUrlProvider vnfmAdapterUrlProvider) {
+ this.packageManagementCacheServiceProvider = packageManagementCacheServiceProvider;
+ this.conversionService = conversionService;
+ this.etsiCatalogServiceProvider = etsiCatalogServiceProvider;
+ this.vnfmAdapterUrlProvider = vnfmAdapterUrlProvider;
+ }
+
+ public Optional<InlineResponse201> createSubscription(final PkgmSubscriptionRequest pkgmSubscriptionRequest)
+ throws GeneralSecurityException {
+
+ final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest =
+ buildEtsiCatalogManagerPkgmSubscriptionRequest(pkgmSubscriptionRequest);
+
+ final Optional<PkgmSubscription> optionalEtsiCatalogManagerSubscription =
+ etsiCatalogServiceProvider.postSubscription(etsiCatalogManagerSubscriptionRequest);
+
+ if (optionalEtsiCatalogManagerSubscription.isPresent()) {
+ final PkgmSubscription etsiCatalogManagerSubscription = optionalEtsiCatalogManagerSubscription.get();
+ logger.debug("postPkgmSubscriptionRequest Response SubscriptionId: {}",
+ Objects.requireNonNull(etsiCatalogManagerSubscription.getId()));
+ final String subscriptionId = etsiCatalogManagerSubscription.getId();
+
+ packageManagementCacheServiceProvider.addSubscription(subscriptionId, pkgmSubscriptionRequest);
+
+ final InlineResponse201 response = new InlineResponse201();
+ response.setId(subscriptionId);
+ response.setFilter(pkgmSubscriptionRequest.getFilter());
+ response.setCallbackUri(vnfmAdapterUrlProvider.getSubscriptionUriString(subscriptionId));
+ response.setLinks(new SubscriptionsLinks()
+ .self(new VnfPackagesLinksSelf().href(getSubscriptionUri(subscriptionId).toString())));
+
+ return Optional.of(response);
+ }
+ throw new InternalServerErrorException(
+ "Received empty response from POST to ETSI Catalog Manager Subscription Endpoint.");
+ }
+
+ public Optional<String> getSubscriptionId(final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+ return packageManagementCacheServiceProvider.getSubscriptionId(pkgmSubscriptionRequest);
+ }
+
+ public Optional<InlineResponse201> getSubscription(final String subscriptionId) {
+
+ logger.debug("Checking if subscrition with id: {} exists in ETSI Catalog Manager", subscriptionId);
+ final Optional<NsdmSubscription> etsiCatalogSubscriptionOption =
+ etsiCatalogServiceProvider.getSubscription(subscriptionId);
+
+ if (!etsiCatalogSubscriptionOption.isPresent()) {
+ logger.debug("Unable to find subscription in ETSI Catalog Manager using id: {}", subscriptionId);
+ if (packageManagementCacheServiceProvider.getSubscription(subscriptionId).isPresent()) {
+ logger.debug("will remove subcription with id: {} from local cache", subscriptionId);
+ packageManagementCacheServiceProvider.deleteSubscription(subscriptionId);
+ }
+ }
+
+ final Optional<PkgmSubscriptionRequest> optional =
+ packageManagementCacheServiceProvider.getSubscription(subscriptionId);
+ if (optional.isPresent()) {
+ final PkgmSubscriptionRequest subscription = optional.get();
+ return Optional.of(getInlineResponse2002(subscriptionId, subscription));
+ }
+ return Optional.empty();
+ }
+
+ public List<InlineResponse201> getSubscriptions() {
+ final Map<String, PkgmSubscriptionRequest> subscriptions =
+ packageManagementCacheServiceProvider.getSubscriptions();
+ final List<InlineResponse201> response = new ArrayList<>();
+ subscriptions.forEach((key, value) -> {
+ final Optional<InlineResponse201> optional = getSubscription(key);
+ if (optional.isPresent()) {
+ response.add(optional.get());
+ }
+ });
+ return response;
+ }
+
+ public boolean deleteSubscription(final String subscriptionId) {
+ if (packageManagementCacheServiceProvider.getSubscription(subscriptionId).isPresent()) {
+ try {
+ if (etsiCatalogServiceProvider.deleteSubscription(subscriptionId)) {
+ return packageManagementCacheServiceProvider.deleteSubscription(subscriptionId);
+ }
+ } catch (final SubscriptionNotFoundException subscriptionNotFoundException) {
+ logger.error(
+ "Unable to find subscription in ETSI Catalog Manager using id: {} will delete it from local cache",
+ subscriptionId);
+ return packageManagementCacheServiceProvider.deleteSubscription(subscriptionId);
+ }
+ }
+ return false;
+ }
+
+ public URI getSubscriptionUri(final String subscriptionId) {
+ return vnfmAdapterUrlProvider.getSubscriptionUri(subscriptionId);
+ }
+
+ public Optional<PkgmSubscriptionRequest> getSubscriptionRequest(final String subscriptionId) {
+ return packageManagementCacheServiceProvider.getSubscription(subscriptionId);
+ }
+
+ private InlineResponse201 getInlineResponse2002(final String id, final PkgmSubscriptionRequest subscription) {
+ return new InlineResponse201().id(id).filter(subscription.getFilter())
+ .callbackUri(subscription.getCallbackUri());
+ }
+
+ private org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest buildEtsiCatalogManagerPkgmSubscriptionRequest(
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest) throws GeneralSecurityException {
+
+ final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest;
+ try {
+ etsiCatalogManagerSubscriptionRequest = conversionService.convert(pkgmSubscriptionRequest,
+ org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest.class);
+ } catch (final org.springframework.core.convert.ConversionException conversionException) {
+ logger.error(conversionException.getMessage());
+ throw new ConversionFailedException(
+ "Could not convert Sol003 PkgmSubscriptionRequest to ETSI-Catalog Manager PkgmSubscriptionRequest");
+ } catch (final Exception exception) {
+ logger.error(exception.getMessage());
+ throw new InternalServerErrorException(
+ "Could not convert Sol003 PkgmSubscriptionRequest to ETSI-Catalog Manager PkgmSubscriptionRequest");
+ }
+
+ if (etsiCatalogManagerSubscriptionRequest != null) {
+ etsiCatalogManagerSubscriptionRequest
+ .setCallbackUri(vnfmAdapterUrlProvider.getEtsiSubscriptionNotificationBaseUrl());
+
+ final ImmutablePair<String, String> immutablePair = vnfmAdapterUrlProvider.getDecryptAuth();
+ if (!immutablePair.equals(ImmutablePair.nullPair())) {
+ etsiCatalogManagerSubscriptionRequest.setAuthentication(
+ new org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.SubscriptionAuthentication()
+ .addAuthTypeItem(BASIC).paramsBasic(new BasicAuth().userName(immutablePair.getLeft())
+ .password(immutablePair.getRight())));
+ }
+ return etsiCatalogManagerSubscriptionRequest;
+ }
+ throw new ConversionFailedException(
+ "Failed to convert Sol003 PkgmSubscriptionRequest to ETSI-Catalog Manager PkgmSubscriptionRequest");
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/TlsNotificationServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/TlsNotificationServiceProvider.java
new file mode 100644
index 0000000000..5e922293d5
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/TlsNotificationServiceProvider.java
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication.AuthTypeEnum;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.AuthenticationTypeNotSupportedException;
+import org.slf4j.Logger;
+import org.springframework.stereotype.Service;
+
+/*
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@Service
+public class TlsNotificationServiceProvider extends AbstractNotificationServiceProvider
+ implements NotificationServiceProvider {
+
+ private static final Logger logger = getLogger(TlsNotificationServiceProvider.class);
+
+ @Override
+ public boolean send(final Object notification, final SubscriptionsAuthentication subscriptionsAuthentication,
+ final String callbackUri) {
+ final String errorMessage = "An error occurred. Authentication type "
+ + subscriptionsAuthentication.getAuthType().toString() + " not currently supported.";
+ logger.error(errorMessage);
+ throw new AuthenticationTypeNotSupportedException(errorMessage);
+ }
+
+
+ @Override
+ public AuthTypeEnum getAuthType() {
+ return AuthTypeEnum.TLS_CERT;
+ }
+
+
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/AbstractCacheServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/AbstractCacheServiceProvider.java
new file mode 100644
index 0000000000..e1e9b2307e
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/AbstractCacheServiceProvider.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+
+/**
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+public abstract class AbstractCacheServiceProvider {
+
+ private final CacheManager cacheManager;
+ private final String cacheName;
+
+ public AbstractCacheServiceProvider(final String cacheName, final CacheManager cacheManager) {
+ this.cacheName = cacheName;
+ this.cacheManager = cacheManager;
+ }
+
+ public Cache getCache() {
+ final Cache cache = cacheManager.getCache(cacheName);
+ if (cache == null) {
+ throw new CacheNotFoundException("Unable to find " + cacheName + " cache");
+ }
+ return cache;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheManagerConfiguration.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheManagerConfiguration.java
new file mode 100644
index 0000000000..a2e1d76ad6
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheManagerConfiguration.java
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import java.util.Arrays;
+import org.onap.so.adapters.vnfmadapter.PackageManagementConstants;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.concurrent.ConcurrentMapCache;
+import org.springframework.cache.support.SimpleCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Configuration
+public class CacheManagerConfiguration {
+
+ @Bean
+ public CacheManager cacheManager() {
+ final SimpleCacheManager manager = new SimpleCacheManager();
+ manager.setCaches(Arrays.asList(getCache(PackageManagementConstants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE)));
+
+ return manager;
+ }
+
+ private Cache getCache(final String name) {
+ return new ConcurrentMapCache(name);
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheNotFoundException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheNotFoundException.java
new file mode 100644
index 0000000000..edd5982ab1
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheNotFoundException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+/**
+ * Exception for failure to find the cache.
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ *
+ */
+public class CacheNotFoundException extends RuntimeException {
+
+ private static final long serialVersionUID = -372361485260755367L;
+
+ public CacheNotFoundException(final String message) {
+ super(message);
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProvider.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProvider.java
new file mode 100644
index 0000000000..713d14b077
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProvider.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import java.util.Map;
+import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+
+/**
+ * Interface which provides methods for communicating with the cache
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ *
+ */
+public interface PackageManagementCacheServiceProvider {
+
+ /**
+ * Checks cache if subscription request Id is already present. If not, it adds the subscription to the cache.
+ *
+ * @param subscriptionId
+ * @param pkgmSubscriptionRequest
+ */
+ void addSubscription(final String subscriptionId, final PkgmSubscriptionRequest pkgmSubscriptionRequest);
+
+ /**
+ * Gets individual subscription from cache
+ *
+ * @param subscriptionId
+ * @return <AbstractMap.SimpleImmutableEntry<String, PkgmSubscriptionRequest>>
+ */
+ Optional<PkgmSubscriptionRequest> getSubscription(final String subscriptionId);
+
+ /**
+ * Gets Map of subscriptions from cache
+ *
+ * @return Map<String, PkgmSubscriptionRequest>>
+ */
+ Map<String, PkgmSubscriptionRequest> getSubscriptions();
+
+ /**
+ * Delete subscription from cache
+ *
+ * @param subscriptionId
+ * @return Boolean
+ */
+ boolean deleteSubscription(final String subscriptionId);
+
+ /**
+ * Checks if subscription exists in cache and return its subscriptionId
+ *
+ * @param pkgmSubscriptionRequest
+ * @return Subscription Id
+ */
+ Optional<String> getSubscriptionId(final PkgmSubscriptionRequest pkgmSubscriptionRequest);
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProviderImpl.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProviderImpl.java
new file mode 100644
index 0000000000..82438228ec
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProviderImpl.java
@@ -0,0 +1,119 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import org.onap.so.adapters.vnfmadapter.PackageManagementConstants;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.stereotype.Service;
+
+/**
+ * Implementation which provides methods for communicating with the cache
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Service
+public class PackageManagementCacheServiceProviderImpl extends AbstractCacheServiceProvider
+ implements PackageManagementCacheServiceProvider {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PackageManagementCacheServiceProviderImpl.class);
+
+ @Autowired
+ public PackageManagementCacheServiceProviderImpl(final CacheManager cacheManager) {
+ super(PackageManagementConstants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE, cacheManager);
+ }
+
+ @Override
+ public void addSubscription(final String subscriptionId, final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+ LOGGER.debug("Adding {} to cache with subscription id: {}", pkgmSubscriptionRequest, subscriptionId);
+ getCache().put(subscriptionId, pkgmSubscriptionRequest);
+ }
+
+ @Override
+ public Optional<PkgmSubscriptionRequest> getSubscription(final String subscriptionId) {
+ LOGGER.debug("Getting subscription from cache using Id: {}", subscriptionId);
+ final Cache cache = getCache();
+ final PkgmSubscriptionRequest cacheValue = cache.get(subscriptionId, PkgmSubscriptionRequest.class);
+ if (cacheValue != null) {
+ return Optional.of(cacheValue);
+ }
+ LOGGER.error("Unable to find Subscription in cache using Id: {}", subscriptionId);
+ return Optional.empty();
+ }
+
+ @Override
+ public Map<String, PkgmSubscriptionRequest> getSubscriptions() {
+ LOGGER.info("Getting all subscriptions from cache");
+ final Cache cache = getCache();
+
+ final Object nativeCache = cache.getNativeCache();
+ if (nativeCache instanceof ConcurrentHashMap) {
+ @SuppressWarnings("unchecked")
+ final ConcurrentHashMap<Object, Object> concurrentHashMap = (ConcurrentHashMap<Object, Object>) nativeCache;
+ final Map<String, PkgmSubscriptionRequest> result = new HashMap<>();
+ concurrentHashMap.keySet().forEach(key -> {
+ final Optional<PkgmSubscriptionRequest> optional = getSubscription(key.toString());
+ optional.ifPresent(pkgmSubscriptionRequest -> result.put(key.toString(), pkgmSubscriptionRequest));
+ });
+ return result;
+ }
+ LOGGER.error("Unable to find Subscriptions in cache");
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public boolean deleteSubscription(final String subscriptionId) {
+ final Cache cache = getCache();
+ final Optional<PkgmSubscriptionRequest> optional = getSubscription(subscriptionId);
+ if (optional.isPresent()) {
+ cache.evict(subscriptionId);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Optional<String> getSubscriptionId(final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+ final Cache cache = getCache();
+ final Object nativeCache = cache.getNativeCache();
+ if (nativeCache instanceof ConcurrentHashMap) {
+ @SuppressWarnings("unchecked")
+ final ConcurrentHashMap<Object, Object> concurrentHashMap = (ConcurrentHashMap<Object, Object>) nativeCache;
+ final Optional<Entry<Object, Object>> optional = concurrentHashMap.entrySet().stream()
+ .filter(entry -> entry.getValue().equals(pkgmSubscriptionRequest)).findAny();
+ if (optional.isPresent()) {
+ return Optional.of(optional.get().getKey().toString());
+ }
+ }
+ return Optional.empty();
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationController.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationController.java
new file mode 100644
index 0000000000..fe9b085095
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationController.java
@@ -0,0 +1,131 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest;
+
+import static org.onap.so.adapters.vnfmadapter.common.CommonConstants.ETSI_SUBSCRIPTION_NOTIFICATION_CONTROLLER_BASE_URL;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.util.AbstractMap;
+import java.util.Map.Entry;
+import javax.ws.rs.core.MediaType;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgChangeNotification;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgOnboardingNotification;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.NotificationManager;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.InternalServerErrorException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.NotificationTypeNotSupportedException;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * This controller handles the ETSI Subscription Notification Endpoints.
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@Controller
+@RequestMapping(value = ETSI_SUBSCRIPTION_NOTIFICATION_CONTROLLER_BASE_URL)
+public class EtsiSubscriptionNotificationController {
+
+ private static final Logger logger = getLogger(EtsiSubscriptionNotificationController.class);
+ private final NotificationManager notificationManager;
+ private final Gson gson;
+
+ @Autowired
+ public EtsiSubscriptionNotificationController(final NotificationManager notificationManager) {
+ this.notificationManager = notificationManager;
+ this.gson = new GsonBuilder().create();
+ }
+
+ @GetMapping(value = "/notification")
+ public ResponseEntity<Void> testSubscriptionNotificationEndPoint() {
+ logger.debug("Testing Notification Endpoint");
+ return ResponseEntity.noContent().build();
+ }
+
+ /**
+ * POST notification on to subscriber.
+ *
+ * @param notification The notification to send.
+ * @return Response Code: 204 No Content if Successful, ProblemDetails Object if not.
+ */
+ @PostMapping(value = "/notification", consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
+ public ResponseEntity<?> postSubscriptionNotification(@RequestBody final String notification) {
+ logger.info("Posting subscription notification \n{}", notification);
+
+ final Entry<String, Object> notificationObject = getNotificationObject(notification);
+ if (notificationManager.processSubscriptionNotification(notificationObject.getValue(),
+ notificationObject.getKey())) {
+ logger.info("Notification Delivered Successfully");
+ return ResponseEntity.noContent().build();
+ }
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed.";
+ logger.error(errorMessage);
+ throw new InternalServerErrorException(errorMessage);
+ }
+
+ private Entry<String, Object> getNotificationObject(final String notification) {
+ final String notificationType = getNotificationType(notification);
+ if (PkgOnboardingNotification.NotificationTypeEnum.VNFPACKAGEONBOARDINGNOTIFICATION.getValue()
+ .equals(notificationType)) {
+ final PkgOnboardingNotification pkgOnboardingNotification =
+ gson.fromJson(notification, PkgOnboardingNotification.class);
+ logger.info("Onboarding notification received:\n{}", pkgOnboardingNotification);
+ return new AbstractMap.SimpleEntry<>(pkgOnboardingNotification.getSubscriptionId(),
+ pkgOnboardingNotification);
+ }
+ if (PkgChangeNotification.NotificationTypeEnum.VNFPACKAGECHANGENOTIFICATION.getValue()
+ .equals(notificationType)) {
+ final PkgChangeNotification pkgChangeNotification =
+ gson.fromJson(notification, PkgChangeNotification.class);
+ logger.info("Change notification received:\n{}", pkgChangeNotification);
+ return new AbstractMap.SimpleEntry<>(pkgChangeNotification.getSubscriptionId(), pkgChangeNotification);
+
+ }
+
+ final String errorMessage = "An error occurred. Notification type not supported for: " + notificationType;
+ logger.error(errorMessage);
+ throw new NotificationTypeNotSupportedException(errorMessage);
+
+ }
+
+ private String getNotificationType(final String notification) {
+ try {
+ final JsonParser parser = new JsonParser();
+ final JsonObject element = (JsonObject) parser.parse(notification);
+ return element.get("notificationType").getAsString();
+ } catch (final Exception e) {
+ logger.error("An error occurred processing notificiation: {}", e.getMessage());
+ }
+ throw new NotificationTypeNotSupportedException(
+ "Unable to parse notification type in object \n" + notification);
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java
new file mode 100644
index 0000000000..48d6a33082
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java
@@ -0,0 +1,176 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest;
+
+import static org.onap.so.adapters.vnfmadapter.PackageManagementConstants.APPLICATION_ZIP;
+import static org.onap.so.adapters.vnfmadapter.common.CommonConstants.PACKAGE_MANAGEMENT_BASE_URL;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.util.Optional;
+import javax.ws.rs.core.MediaType;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.EtsiCatalogServiceProvider;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse2001;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Controller for handling the VNF Package Management. For further information please read:
+ * https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/003/02.05.01_60/gs_nfv-sol003v020501p.pdf Use the section number
+ * above each endpoint to find the corresponding section in the above document.
+ *
+ * @author gareth.roper@est.tech
+ */
+@Controller
+@RequestMapping(value = PACKAGE_MANAGEMENT_BASE_URL, consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+public class Sol003PackageManagementController {
+
+ private final EtsiCatalogServiceProvider etsiCatalogServiceProvider;
+ private static final String LOG_REQUEST_RECEIVED = "VNF PackageManagement Controller: {} {} {} {}";
+ private static final Logger logger = getLogger(Sol003PackageManagementController.class);
+
+ @Autowired
+ Sol003PackageManagementController(final EtsiCatalogServiceProvider etsiCatalogServiceProvider) {
+ this.etsiCatalogServiceProvider = etsiCatalogServiceProvider;
+ }
+
+ /**
+ * GET VNF packages information. Will return zero or more VNF package representations that match the attribute
+ * filter. These representations will be in a list. Section Number: 10.4.2
+ *
+ * @return An Array of all VNF packages. Object: InlineResponse2001[] Response Code: 200 OK
+ */
+ @GetMapping(value = "/vnf_packages", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public ResponseEntity<?> getVnfPackages() {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackages.");
+ final Optional<InlineResponse2001[]> response = etsiCatalogServiceProvider.getVnfPackages();
+ if (response.isPresent()) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackages Response: ", HttpStatus.OK);
+ return ResponseEntity.ok().body(response.get());
+ }
+ final String errorMessage = "An error occurred, a null response was received by the\n"
+ + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"vnf_packages\" \n"
+ + "endpoint.";
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ /**
+ * GET VNF package information. Will return a specific VNF package representation that match the attribute filter.
+ * Section Number: 10.4.3
+ *
+ * @param vnfPkgId The ID of the VNF Package that you want to query.
+ * @return A VNF package based on vnfPkgId. Object: VnfPkgInfo Response Code: 200 OK
+ */
+ @GetMapping(value = "/vnf_packages/{vnfPkgId}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public ResponseEntity<?> getVnfPackage(@PathVariable("vnfPkgId") final String vnfPkgId) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackage: ", vnfPkgId);
+ final Optional<InlineResponse2001> response = etsiCatalogServiceProvider.getVnfPackage(vnfPkgId);
+ if (response.isPresent()) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackage Response: ", HttpStatus.OK);
+ return ResponseEntity.ok().body(response.get());
+ }
+ final String errorMessage = "An error occurred, a null response was received by the\n"
+ + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"vnf_packages\" by vnfPkgId: \""
+ + vnfPkgId + "\" \n" + "endpoint.";
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ /**
+ * GET VNFD, from VNF package. Will return a copy of the file representing the VNFD or a ZIP file that contains the
+ * file/multiple files representing the VNFD specified. Section Number: 10.4.4
+ *
+ * @param vnfPkgId The ID of the VNF Package that you want to retrieve the VNFD from.
+ * @return The VNFD of a VNF Package as a single file or within a ZIP file. Object: byte[] Response Code: 200 OK
+ */
+ @GetMapping(value = "/vnf_packages/{vnfPkgId}/vnfd",
+ produces = {MediaType.TEXT_PLAIN, APPLICATION_ZIP, MediaType.APPLICATION_JSON})
+ public ResponseEntity<?> getVnfPackageVnfd(@PathVariable("vnfPkgId") final String vnfPkgId) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackageVnfd Endpoint Invoked with VNF Package ID: ", vnfPkgId);
+ final Optional<byte[]> response = etsiCatalogServiceProvider.getVnfPackageVnfd(vnfPkgId);
+ if (response.isPresent()) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackageVnfd Response: ", HttpStatus.OK);
+ return new ResponseEntity<>(response.get(), HttpStatus.OK);
+ }
+ final String errorMessage = "An error occurred, a null response was received by the\n"
+ + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"vnfd\" \n"
+ + "endpoint.";
+
+ logger.error(errorMessage);
+ return new ResponseEntity<>(new ProblemDetails().detail(errorMessage), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * GET Package Content, from VNF Package. Will return a copy of the VNF package file that you specified. Section
+ * Number: 10.4.5
+ *
+ * @param vnfPkgId The ID of the VNF Package that you want to retrieve the "package_content" from.
+ * @return The Package Content of a VNF Package. Object: byte[] Response Code: 200 OK
+ */
+ @GetMapping(value = "/vnf_packages/{vnfPkgId}/package_content",
+ produces = {MediaType.APPLICATION_JSON, APPLICATION_ZIP, MediaType.APPLICATION_OCTET_STREAM})
+ public ResponseEntity<?> getVnfPackageContent(@PathVariable("vnfPkgId") final String vnfPkgId) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackageContent Endpoint Invoked with VNF Package ID: ", vnfPkgId);
+ final Optional<byte[]> response = etsiCatalogServiceProvider.getVnfPackageContent(vnfPkgId);
+ if (response.isPresent()) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackageContent Response: ", HttpStatus.OK);
+ return ResponseEntity.ok().body(response.get());
+ }
+ final String errorMessage = "An error occurred, a null response was received by the\n"
+ + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"package_content\" \n"
+ + "endpoint.";
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ /**
+ * GET Artifact, from VNF Package Will return a the content of the artifact that you specified. Section Number:
+ * 10.4.6
+ *
+ * @param vnfPkgId The ID of the VNF Package that you want to retrieve an artifact from.
+ * @param artifactPath The path of the artifact that you want to retrieve.
+ * @return An Artifact from a VNF Package. Object: byte[] Response Code: 200 OK
+ */
+ @GetMapping(value = "/vnf_packages/{vnfPkgId}/artifacts/{artifactPath}",
+ produces = {MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_JSON})
+ public ResponseEntity<?> getVnfPackageArtifact(@PathVariable("vnfPkgId") final String vnfPkgId,
+ @PathVariable("artifactPath") final String artifactPath) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackageArtifact: vnfPkgId= ", vnfPkgId, " artifactPath=",
+ artifactPath);
+ final Optional<byte[]> response = etsiCatalogServiceProvider.getVnfPackageArtifact(vnfPkgId, artifactPath);
+ if (response.isPresent()) {
+ logger.info(LOG_REQUEST_RECEIVED, "getVnfPackageArtifact Response: ", HttpStatus.OK);
+ return ResponseEntity.ok().body(response.get());
+ }
+ final String errorMessage = "An error occurred, a null response was received by the\n"
+ + " Sol003PackageManagementController from the EtsiCatalogManager using the\n GET \"vnf_packages\" by vnfPkgId: \""
+ + vnfPkgId + "\" for artifactPath: \"" + artifactPath + "\"\n" + "endpoint.";
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionController.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionController.java
new file mode 100644
index 0000000000..75c72b6df3
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionController.java
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest;
+
+import static org.onap.so.adapters.vnfmadapter.common.CommonConstants.PACKAGE_MANAGEMENT_BASE_URL;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.net.URI;
+import java.security.GeneralSecurityException;
+import java.util.List;
+import java.util.Optional;
+import javax.ws.rs.core.MediaType;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse201;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.SubscriptionManager;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Controller for handling the Subscription Management. The client can use this resource to subscribe to notifications
+ * related to the VNF package management, and to query its subscriptions. For further information please read:
+ * https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/003/02.05.01_60/gs_nfv-sol003v020501p.pdf Use the section number
+ * above each endpoint to find the corresponding section in the above document.
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Controller
+@RequestMapping(value = PACKAGE_MANAGEMENT_BASE_URL, produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+ consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+public class Sol003PackageManagementSubscriptionController {
+
+ private static final String LOG_REQUEST_RECEIVED = "Subscription Management Controller: {} {}";
+ private static final Logger logger = getLogger(Sol003PackageManagementSubscriptionController.class);
+ private final SubscriptionManager subscriptionManager;
+
+ @Autowired
+ public Sol003PackageManagementSubscriptionController(final SubscriptionManager subscriptionManager) {
+ this.subscriptionManager = subscriptionManager;
+ }
+
+ /**
+ * POST Subscribe request. Will send request and respond with the subscription that you subscribed to, if
+ * successful. Section Number: 10.4.7
+ *
+ * @param pkgmSubscriptionRequest This includes the details of the subscription to be created.
+ * @return The subscription requested, if successful. Object: InlineRespone2002 Response Code: 201 Created Response
+ * Code: 303 Duplicate Subscription
+ * @throws GeneralSecurityException
+ */
+ @PostMapping(value = "/subscriptions")
+ public ResponseEntity<?> postSubscriptionRequest(@RequestBody final PkgmSubscriptionRequest pkgmSubscriptionRequest)
+ throws GeneralSecurityException {
+ logger.info(LOG_REQUEST_RECEIVED, " postSubscriptionRequest Endpoint Called", pkgmSubscriptionRequest);
+
+ // Check if subscription exists already.
+ final Optional<String> exists = subscriptionManager.getSubscriptionId(pkgmSubscriptionRequest);
+
+ if (exists.isPresent()) {
+ final URI subscriptionUri = subscriptionManager.getSubscriptionUri(exists.get());
+ final HttpHeaders headers = createLocationHeader(subscriptionUri);
+ logger.info("PkgmSubscriptionRequest already exists with uri {} ", subscriptionUri);
+ return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER);
+ }
+
+ logger.debug("No duplicate Subscription exists, continuing with POST.");
+ final Optional<InlineResponse201> optionalInlineResponse =
+ subscriptionManager.createSubscription(pkgmSubscriptionRequest);
+
+ if (optionalInlineResponse.isPresent()) {
+ InlineResponse201 inlineResponse = optionalInlineResponse.get();
+ final URI subscriptionUri = subscriptionManager.getSubscriptionUri(inlineResponse.getId());
+ final HttpHeaders headers = createLocationHeader(subscriptionUri);
+ logger.debug("Sending response with uri {} ", subscriptionUri);
+ return new ResponseEntity<>(inlineResponse, headers, HttpStatus.CREATED);
+ }
+ final String errorMessage = "A null response was received during the postSubscriptionRequest call.";
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ /**
+ * GET all subscriptions. Will return a list of all subscriptions currently active. Section Number: 10.4.7
+ *
+ * @return All of the current active subscriptions. Object: List<InlineResponse2002> Response Code: 200 OK
+ */
+ @GetMapping(value = "/subscriptions")
+ public ResponseEntity<List<InlineResponse201>> getSubscriptions() {
+ logger.info(LOG_REQUEST_RECEIVED, " getSubscriptions.");
+ List<InlineResponse201> subscriptionsList = subscriptionManager.getSubscriptions();
+ return new ResponseEntity<>(subscriptionsList, HttpStatus.OK);
+ }
+
+ /**
+ * GET a specific subscription, by subscriptionId. Section Number: 10.4.8
+ *
+ * @param subscriptionId The ID of the subscription that you wish to retrieve.
+ * @return A subscription based on subscriptionId. Object: InlineResponse2002 Response Code: 200 OK
+ */
+ @GetMapping(value = "/subscriptions/{subscriptionId}")
+ public ResponseEntity<?> getSubscription(@PathVariable("subscriptionId") final String subscriptionId) {
+ logger.info(LOG_REQUEST_RECEIVED, " Getting Subscription: ", subscriptionId);
+ final Optional<InlineResponse201> optional = subscriptionManager.getSubscription(subscriptionId);
+ if (optional.isPresent()) {
+ logger.debug("Return subscription with id {} and body {}", subscriptionId, optional);
+ return new ResponseEntity<>(optional.get(), HttpStatus.OK);
+ }
+ final String errorMessage =
+ "The requested subscription: " + subscriptionId + " was not found on call getSubscription";
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ /**
+ * DELETE a specific subscription, by subscriptionId. Section Number: 10.4.8.3.5
+ *
+ * @param subscriptionId The ID of the subscription that you wish to delete.
+ * @return Empty response if successful. Object: Void Response Code: 204 No Content
+ */
+ @DeleteMapping(value = "/subscriptions/{subscriptionId}")
+ public ResponseEntity<?> deleteSubscription(@PathVariable("subscriptionId") final String subscriptionId) {
+ if (subscriptionManager.deleteSubscription(subscriptionId)) {
+ logger.debug("Successfully deleted subscription with id {}", subscriptionId);
+ return ResponseEntity.noContent().build();
+ }
+ final String errorMessage =
+ "The requested subscription: " + subscriptionId + " was not found on call deleteSubscription";
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ /**
+ * Method to set the Location in the header with the URI parameter
+ *
+ * @param subscriptionUri
+ * @return header with callbackUri in Location
+ */
+ private HttpHeaders createLocationHeader(final URI subscriptionUri) {
+ final HttpHeaders headers = new HttpHeaders();
+ headers.setLocation(subscriptionUri);
+ return headers;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/AuthenticationTypeNotSupportedException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/AuthenticationTypeNotSupportedException.java
new file mode 100644
index 0000000000..303420f1e8
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/AuthenticationTypeNotSupportedException.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an unsupported authentication type
+ *
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class AuthenticationTypeNotSupportedException extends RuntimeException {
+
+ private static final long serialVersionUID = 2939423208362066902L;
+
+ public AuthenticationTypeNotSupportedException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/ConversionFailedException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/ConversionFailedException.java
new file mode 100644
index 0000000000..e19a53d1dc
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/ConversionFailedException.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for Conversion Failures
+ *
+ * @author Gareth Roper (gareth.roper@est.tech)
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class ConversionFailedException extends RuntimeException {
+
+ private static final long serialVersionUID = 45898561453196895L;
+
+ public ConversionFailedException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerBadRequestException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerBadRequestException.java
new file mode 100644
index 0000000000..dbd098f7cd
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerBadRequestException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Bad Request Exception.
+ *
+ * @author Gareth Roper (gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.BAD_REQUEST)
+public class EtsiCatalogManagerBadRequestException extends RuntimeException {
+
+ private static final long serialVersionUID = 6571317418914258768L;
+
+ public EtsiCatalogManagerBadRequestException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerRequestFailureException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerRequestFailureException.java
new file mode 100644
index 0000000000..dbdc354f4e
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerRequestFailureException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Request Failure
+ *
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class EtsiCatalogManagerRequestFailureException extends RuntimeException {
+
+ private static final long serialVersionUID = 66862444537194516L;
+
+ public EtsiCatalogManagerRequestFailureException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiSubscriptionNotificationControllerExceptionHandler.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiSubscriptionNotificationControllerExceptionHandler.java
new file mode 100644
index 0000000000..e8e1ce35b9
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiSubscriptionNotificationControllerExceptionHandler.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.rest.EtsiSubscriptionNotificationController;
+import org.onap.so.rest.exceptions.HttpResouceNotFoundException;
+import org.onap.so.rest.exceptions.InvalidRestRequestException;
+import org.onap.so.rest.exceptions.RestProcessingException;
+import org.slf4j.Logger;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * Exception Handler for the Etsi Subscription Notification Controller {@link EtsiSubscriptionNotificationController
+ * EtsiSubscriptionNotificationController}
+ *
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@ControllerAdvice(assignableTypes = EtsiSubscriptionNotificationController.class)
+public class EtsiSubscriptionNotificationControllerExceptionHandler {
+
+ private static final Logger logger = getLogger(EtsiSubscriptionNotificationControllerExceptionHandler.class);
+
+ @ExceptionHandler(InvalidRestRequestException.class)
+ public ResponseEntity<ProblemDetails> handleInvalidRestRequestException(
+ final InvalidRestRequestException invalidRestRequestException) {
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.BAD_REQUEST + ".\n" + invalidRestRequestException.getMessage();
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ @ExceptionHandler(HttpResouceNotFoundException.class)
+ public ResponseEntity<ProblemDetails> handleHttpResourceNotFoundException(
+ final HttpResouceNotFoundException httpResourceNotFoundException) {
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.NOT_FOUND + ".\n" + httpResourceNotFoundException.getMessage();
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ @ExceptionHandler(RestProcessingException.class)
+ public ResponseEntity<ProblemDetails> handleRestProcessingException(
+ final RestProcessingException restProcessingException) {
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + restProcessingException.getStatusCode() + ".\n" + restProcessingException.getMessage();
+ logger.error(errorMessage);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+ }
+
+ @ExceptionHandler(InternalServerErrorException.class)
+ public ResponseEntity<ProblemDetails> handleInternalServerErrorException(
+ final InternalServerErrorException internalServerErrorException) {
+ logger.error(internalServerErrorException.getMessage());
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(new ProblemDetails().detail(internalServerErrorException.getMessage()));
+ }
+
+ @ExceptionHandler(AuthenticationTypeNotSupportedException.class)
+ public ResponseEntity<ProblemDetails> handleAuthenticationTypeNotSupportedException(
+ final AuthenticationTypeNotSupportedException authenticationTypeNotSupportedException) {
+ logger.error(authenticationTypeNotSupportedException.getMessage());
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(new ProblemDetails().detail(authenticationTypeNotSupportedException.getMessage()));
+ }
+
+ @ExceptionHandler(ConversionFailedException.class)
+ public ResponseEntity<ProblemDetails> handleConversionFailedException(
+ final ConversionFailedException conversionFailedException) {
+ logger.error(conversionFailedException.getMessage());
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(new ProblemDetails().detail(conversionFailedException.getMessage()));
+ }
+
+ @ExceptionHandler(NotificationTypeNotSupportedException.class)
+ public ResponseEntity<ProblemDetails> handleNotificationTypeNotSupportedException(
+ final NotificationTypeNotSupportedException notificationTypeNotSupportedException) {
+ logger.error(notificationTypeNotSupportedException.getMessage());
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(new ProblemDetails().detail(notificationTypeNotSupportedException.getMessage()));
+ }
+
+ @ExceptionHandler(SubscriptionNotFoundException.class)
+ public ResponseEntity<ProblemDetails> handleSubscriptionNotFoundException(
+ final SubscriptionNotFoundException subscriptionNotFoundException) {
+ logger.error(subscriptionNotFoundException.getMessage());
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(new ProblemDetails().detail(subscriptionNotFoundException.getMessage()));
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/InternalServerErrorException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/InternalServerErrorException.java
new file mode 100644
index 0000000000..9b547d3c5a
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/InternalServerErrorException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Request Failure
+ *
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class InternalServerErrorException extends RuntimeException {
+
+ private static final long serialVersionUID = 66864561537194516L;
+
+ public InternalServerErrorException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/NotificationTypeNotSupportedException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/NotificationTypeNotSupportedException.java
new file mode 100644
index 0000000000..dcc98864aa
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/NotificationTypeNotSupportedException.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an unsupported notification type
+ *
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class NotificationTypeNotSupportedException extends RuntimeException {
+
+ private static final long serialVersionUID = 2939423208362066902L;
+
+ public NotificationTypeNotSupportedException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java
new file mode 100644
index 0000000000..8091f35da6
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.rest.Sol003PackageManagementController;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * Exception Handler for the Package Management Controller {@link Sol003PackageManagementController Sol003Controller}
+ *
+ * @author gareth.roper@est.tech
+ */
+@ControllerAdvice(assignableTypes = Sol003PackageManagementController.class)
+
+public class Sol003PackageManagementControllerExceptionHandler {
+
+ @ExceptionHandler(EtsiCatalogManagerRequestFailureException.class)
+ public ResponseEntity<ProblemDetails> handleEtsiCatalogManagerRequestFailureException(
+ final EtsiCatalogManagerRequestFailureException etsiCatalogManagerRequestFailureException) {
+ final ProblemDetails problemDetails = new ProblemDetails();
+ problemDetails.setDetail(etsiCatalogManagerRequestFailureException.getMessage());
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(problemDetails);
+ }
+
+ @ExceptionHandler(EtsiCatalogManagerBadRequestException.class)
+ public ResponseEntity<ProblemDetails> handleEtsiCatalogManagerBadRequestFailureException(
+ final EtsiCatalogManagerBadRequestException etsiCatalogManagerBadRequestException) {
+ final ProblemDetails problemDetails = new ProblemDetails();
+ problemDetails.setDetail(etsiCatalogManagerBadRequestException.getMessage());
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetails);
+ }
+
+ @ExceptionHandler(SubscriptionNotFoundException.class)
+ public ResponseEntity<ProblemDetails> handleSubscriptionNotFoundException(
+ final SubscriptionNotFoundException subscriptionNotFoundException) {
+ final ProblemDetails problemDetails = new ProblemDetails();
+ problemDetails.setDetail(subscriptionNotFoundException.getMessage());
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetails);
+ }
+
+ @ExceptionHandler(ConversionFailedException.class)
+ public ResponseEntity<ProblemDetails> handleConversionFailedException(
+ final ConversionFailedException conversionFailedException) {
+ final ProblemDetails problemDetails = new ProblemDetails();
+ problemDetails.setDetail(conversionFailedException.getMessage());
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(problemDetails);
+ }
+
+ @ExceptionHandler(VnfPkgConflictException.class)
+ public ResponseEntity<ProblemDetails> handleVnfPkgConflictException(
+ final VnfPkgConflictException vnfPkgConflictException) {
+ final ProblemDetails problemDetails = new ProblemDetails();
+ problemDetails.setDetail(vnfPkgConflictException.getMessage());
+ return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetails);
+ }
+
+ @ExceptionHandler(VnfPkgNotFoundException.class)
+ public ResponseEntity<ProblemDetails> handleVnfPkgNotFoundException(
+ final VnfPkgNotFoundException vnfPkgNotFoundException) {
+ final ProblemDetails problemDetails = new ProblemDetails();
+ problemDetails.setDetail(vnfPkgNotFoundException.getMessage());
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetails);
+ }
+
+ @ExceptionHandler(VnfPkgBadRequestException.class)
+ public ResponseEntity<ProblemDetails> handleVnfPkgBadRequestException(
+ final VnfPkgBadRequestException vnfPkgBadRequestException) {
+ final ProblemDetails problemDetails = new ProblemDetails();
+ problemDetails.setDetail(vnfPkgBadRequestException.getMessage());
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetails);
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionNotFoundException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionNotFoundException.java
new file mode 100644
index 0000000000..58c2ef050d
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionNotFoundException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Request Failure
+ *
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.NOT_FOUND)
+public class SubscriptionNotFoundException extends RuntimeException {
+
+ private static final long serialVersionUID = 85268561453194516L;
+
+ public SubscriptionNotFoundException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgBadRequestException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgBadRequestException.java
new file mode 100644
index 0000000000..211131c2a4
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgBadRequestException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for a Vnfpkg Bad Request failure, due to state of resource.
+ *
+ * @author andrew.a.lamb@est.tech
+ */
+@ResponseStatus(code = HttpStatus.BAD_REQUEST)
+public class VnfPkgBadRequestException extends RuntimeException {
+
+ private static final long serialVersionUID = 3301317418914258411L;
+
+ public VnfPkgBadRequestException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgConflictException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgConflictException.java
new file mode 100644
index 0000000000..f9aa2a0e21
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgConflictException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for a VnfPkg Conflict failures, due to state of resource.
+ *
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.CONFLICT)
+public class VnfPkgConflictException extends RuntimeException {
+
+ private static final long serialVersionUID = 26862444537198441L;
+
+ public VnfPkgConflictException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgNotFoundException.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgNotFoundException.java
new file mode 100644
index 0000000000..c15e7052ab
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/VnfPkgNotFoundException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for VnfPkg Not Found Failures
+ *
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.NOT_FOUND)
+public class VnfPkgNotFoundException extends RuntimeException {
+
+ private static final long serialVersionUID = 26862444537198441L;
+
+ public VnfPkgNotFoundException(final String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationControllerTest.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationControllerTest.java
new file mode 100644
index 0000000000..1d3cf73729
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationControllerTest.java
@@ -0,0 +1,602 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.adapters.vnfmadapter.common.CommonConstants.ETSI_SUBSCRIPTION_NOTIFICATION_CONTROLLER_BASE_URL;
+import static org.onap.so.client.RestTemplateConfig.CONFIGURABLE_REST_TEMPLATE;
+import static org.springframework.test.annotation.DirtiesContext.ClassMode.BEFORE_CLASS;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.so.adapters.vnfmadapter.PackageManagementConstants;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.NOTIFICATIONLINKSERIALIZER;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgChangeNotification;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgOnboardingNotification;
+import org.onap.so.adapters.vnfmadapter.etsicatalog.notification.model.PkgmLinks;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthenticationParamsBasic;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthenticationParamsOauth2ClientCredentials;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.VnfPackageChangeNotification;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.notification.model.VnfPackageOnboardingNotification;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.client.MockRestServiceServer;
+import org.springframework.web.client.RestTemplate;
+import org.threeten.bp.LocalDateTime;
+import org.threeten.bp.OffsetDateTime;
+import org.threeten.bp.ZoneOffset;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+@DirtiesContext(classMode = BEFORE_CLASS)
+public class EtsiSubscriptionNotificationControllerTest {
+
+ @LocalServerPort
+ private int port;
+
+ private static final URI CALLBACK_URI = URI.create("http://test_callback_uri/notification");
+ private static final String TOKEN_ENDPOINT = "http://test_token_endpoint_uri/";
+ private static final String TOKEN = "dXNlcm5hbWU6cGFzc3dvcmQ=......";
+ private static final String JSON_TOKEN = "{\"access_token\":\"" + TOKEN + "\"}";
+ private static final String LOCALHOST_URL = "http://localhost:";
+ private static final String NOTIFICATION_BASE_URL =
+ ETSI_SUBSCRIPTION_NOTIFICATION_CONTROLLER_BASE_URL + "/notification";
+ private static final String USERNAME = "username";
+ private static final String PASSWORD = "password";
+ private static final String EXPECTED_BASIC_AUTHORIZATION = "Basic dXNlcm5hbWU6cGFzc3dvcmQ=";
+ private static final String EXPECTED_OAUTH_AUTHORIZATION = "Bearer " + TOKEN;
+ private static final String NOTIFICATION_ID = "NOTIFICATION_ID";
+ private static final String SUBSCRIPTION_ID = "SUBSCRIPTION_ID";
+ private static final OffsetDateTime TIMESTAMP =
+ OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 1, 1, 1, 1), ZoneOffset.ofHours(1));
+ private static final String VNFPKG_ID = UUID.randomUUID().toString();
+ private static final String VNFD_ID = UUID.randomUUID().toString();
+
+ private BasicHttpHeadersProvider basicHttpHeadersProvider;
+ private final Gson gson = new GsonBuilder().create();;
+
+ @Autowired
+ @Qualifier(CONFIGURABLE_REST_TEMPLATE)
+ private RestTemplate restTemplate;
+ private MockRestServiceServer mockRestServiceServer;
+
+ @Autowired
+ private TestRestTemplate testRestTemplate;
+
+ @Autowired
+ private CacheManager cacheServiceProvider;
+ private Cache cache;
+
+ @Before
+ public void setUp() {
+ mockRestServiceServer = MockRestServiceServer.bindTo(restTemplate).build();
+ basicHttpHeadersProvider = new BasicHttpHeadersProvider();
+ cache = cacheServiceProvider.getCache(PackageManagementConstants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE);
+ cache.clear();
+ }
+
+ @After
+ public void tearDown() {
+ mockRestServiceServer.reset();
+ cache.clear();
+ }
+
+ @Test
+ public void testSubscriptionNotificationEndPoint_ReturnsNoContent() {
+ final ResponseEntity<?> response = sendHttpGet(NOTIFICATION_BASE_URL);
+ assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+ }
+
+ @Test
+ public void testOnboardingNotificationSentOnToVnfmCallbackUri_SubscriptionRequestInCache_Success() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgOnboardingNotification notification = buildPkgOnboardingNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andExpect(jsonPath("$.id").value(NOTIFICATION_ID))
+ .andExpect(jsonPath("$.notificationType")
+ .value(VnfPackageOnboardingNotification.NotificationTypeEnum.VNFPACKAGEONBOARDINGNOTIFICATION
+ .toString()))
+ .andExpect(jsonPath("$.subscriptionId").value(SUBSCRIPTION_ID))
+ .andExpect(jsonPath("$.timeStamp").value(TIMESTAMP.toString()))
+ .andExpect(jsonPath("$.vnfPkgId").value(VNFPKG_ID.toString()))
+ .andExpect(jsonPath("$.vnfdId").value(VNFD_ID.toString()))
+ .andExpect(jsonPath("$._links").value(buildPkgmLinks()))
+ .andExpect(header("Authorization", EXPECTED_BASIC_AUTHORIZATION)).andRespond(withSuccess());
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+ }
+
+ @Test
+ public void testOnboardingNotificationNotSentOnToVnfmCallbackUri_SubscriptionRequestNotInCache_Fail() {
+ final PkgOnboardingNotification notification = buildPkgOnboardingNotification();
+ final String notificationString = gson.toJson(notification);
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "No subscription found with subscriptionId " + SUBSCRIPTION_ID
+ + ". Unable to forward notification to subscriber.";
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testOnboardingNotificationSentOnToVnfmCallbackUri_BadRequestResponseFromCallbackUri_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgOnboardingNotification notification = buildPkgOnboardingNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andRespond(withStatus(HttpStatus.BAD_REQUEST));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.BAD_REQUEST + ".\n" + "No result found for given url: " + CALLBACK_URI;
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testOnboardingNotificationSentOnToVnfmCallbackUri_301MovedPermanentlyResponseFromCallbackUri_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgOnboardingNotification notification = buildPkgOnboardingNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andRespond(withStatus(HttpStatus.MOVED_PERMANENTLY));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed.";
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testOnboardingNotificationSentOnToVnfmCallbackUri_NotFoundResponseFromCallbackUri_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgOnboardingNotification notification = buildPkgOnboardingNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.NOT_FOUND + ".\n" + "No result found for given url: " + CALLBACK_URI;
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testOnboardingNotificationSentOnToVnfmCallbackUri_InternalServerErrorResponseFromCallbackUri_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgOnboardingNotification notification = buildPkgOnboardingNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.INTERNAL_SERVER_ERROR.value() + ".\n" + "Unable to invoke HTTP POST using URL: "
+ + CALLBACK_URI;
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testChangeNotificationSentOnToVnfmCallbackUri_SubscriptionRequestInCache_Success() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andExpect(jsonPath("$.id").value(NOTIFICATION_ID))
+ .andExpect(jsonPath("$.notificationType").value(
+ VnfPackageChangeNotification.NotificationTypeEnum.VNFPACKAGECHANGENOTIFICATION.getValue()))
+ .andExpect(jsonPath("$.subscriptionId").value(SUBSCRIPTION_ID))
+ .andExpect(jsonPath("$.timeStamp").value(TIMESTAMP.toString()))
+ .andExpect(jsonPath("$.vnfPkgId").value(VNFPKG_ID.toString()))
+ .andExpect(jsonPath("$.vnfdId").value(VNFD_ID.toString()))
+ .andExpect(
+ jsonPath("$.changeType").value(PkgChangeNotification.ChangeTypeEnum.OP_STATE_CHANGE.toString()))
+ .andExpect(jsonPath("$.operationalState")
+ .value(PkgChangeNotification.OperationalStateEnum.ENABLED.toString()))
+ .andExpect(jsonPath("$._links").value(buildPkgmLinks()))
+ .andExpect(header("Authorization", EXPECTED_BASIC_AUTHORIZATION)).andRespond(withSuccess());
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+ }
+
+ @Test
+ public void testChangeNotificationNotSentOnToVnfmCallbackUri_SubscriptionRequestNotInCache_Fail() {
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "No subscription found with subscriptionId " + SUBSCRIPTION_ID
+ + ". Unable to forward notification to subscriber.";
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testChangeNotificationSentOnToVnfmCallbackUri_BadRequestResponseFromCallbackUri_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andRespond(withStatus(HttpStatus.BAD_REQUEST));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.BAD_REQUEST + ".\n" + "No result found for given url: " + CALLBACK_URI;
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testChangeNotificationSentOnToVnfmCallbackUri_NotFoundResponseFromCallbackUri_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.NOT_FOUND + ".\n" + "No result found for given url: " + CALLBACK_URI;
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testChangeNotificationSentOnToVnfmCallbackUri_InternalServerErrorResponseFromCallbackUri_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.INTERNAL_SERVER_ERROR.value() + ".\n" + "Unable to invoke HTTP POST using URL: "
+ + CALLBACK_URI;
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testNotificationSentOnToVnfm_BasicAuthUserPasswordAuthorized_Success() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgOnboardingNotification notification = buildPkgOnboardingNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andExpect(jsonPath("$.id").value(NOTIFICATION_ID))
+ .andExpect(jsonPath("$.notificationType")
+ .value(VnfPackageOnboardingNotification.NotificationTypeEnum.VNFPACKAGEONBOARDINGNOTIFICATION
+ .toString()))
+ .andExpect(jsonPath("$.subscriptionId").value(SUBSCRIPTION_ID))
+ .andExpect(jsonPath("$.timeStamp").value(TIMESTAMP.toString()))
+ .andExpect(jsonPath("$.vnfPkgId").value(VNFPKG_ID.toString()))
+ .andExpect(jsonPath("$.vnfdId").value(VNFD_ID.toString()))
+ .andExpect(jsonPath("$._links").value(buildPkgmLinks()))
+ .andExpect(header("Authorization", EXPECTED_BASIC_AUTHORIZATION)).andRespond(withSuccess());
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+ }
+
+ @Test
+ public void testNotificationSentOnToVnfm_BasicAuthUserPasswordNotAuthorized_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.BASIC);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andExpect(header("Authorization", EXPECTED_BASIC_AUTHORIZATION))
+ .andRespond(withStatus(HttpStatus.UNAUTHORIZED));
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Sending of notification to VNFM failed with response: "
+ + HttpStatus.UNAUTHORIZED.value() + ".\n" + "Unable to invoke HTTP POST using URL: " + CALLBACK_URI;
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testNotificationSentOnToVnfm_OAuthAuthorized_Success() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.OAUTH2_CLIENT_CREDENTIALS);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(TOKEN_ENDPOINT)).andExpect(method(HttpMethod.POST))
+ .andExpect(header("Authorization", EXPECTED_BASIC_AUTHORIZATION))
+ .andRespond(withSuccess(JSON_TOKEN, MediaType.APPLICATION_JSON));
+
+ mockRestServiceServer.expect(requestTo(CALLBACK_URI)).andExpect(method(HttpMethod.POST))
+ .andExpect(header("Authorization", EXPECTED_OAUTH_AUTHORIZATION))
+ .andExpect(jsonPath("$.id").value(NOTIFICATION_ID))
+ .andExpect(jsonPath("$.notificationType").value(
+ VnfPackageChangeNotification.NotificationTypeEnum.VNFPACKAGECHANGENOTIFICATION.toString()))
+ .andExpect(jsonPath("$.subscriptionId").value(SUBSCRIPTION_ID))
+ .andExpect(jsonPath("$.timeStamp").value(TIMESTAMP.toString()))
+ .andExpect(jsonPath("$.vnfPkgId").value(VNFPKG_ID.toString()))
+ .andExpect(jsonPath("$.vnfdId").value(VNFD_ID.toString()))
+ .andExpect(
+ jsonPath("$.changeType").value(PkgChangeNotification.ChangeTypeEnum.OP_STATE_CHANGE.toString()))
+ .andExpect(jsonPath("$.operationalState")
+ .value(PkgChangeNotification.OperationalStateEnum.ENABLED.toString()))
+ .andExpect(jsonPath("$._links").value(buildPkgmLinks())).andRespond(withSuccess());
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+ }
+
+ @Test
+ public void testNotificationSentOnToVnfm_OAuthTokenNotReceived_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.OAUTH2_CLIENT_CREDENTIALS);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ mockRestServiceServer.expect(requestTo(TOKEN_ENDPOINT)).andExpect(method(HttpMethod.POST))
+ .andExpect(header("Authorization", EXPECTED_BASIC_AUTHORIZATION)).andRespond(withSuccess());
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Unable to retrieve OAuth Token from VNFM for notification.";
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ @Test
+ public void testNotificationSentOnToVnfm_TLSCertNotYetSupported_Fail() {
+ final PkgmSubscriptionRequest subscriptionRequest =
+ buildPkgmSubscriptionRequest(SubscriptionsAuthentication.AuthTypeEnum.TLS_CERT);
+ cache.put(SUBSCRIPTION_ID, subscriptionRequest);
+ final PkgChangeNotification notification = buildPkgChangeNotification();
+ final String notificationString = gson.toJson(notification);
+
+ final ResponseEntity<?> response = sendHttpPost(notificationString);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+
+ final ProblemDetails problemDetails = (ProblemDetails) response.getBody();
+ final String errorMessage = "An error occurred. Authentication type "
+ + subscriptionRequest.getAuthentication().getAuthType().toString() + " not currently supported.";
+
+ assertEquals(errorMessage, problemDetails.getDetail());
+ }
+
+ private PkgOnboardingNotification buildPkgOnboardingNotification() {
+ final PkgOnboardingNotification notification = new PkgOnboardingNotification();
+ notification.setId(NOTIFICATION_ID);
+ notification
+ .setNotificationType(PkgOnboardingNotification.NotificationTypeEnum.VNFPACKAGEONBOARDINGNOTIFICATION);
+ notification.setSubscriptionId(SUBSCRIPTION_ID);
+ notification.setTimeStamp(TIMESTAMP);
+ notification.setVnfPkgId(VNFPKG_ID);
+ notification.setVnfdId(VNFD_ID);
+ notification.setLinks(buildPkgmLinks());
+ return notification;
+ }
+
+ private PkgChangeNotification buildPkgChangeNotification() {
+ final PkgChangeNotification notification = new PkgChangeNotification();
+ notification.setId(NOTIFICATION_ID);
+ notification.setNotificationType(PkgChangeNotification.NotificationTypeEnum.VNFPACKAGECHANGENOTIFICATION);
+ notification.setSubscriptionId(SUBSCRIPTION_ID);
+ notification.setTimeStamp(TIMESTAMP);
+ notification.setVnfPkgId(VNFPKG_ID);
+ notification.setVnfdId(VNFD_ID);
+ notification.setChangeType(PkgChangeNotification.ChangeTypeEnum.OP_STATE_CHANGE);
+ notification.setOperationalState(PkgChangeNotification.OperationalStateEnum.ENABLED);
+ notification.setLinks(buildPkgmLinks());
+ return notification;
+ }
+
+ private PkgmLinks buildPkgmLinks() {
+ final PkgmLinks pkgmLinks = new PkgmLinks();
+
+ final NOTIFICATIONLINKSERIALIZER subscriptionLinkSerializer = new NOTIFICATIONLINKSERIALIZER();
+ subscriptionLinkSerializer.setHref("subscription_href");
+ pkgmLinks.setSubscription(subscriptionLinkSerializer);
+
+ final NOTIFICATIONLINKSERIALIZER vnfPackageLinkSerializer = new NOTIFICATIONLINKSERIALIZER();
+ vnfPackageLinkSerializer.setHref("vnf_package_href");
+ pkgmLinks.setVnfPackage(vnfPackageLinkSerializer);
+
+ return pkgmLinks;
+ }
+
+ private PkgmSubscriptionRequest buildPkgmSubscriptionRequest(
+ final SubscriptionsAuthentication.AuthTypeEnum authTypeEnum) {
+ final PkgmSubscriptionRequest subscriptionRequest = new PkgmSubscriptionRequest();
+ subscriptionRequest.setCallbackUri(CALLBACK_URI.toString());
+ subscriptionRequest.setAuthentication(buildSubscriptionsAuthentication(authTypeEnum));
+ return subscriptionRequest;
+ }
+
+ // TODO update for auth types other than basicAuth
+ private SubscriptionsAuthentication buildSubscriptionsAuthentication(
+ final SubscriptionsAuthentication.AuthTypeEnum authTypeEnum) {
+ final SubscriptionsAuthentication subscriptionsAuthentication = new SubscriptionsAuthentication();
+ final List<SubscriptionsAuthentication.AuthTypeEnum> authTypes = new ArrayList<>();
+ authTypes.add(authTypeEnum);
+ subscriptionsAuthentication.setAuthType(authTypes);
+ if (authTypeEnum == SubscriptionsAuthentication.AuthTypeEnum.TLS_CERT) {
+ // TODO: remove basic params and code for TLS
+ final SubscriptionsAuthenticationParamsBasic basicParams =
+ new SubscriptionsAuthenticationParamsBasic().userName(USERNAME).password(PASSWORD);
+ subscriptionsAuthentication.setParamsBasic(basicParams);
+ } else if (authTypeEnum == SubscriptionsAuthentication.AuthTypeEnum.OAUTH2_CLIENT_CREDENTIALS) {
+ final SubscriptionsAuthenticationParamsOauth2ClientCredentials oathParams =
+ new SubscriptionsAuthenticationParamsOauth2ClientCredentials().clientId(USERNAME)
+ .clientPassword(PASSWORD).tokenEndpoint(TOKEN_ENDPOINT);
+ subscriptionsAuthentication.setParamsOauth2ClientCredentials(oathParams);
+ } else {
+ final SubscriptionsAuthenticationParamsBasic basicParams =
+ new SubscriptionsAuthenticationParamsBasic().userName(USERNAME).password(PASSWORD);
+ subscriptionsAuthentication.setParamsBasic(basicParams);
+ }
+
+ return subscriptionsAuthentication;
+ }
+
+ private <T> ResponseEntity<ProblemDetails> sendHttpPost(final T notification) {
+ final String testURL = LOCALHOST_URL + port + NOTIFICATION_BASE_URL;
+ final HttpEntity<?> request = new HttpEntity<>(notification, basicHttpHeadersProvider.getHttpHeaders());
+ return testRestTemplate.withBasicAuth("test", "test").exchange(testURL, HttpMethod.POST, request,
+ ProblemDetails.class);
+ }
+
+ private ResponseEntity<Void> sendHttpGet(final String url) {
+ final String testURL = LOCALHOST_URL + port + url;
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+ return testRestTemplate.withBasicAuth("test", "test").exchange(testURL, HttpMethod.GET, request, Void.class);
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementControllerTest.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementControllerTest.java
new file mode 100644
index 0000000000..9ea0c1d880
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementControllerTest.java
@@ -0,0 +1,677 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.adapters.vnfmadapter.common.CommonConstants.PACKAGE_MANAGEMENT_BASE_URL;
+import static org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.Checksum;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.UriLink;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VNFPKGMLinkSerializer;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPackageArtifactInfo;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPackageSoftwareImageInfo;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPkgInfo;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse2001;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesLinks;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.client.MockRestServiceServer;
+import org.springframework.web.client.RestTemplate;
+import com.google.gson.Gson;
+
+/**
+ * @author gareth.roper@est.tech
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+public class Sol003PackageManagementControllerTest {
+
+ @LocalServerPort
+ private int port;
+
+ @Autowired
+ @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
+ private RestTemplate restTemplate;
+
+ @Autowired
+ private TestRestTemplate testRestTemplate;
+
+ private static final String VNF_PACKAGE_ID = "myVnfPackageId";
+ private static final String ARTIFACT_PATH = "myArtifactPath";
+ private static final String MSB_BASE_URL = "http://msb-iag.onap:80/api/vnfpkgm/v1/vnf_packages";
+ private static final String VNFPKGM_BASE_URL = PACKAGE_MANAGEMENT_BASE_URL + "/vnf_packages";
+ private static final String localhostUrl = "http://localhost:";
+ private static final String GET_VNF_PACKAGES_URL = "";
+ private static final String GET_VNF_PACKAGE_BY_ID_URL = "/" + VNF_PACKAGE_ID;
+ private static final String VNFD_ID = "vnfdId";
+ private static final String VNF_PROVIDER = "vnfProvider";
+ private static final String VNF_PRODUCT_NAME = "vnfProductName";
+ private static final String VNF_SOFTWARE_VERSION = "vnfSoftwareVersion";
+ private static final String VNFD_VERSION = "vnfdVersion";
+ private static final String ALGORITHM = "algorithm";
+ private static final String HASH = "hash";
+ private static final String EXPECTED_BASE_URL =
+ "https://so-vnfm-adapter.onap:30406/so/vnfm-adapter/v1/vnfpkgm/v1/vnf_packages/";
+ private static final String EXPECTED_SELF_HREF = EXPECTED_BASE_URL + VNF_PACKAGE_ID;
+ private static final String EXPECTED_VNFD_HREF = EXPECTED_BASE_URL + VNF_PACKAGE_ID + "/vnfd";
+ private static final String EXPECTED_PACKAGE_CONTENT_HREF = EXPECTED_BASE_URL + VNF_PACKAGE_ID + "/package_content";
+
+ private MockRestServiceServer mockRestServiceServer;
+ private BasicHttpHeadersProvider basicHttpHeadersProvider;
+ private final Gson gson = new Gson();
+
+ public Sol003PackageManagementControllerTest() {}
+
+ @Before
+ public void setUp() {
+ final MockRestServiceServer.MockRestServiceServerBuilder builder = MockRestServiceServer.bindTo(restTemplate);
+ builder.ignoreExpectOrder(true);
+ mockRestServiceServer = builder.build();
+ basicHttpHeadersProvider = new BasicHttpHeadersProvider();
+ }
+
+ @After
+ public void after() {
+ mockRestServiceServer.reset();
+ }
+
+ @Test
+ public void testGetPackageContent_ValidArray_Success() {
+ final byte[] responseArray = buildByteArrayWithRandomData(10);
+
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(responseArray, MediaType.APPLICATION_OCTET_STREAM));
+
+ final String testURL = "http://localhost:" + port + PACKAGE_MANAGEMENT_BASE_URL + "/vnf_packages/"
+ + VNF_PACKAGE_ID + "/package_content";
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+ final ResponseEntity<byte[]> responseEntity =
+ testRestTemplate.withBasicAuth("test", "test").exchange(testURL, HttpMethod.GET, request, byte[].class);
+
+ assertEquals(byte[].class, responseEntity.getBody().getClass());
+ assertArrayEquals(responseEntity.getBody(), responseArray);
+ assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageContent_Conflict_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.CONFLICT));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/package_content");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.CONFLICT, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageContent_NotFound_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/package_content");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageContent_UnauthorizedClient_Fail() {
+ final String testURL = "http://localhost:" + port + PACKAGE_MANAGEMENT_BASE_URL + "/vnf_packages/"
+ + VNF_PACKAGE_ID + "/package_content";
+
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.UNAUTHORIZED));
+
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+
+
+ final ResponseEntity<ProblemDetails> responseEntity =
+ testRestTemplate.exchange(testURL, HttpMethod.GET, request, ProblemDetails.class);
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageContent_InternalServerError_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/package_content");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageContent_BadRequest_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.BAD_REQUEST));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/package_content");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageContent_UnauthorizedServer_InternalError_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.UNAUTHORIZED));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/package_content");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testGetPackageContent_SuccessResponseFromServerWithNullPackage_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/package_content"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withSuccess());
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/package_content");
+
+ assertEquals(ProblemDetails.class, responseEntity.getBody().getClass());
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testGetPackageArtifact_ValidArray_Success() {
+ final byte[] responseArray = buildByteArrayWithRandomData(10);
+
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(responseArray, MediaType.APPLICATION_OCTET_STREAM));
+
+ final String testURL = "http://localhost:" + port + PACKAGE_MANAGEMENT_BASE_URL + "/vnf_packages/"
+ + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH;
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+ final ResponseEntity<byte[]> responseEntity =
+ testRestTemplate.withBasicAuth("test", "test").exchange(testURL, HttpMethod.GET, request, byte[].class);
+
+ assertEquals(byte[].class, responseEntity.getBody().getClass());
+ assertArrayEquals(responseEntity.getBody(), responseArray);
+ assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageArtifact_Conflict_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.CONFLICT));
+
+ final ResponseEntity<ProblemDetails> responseEntity =
+ sendHttpRequest(VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH);
+
+ assertNotNull(responseEntity.getBody());
+ assertEquals(HttpStatus.CONFLICT, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageArtifact_NotFound_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<ProblemDetails> responseEntity =
+ sendHttpRequest(VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH);
+
+ assertNotNull(responseEntity.getBody());
+ assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageArtifact_UnauthorizedClient_Fail() {
+ final String testURL = "http://localhost:" + port + PACKAGE_MANAGEMENT_BASE_URL + "/vnf_packages/"
+ + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH;
+
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.UNAUTHORIZED));
+
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+ final ResponseEntity<ProblemDetails> responseEntity =
+ testRestTemplate.exchange(testURL, HttpMethod.GET, request, ProblemDetails.class);
+
+ assertNotNull(responseEntity.getBody());
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageArtifact_InternalServerError_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
+
+ final ResponseEntity<ProblemDetails> responseEntity =
+ sendHttpRequest(VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH);
+
+ assertNotNull(responseEntity.getBody());
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageArtifact_BadRequest_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.BAD_REQUEST));
+
+ final ResponseEntity<ProblemDetails> responseEntity =
+ sendHttpRequest(VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH);
+
+ assertNotNull(responseEntity.getBody());
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageArtifact_UnauthorizedServer_InternalError_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.UNAUTHORIZED));
+
+ final ResponseEntity<ProblemDetails> responseEntity =
+ sendHttpRequest(VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH);
+
+ assertNotNull(responseEntity.getBody());
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testGetPackageArtifact_SuccessResponseFromServerWithNullPackage_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH))
+ .andExpect(method(HttpMethod.GET)).andRespond(withSuccess());
+
+ final ResponseEntity<ProblemDetails> responseEntity =
+ sendHttpRequest(VNF_PACKAGE_ID + "/artifacts/" + ARTIFACT_PATH);
+
+ assertNotNull(responseEntity.getBody());
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testVnfPackagesReceivedAsInlineResponse2001ListIfGetVnfPackagesSuccessful() {
+ final VnfPkgInfo[] responses = createVnfPkgArray();
+
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL)).andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(gson.toJson(responses), MediaType.APPLICATION_JSON));
+
+ final String testURL = localhostUrl + port + VNFPKGM_BASE_URL;
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+
+ final ResponseEntity<InlineResponse2001[]> responseEntity = testRestTemplate.withBasicAuth("test", "test")
+ .exchange(testURL, HttpMethod.GET, request, InlineResponse2001[].class);
+
+ assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
+ assertNotNull(responseEntity.getBody());
+ final InlineResponse2001[] inlineResponse2001array = responseEntity.getBody();
+ final InlineResponse2001 inlineResponse2001 = inlineResponse2001array[0];
+ assertEquals(VNF_PACKAGE_ID, inlineResponse2001.getId());
+ assertEquals(VNFD_ID, inlineResponse2001.getVnfdId());
+ assertEquals(VNFD_ID, inlineResponse2001.getSoftwareImages().get(0).getId());
+ assertEquals(VNF_PRODUCT_NAME, inlineResponse2001.getSoftwareImages().get(0).getName());
+ assertEquals(ALGORITHM, inlineResponse2001.getChecksum().getAlgorithm());
+ assertEquals(HASH, inlineResponse2001.getChecksum().getHash());
+ assertEquals(ARTIFACT_PATH, inlineResponse2001.getAdditionalArtifacts().get(0).getArtifactPath());
+ assertEquals(ALGORITHM, inlineResponse2001.getAdditionalArtifacts().get(0).getChecksum().getAlgorithm());
+ assertEquals(HASH, inlineResponse2001.getAdditionalArtifacts().get(0).getChecksum().getHash());
+ final VnfPackagesLinks links = inlineResponse2001.getLinks();
+ assertNotNull(links);
+ assertEquals(EXPECTED_SELF_HREF, links.getSelf().getHref());
+ assertEquals(EXPECTED_VNFD_HREF, links.getVnfd().getHref());
+ assertEquals(EXPECTED_PACKAGE_CONTENT_HREF, links.getPackageContent().getHref());
+ }
+
+ @Test
+ public void test400BadRequestInfoReceivedAsProblemDetailsIfGetVnfPackagesIs400BadRequest() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL)).andExpect(method(HttpMethod.GET))
+ .andRespond(withStatus(HttpStatus.BAD_REQUEST));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGES_URL);
+ assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
+
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("Error: Bad Request Received", problemDetails.getDetail());
+ }
+
+ @Test
+ public void test404NotFoundInfoReceivedAsProblemDetailsIfGetVnfPackagesIs404NotFound() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL)).andExpect(method(HttpMethod.GET))
+ .andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGES_URL);
+ assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
+
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("No Vnf Packages found", problemDetails.getDetail());
+ }
+
+ @Test
+ public void test500InternalServerErrorProblemDetailsReceivedIfGetVnfPackagesReturns500InternalServerError() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL)).andExpect(method(HttpMethod.GET))
+ .andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGES_URL);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("Internal Server Error Occurred.", problemDetails.getDetail());
+ }
+
+ @Test
+ public void test500InternalServerErrorProblemDetailsReceivedIfGetVnfPackagesReturnsANullPackage() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL)).andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess());
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGES_URL);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("An error occurred, a null response was received by the\n"
+ + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"vnf_packages\" \n"
+ + "endpoint.", problemDetails.getDetail());
+ }
+
+ @Test
+ public void testVnfPackageReceivedAsInlineResponse2001IfGetVnfPackageByIdSuccessful() {
+ final VnfPkgInfo response = createVnfPkgInfo(VNF_PACKAGE_ID);
+
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID)).andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(gson.toJson(response), MediaType.APPLICATION_JSON));
+
+ final String testURL = localhostUrl + port + VNFPKGM_BASE_URL + "/" + VNF_PACKAGE_ID;
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+ final ResponseEntity<InlineResponse2001> responseEntity = testRestTemplate.withBasicAuth("test", "test")
+ .exchange(testURL, HttpMethod.GET, request, InlineResponse2001.class);
+
+ assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
+ assertNotNull(responseEntity.getBody());
+ final InlineResponse2001 inlineResponse2001 = responseEntity.getBody();
+ assertEquals(VNF_PACKAGE_ID, inlineResponse2001.getId());
+ assertEquals(VNFD_ID, inlineResponse2001.getVnfdId());
+ assertEquals(VNFD_ID, inlineResponse2001.getSoftwareImages().get(0).getId());
+ assertEquals(VNF_PRODUCT_NAME, inlineResponse2001.getSoftwareImages().get(0).getName());
+ assertEquals(ALGORITHM, inlineResponse2001.getChecksum().getAlgorithm());
+ assertEquals(HASH, inlineResponse2001.getChecksum().getHash());
+ assertEquals(ARTIFACT_PATH, inlineResponse2001.getAdditionalArtifacts().get(0).getArtifactPath());
+ assertEquals(ALGORITHM, inlineResponse2001.getAdditionalArtifacts().get(0).getChecksum().getAlgorithm());
+ assertEquals(HASH, inlineResponse2001.getAdditionalArtifacts().get(0).getChecksum().getHash());
+ final VnfPackagesLinks links = inlineResponse2001.getLinks();
+ assertNotNull(links);
+ assertEquals(EXPECTED_SELF_HREF, links.getSelf().getHref());
+ assertEquals(EXPECTED_VNFD_HREF, links.getVnfd().getHref());
+ assertEquals(EXPECTED_PACKAGE_CONTENT_HREF, links.getPackageContent().getHref());
+
+ }
+
+ @Test
+ public void test400BadRequestInfoReceivedAsProblemDetailsIfGetVnfPackageByIdIs400BadRequest() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID)).andExpect(method(HttpMethod.GET))
+ .andRespond(withStatus(HttpStatus.BAD_REQUEST));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGE_BY_ID_URL);
+
+ assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("Error: Bad Request Received", problemDetails.getDetail());
+ }
+
+ @Test
+ public void test404NotFoundInfoReceivedAsProblemDetailsIfGetVnfPackageByIdIs404NotFound() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID)).andExpect(method(HttpMethod.GET))
+ .andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGE_BY_ID_URL);
+
+ assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("No Vnf Package found with vnfPkgId: " + VNF_PACKAGE_ID, problemDetails.getDetail());
+ }
+
+ @Test
+ public void test500InternalServerErrorProblemDetailsReceivedIfGetVnfPackageByIdReturns500InternalServerError() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID)).andExpect(method(HttpMethod.GET))
+ .andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGE_BY_ID_URL);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("Internal Server Error Occurred.", problemDetails.getDetail());
+ }
+
+ @Test
+ public void test500InternalServerErrorProblemDetailsReceivedIfGetVnfPackageByIdReturnsANullPackage() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID)).andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess());
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(GET_VNF_PACKAGE_BY_ID_URL);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+
+ assertNotNull(responseEntity.getBody());
+ final ProblemDetails problemDetails = responseEntity.getBody();
+ assertEquals("An error occurred, a null response was received by the\n"
+ + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"vnf_packages\" by vnfPkgId: \""
+ + VNF_PACKAGE_ID + "\" \n" + "endpoint.", problemDetails.getDetail());
+ }
+
+ // The below test method is here to improve code coverage and provide a foundation for writing
+ // future tests
+ @Test
+ public void testGetPackageVnfd_ValidArray_Success() {
+ final byte[] responseArray = buildByteArrayWithRandomData(10);
+
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(responseArray, MediaType.APPLICATION_OCTET_STREAM));
+
+ final String testURL =
+ "http://localhost:" + port + PACKAGE_MANAGEMENT_BASE_URL + "/vnf_packages/" + VNF_PACKAGE_ID + "/vnfd";
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+ final ResponseEntity<byte[]> responseEntity =
+ testRestTemplate.withBasicAuth("test", "test").exchange(testURL, HttpMethod.GET, request, byte[].class);
+
+ assertEquals(byte[].class, responseEntity.getBody().getClass());
+ assertArrayEquals(responseEntity.getBody(), responseArray);
+ assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageVnfd_Conflict_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.CONFLICT));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/vnfd");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.CONFLICT, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageVnfd_NotFound_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/vnfd");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageVnfd_UnauthorizedClient_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.UNAUTHORIZED));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/vnfd");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageVnfd_InternalServerError_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/vnfd");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageVnfd_BadRequest_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.BAD_REQUEST));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/vnfd");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testOnGetPackageVnfd_UnauthorizedServer_InternalError_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.UNAUTHORIZED));
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/vnfd");
+
+ assertTrue(responseEntity.getBody() instanceof ProblemDetails);
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ @Test
+ public void testGetPackageVnfd_SuccessResponseFromServerWithNullPackage_Fail() {
+ mockRestServiceServer.expect(requestTo(MSB_BASE_URL + "/" + VNF_PACKAGE_ID + "/vnfd"))
+ .andExpect(method(HttpMethod.GET)).andRespond(withSuccess());
+
+ final ResponseEntity<ProblemDetails> responseEntity = sendHttpRequest(VNF_PACKAGE_ID + "/vnfd");
+
+ assertEquals(ProblemDetails.class, responseEntity.getBody().getClass());
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+ }
+
+ // Simply returns a byte array filled with random data, for use in the tests.
+ private byte[] buildByteArrayWithRandomData(final int sizeInKb) {
+ final Random rnd = new Random();
+ final byte[] b = new byte[sizeInKb * 1024]; // converting kb to byte
+ rnd.nextBytes(b);
+ return b;
+ }
+
+ private ResponseEntity<ProblemDetails> sendHttpRequest(final String url) {
+ final String testURL = localhostUrl + port + VNFPKGM_BASE_URL + "/" + url;
+ final HttpEntity<?> request = new HttpEntity<>(basicHttpHeadersProvider.getHttpHeaders());
+ return testRestTemplate.withBasicAuth("test", "test").exchange(testURL, HttpMethod.GET, request,
+ ProblemDetails.class);
+ }
+
+ private VnfPkgInfo[] createVnfPkgArray() {
+ final VnfPkgInfo[] vnfPkgInfoArray = new VnfPkgInfo[1];
+ final VnfPkgInfo vnfPkgInfo = createVnfPkgInfo(VNF_PACKAGE_ID);
+ vnfPkgInfoArray[0] = vnfPkgInfo;
+ return vnfPkgInfoArray;
+ }
+
+ private VnfPkgInfo createVnfPkgInfo(final String vnfPackageId) {
+ final VnfPkgInfo vnfPkgInfo = new VnfPkgInfo();
+ vnfPkgInfo.setId(vnfPackageId);
+ vnfPkgInfo.setVnfdId(VNFD_ID);
+ vnfPkgInfo.setVnfProvider(VNF_PROVIDER);
+ vnfPkgInfo.setVnfProductName(VNF_PRODUCT_NAME);
+ vnfPkgInfo.setVnfSoftwareVersion(VNF_SOFTWARE_VERSION);
+ vnfPkgInfo.setVnfdVersion(VNFD_VERSION);
+ vnfPkgInfo.setChecksum(createVnfPkgChecksum());
+ vnfPkgInfo.setSoftwareImages(createSoftwareImages());
+ vnfPkgInfo.setAdditionalArtifacts(createAdditionalArtifacts());
+ vnfPkgInfo.setLinks(createVNFPKGMLinkSerializerLinks());
+ return vnfPkgInfo;
+ }
+
+ private Checksum createVnfPkgChecksum() {
+ final Checksum checksum = new Checksum();
+ checksum.setAlgorithm(ALGORITHM);
+ checksum.setHash(HASH);
+ return checksum;
+ }
+
+ private List<VnfPackageSoftwareImageInfo> createSoftwareImages() {
+ final List<VnfPackageSoftwareImageInfo> softwareImages = new ArrayList<>();
+ final VnfPackageSoftwareImageInfo vnfPackageSoftwareImageInfo = new VnfPackageSoftwareImageInfo();
+ vnfPackageSoftwareImageInfo.setId(VNFD_ID);
+ vnfPackageSoftwareImageInfo.setName(VNF_PRODUCT_NAME);
+ vnfPackageSoftwareImageInfo.setProvider("");
+ vnfPackageSoftwareImageInfo.setVersion("");
+ vnfPackageSoftwareImageInfo.setChecksum(createVnfPkgChecksum());
+ vnfPackageSoftwareImageInfo
+ .setContainerFormat(VnfPackageSoftwareImageInfo.ContainerFormatEnum.fromValue("AKI"));
+ softwareImages.add(vnfPackageSoftwareImageInfo);
+ return softwareImages;
+ }
+
+ private List<VnfPackageArtifactInfo> createAdditionalArtifacts() {
+ final List<VnfPackageArtifactInfo> vnfPackageArtifactInfos = new ArrayList<>();
+ final VnfPackageArtifactInfo vnfPackageArtifactInfo =
+ new VnfPackageArtifactInfo().artifactPath(ARTIFACT_PATH).checksum(createVnfPkgChecksum());
+ vnfPackageArtifactInfos.add(vnfPackageArtifactInfo);
+ return vnfPackageArtifactInfos;
+ }
+
+ private VNFPKGMLinkSerializer createVNFPKGMLinkSerializerLinks() {
+ final String baseUrl = "http://msb-iag:443/api/vnfpkgm/v1/vnf_packages";
+ return new VNFPKGMLinkSerializer().self(new UriLink().href(baseUrl + "/myVnfPackageId"))
+ .vnfd(new UriLink().href(baseUrl + "/myVnfPackageId/vnfd"))
+ .packageContent(new UriLink().href(baseUrl + "/myVnfPackageId/package_content"));
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionControllerTest.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionControllerTest.java
new file mode 100644
index 0000000000..b8eb73b2c8
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionControllerTest.java
@@ -0,0 +1,403 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.adapters.vnfmadapter.common.CommonConstants.ETSI_SUBSCRIPTION_NOTIFICATION_BASE_URL;
+import static org.onap.so.adapters.vnfmadapter.common.CommonConstants.PACKAGE_MANAGEMENT_BASE_URL;
+import static org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.so.adapters.vnfmadapter.PackageManagementConstants;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.BasicAuth;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.LinkSelf;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.NsdmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.SubscriptionAuthentication;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.Version;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfProducts;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfProductsProviders;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse2002;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.InlineResponse201;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilter1;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsFilterVnfProductsFromProviders;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.SubscriptionsLinks;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.model.VnfPackagesLinksSelf;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.client.MockRestServiceServer;
+import org.springframework.test.web.client.match.MockRestRequestMatchers;
+import org.springframework.web.client.RestTemplate;
+import com.google.gson.Gson;
+
+/**
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+public class Sol003PackageManagementSubscriptionControllerTest {
+
+ private final Gson gson = new Gson();
+ private final URI msbEndpoint = URI.create("http://msb-iag.onap:80/api/vnfpkgm/v1/subscriptions");
+ private static final String _NOTIFICATION_CALLBACK_URI =
+ "https://so-vnfm-adapter.onap:30406" + ETSI_SUBSCRIPTION_NOTIFICATION_BASE_URL;
+ private static final String LOCALHOST_URL = "http://localhost:";
+
+ @Autowired
+ @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
+ private RestTemplate restTemplate;
+ private MockRestServiceServer mockRestServiceServer;
+ @Autowired
+ private CacheManager cacheServiceProvider;
+ @Autowired
+ private Sol003PackageManagementSubscriptionController sol003PackageManagementSubscriptionController;
+
+ @Autowired
+ private TestRestTemplate testRestTemplate;
+
+ @LocalServerPort
+ private int port;
+
+ private static final String ID = UUID.randomUUID().toString();
+
+ @Before
+ public void setUp() {
+ mockRestServiceServer = MockRestServiceServer.bindTo(restTemplate).build();
+ final Cache cache =
+ cacheServiceProvider.getCache(PackageManagementConstants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE);
+ cache.clear();
+ }
+
+ @After
+ public void after() {
+ mockRestServiceServer.reset();
+ }
+
+ @Test
+ public void testSuccessPostSubscription() throws GeneralSecurityException, URISyntaxException {
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
+ final ResponseEntity<InlineResponse201> response =
+ (ResponseEntity<InlineResponse201>) sol003PackageManagementSubscriptionController
+ .postSubscriptionRequest(pkgmSubscriptionRequest);
+
+ final HttpHeaders headers = buildHttpHeaders(Objects.requireNonNull(response.getBody()).getCallbackUri());
+
+ final SubscriptionsLinks subscriptionsLinks = new SubscriptionsLinks();
+ final VnfPackagesLinksSelf vnfPackagesLinksSelf = new VnfPackagesLinksSelf();
+ vnfPackagesLinksSelf.setHref("https://so-vnfm-adapter.onap:30406" + PACKAGE_MANAGEMENT_BASE_URL
+ + "/subscriptions/" + response.getBody().getId());
+ subscriptionsLinks.setSelf(vnfPackagesLinksSelf);
+
+ assertEquals(pkgmSubscriptionRequest.getFilter(), response.getBody().getFilter());
+ assertEquals(subscriptionsLinks, response.getBody().getLinks());
+ assertEquals(response.getBody().getFilter(), pkgmSubscriptionRequest.getFilter());
+ assert (response.getHeaders().equals(headers));
+ assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
+ assertNotNull(response.getBody().getCallbackUri());
+ }
+
+ @Test
+ public void testFailPostSubscriptionAlreadyExists() throws GeneralSecurityException {
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
+
+ final ResponseEntity<InlineResponse2002> response =
+ (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+ .postSubscriptionRequest(pkgmSubscriptionRequest);
+
+ // Create duplicate entry
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest2 = buildPkgmSubscriptionRequest();
+
+ final ResponseEntity<InlineResponse2002> response2002 =
+ (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+ .postSubscriptionRequest(pkgmSubscriptionRequest2);
+
+ assertEquals(HttpStatus.SEE_OTHER, response2002.getStatusCode());
+ }
+
+ @Test
+ public void testSuccessGetSubscriptionWithSubscriptionId() throws GeneralSecurityException, URISyntaxException {
+
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + ID)).andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(gson.toJson(new NsdmSubscription().id(ID)), MediaType.APPLICATION_JSON));
+
+ final ResponseEntity<InlineResponse201> response =
+ (ResponseEntity<InlineResponse201>) sol003PackageManagementSubscriptionController
+ .postSubscriptionRequest(pkgmSubscriptionRequest);
+ final String subscriptionId = response.getBody().getId();
+
+
+
+ final ResponseEntity<InlineResponse201> responseEntity =
+ (ResponseEntity<InlineResponse201>) sol003PackageManagementSubscriptionController
+ .getSubscription(subscriptionId);
+
+ final HttpHeaders headers = buildHttpHeaders(response.getBody().getCallbackUri());
+
+ assertEquals(response.getBody().getFilter(), pkgmSubscriptionRequest.getFilter());
+ assertEquals(response.getHeaders(), headers);
+ assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
+ assertEquals(pkgmSubscriptionRequest.getFilter(), response.getBody().getFilter());
+ // Ensure CallBackUri is set to new URI
+ assertNotEquals(pkgmSubscriptionRequest.getCallbackUri(), response.getBody().getCallbackUri());
+ }
+
+ @Test
+ public void testFailGetSubscriptionWithInvalidSubscriptionId() {
+ final String invalidId = "invalidSubscriptionId";
+ mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + invalidId)).andExpect(method(HttpMethod.GET))
+ .andRespond(withStatus(HttpStatus.NOT_FOUND));
+ final ResponseEntity<?> response = sol003PackageManagementSubscriptionController.getSubscription(invalidId);
+ assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
+ assertTrue(response.getBody() instanceof ProblemDetails);
+ }
+
+ @Test
+ public void testSuccessGetSubscriptions() throws GeneralSecurityException {
+ final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
+ .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
+ mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + ID)).andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(gson.toJson(new NsdmSubscription().id(ID)), MediaType.APPLICATION_JSON));
+
+ sol003PackageManagementSubscriptionController.postSubscriptionRequest(pkgmSubscriptionRequest);
+ final ResponseEntity<List<InlineResponse201>> response =
+ sol003PackageManagementSubscriptionController.getSubscriptions();
+
+ final List<InlineResponse201> subscriptionsList = response.getBody();
+
+ assertEquals(Objects.requireNonNull(response.getBody()).get(0).getFilter(),
+ pkgmSubscriptionRequest.getFilter());
+ assertNotNull(subscriptionsList != null);
+ assertNotEquals('0', subscriptionsList.size());
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ }
+
+ @Test
+ public void testSuccessDeleteSubscriptionWithSubscriptionId() throws GeneralSecurityException {
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
+ final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
+ final String subscriptionId = pkgmSubscription.getId();
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
+ .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + subscriptionId)).andExpect(method(HttpMethod.DELETE))
+ .andRespond(withStatus(HttpStatus.NO_CONTENT));
+ mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + subscriptionId)).andExpect(method(HttpMethod.GET))
+ .andRespond(withSuccess(gson.toJson(new NsdmSubscription().id(subscriptionId)),
+ MediaType.APPLICATION_JSON));
+
+ final ResponseEntity<InlineResponse2002> responsePost =
+ (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+ .postSubscriptionRequest(pkgmSubscriptionRequest);
+
+ final ResponseEntity responseDelete =
+ sol003PackageManagementSubscriptionController.deleteSubscription(subscriptionId);
+
+ // Attempt to retrieve the subscription after delete
+ final ResponseEntity<InlineResponse2002> responseGetSubscription =
+ (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+ .getSubscription(subscriptionId);
+
+ assertEquals(HttpStatus.NOT_FOUND, responseGetSubscription.getStatusCode());
+ assertEquals(HttpStatus.NO_CONTENT, responseDelete.getStatusCode());
+ }
+
+ @Test
+ public void testDeleteSubscription_SubscripitonNotFoundInEtsiCatalogManager_SubscriptionDeletedFromLocalCache()
+ throws GeneralSecurityException {
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
+ final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
+ .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + ID)).andExpect(method(HttpMethod.DELETE))
+ .andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+ final ResponseEntity<InlineResponse2002> responsePost =
+ (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+ .postSubscriptionRequest(pkgmSubscriptionRequest);
+
+ final Cache cache =
+ cacheServiceProvider.getCache(PackageManagementConstants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE);
+ assertNotNull(cache.get(ID));
+
+ final ResponseEntity responseDelete = sol003PackageManagementSubscriptionController.deleteSubscription(ID);
+
+ assertEquals(HttpStatus.NO_CONTENT, responseDelete.getStatusCode());
+ assertNull(cache.get(ID));
+
+ }
+
+ @Test
+ public void testFailDeleteSubscriptionWithInvalidSubscriptionId() throws URISyntaxException, InterruptedException {
+ final ResponseEntity<Void> responseDelete = (ResponseEntity<Void>) sol003PackageManagementSubscriptionController
+ .deleteSubscription("invalidSubscriptionId");
+ assertEquals(HttpStatus.NOT_FOUND, responseDelete.getStatusCode());
+ }
+
+
+ @Test
+ public void testSuccessPostSubscriptionWithValidNotificationTypes() throws Exception {
+
+ final String file = getAbsolutePath("src/test/resources/requests/SubscriptionRequest.json");
+ final String json = new String(Files.readAllBytes(Paths.get(file)));
+ final PkgmSubscriptionRequest request = gson.fromJson(json, PkgmSubscriptionRequest.class);
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
+ .andExpect(MockRestRequestMatchers.content().json(gson.toJson(getEtsiCatalogPkgmSubscriptionRequest())))
+ .andRespond(withSuccess(gson.toJson(buildPkgmSubscription()), MediaType.APPLICATION_JSON));
+
+
+ final ResponseEntity<InlineResponse201> responseEntity =
+ testRestTemplate.postForEntity(LOCALHOST_URL + port + PACKAGE_MANAGEMENT_BASE_URL + "/subscriptions",
+ request, InlineResponse201.class);
+
+ assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
+ assertTrue(responseEntity.hasBody());
+ final InlineResponse201 actual = responseEntity.getBody();
+ assertEquals(ID, actual.getId());
+
+
+ }
+
+ private org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest getEtsiCatalogPkgmSubscriptionRequest() {
+ return new org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest()
+ .filter(new PkgmNotificationsFilter()
+ .addNotificationTypesItem(
+ PkgmNotificationsFilter.NotificationTypesEnum.VNFPACKAGEONBOARDINGNOTIFICATION)
+ .addVnfdIdItem("VNFDID").addVnfPkgIdItem("VNFPKGID")
+ .addOperationalStateItem(PkgmNotificationsFilter.OperationalStateEnum.ENABLED)
+ .addVnfProductsFromProvidersItem(new VnfProductsProviders().vnfProvider("EST")
+ .addVnfProductsItem(new VnfProducts().vnfProductName("VnfProducts")
+ .addVersionsItem(new Version().vnfSoftwareVersion("vnfSoftwareVersion")
+ .addVnfdVersionsItem("version1")))))
+ .callbackUri(_NOTIFICATION_CALLBACK_URI).authentication(
+ new SubscriptionAuthentication().addAuthTypeItem(SubscriptionAuthentication.AuthTypeEnum.BASIC)
+ .paramsBasic(new BasicAuth().userName("vnfm").password("password1$")));
+ }
+
+ private PkgmSubscriptionRequest buildPkgmSubscriptionRequest() {
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = new PkgmSubscriptionRequest();
+ final SubscriptionsFilter1 sub = buildSubscriptionsFilter();
+ final SubscriptionsAuthentication auth = new SubscriptionsAuthentication();
+ pkgmSubscriptionRequest.setFilter(sub);
+ pkgmSubscriptionRequest.setCallbackUri(msbEndpoint.toString());
+ pkgmSubscriptionRequest.setAuthentication(auth);
+ return pkgmSubscriptionRequest;
+ }
+
+ private SubscriptionsFilter1 buildSubscriptionsFilter() {
+ final SubscriptionsFilter1 sub = new SubscriptionsFilter1();
+ final List<String> vnfdIdList = new ArrayList<>();
+ final List<String> vnfPkgIdList = new ArrayList<>();
+ final List<SubscriptionsFilter1.NotificationTypesEnum> notificationTypes = new ArrayList<>();
+ final SubscriptionsFilterVnfProductsFromProviders subscriptionsFilterVnfProductsFromProviders =
+ new SubscriptionsFilterVnfProductsFromProviders();
+ final List<SubscriptionsFilterVnfProductsFromProviders> vnfProductsFromProviders = new ArrayList<>();
+
+ vnfProductsFromProviders.add(subscriptionsFilterVnfProductsFromProviders);
+ sub.setVnfdId(vnfdIdList);
+ sub.setNotificationTypes(notificationTypes);
+ sub.setVnfPkgId(vnfPkgIdList);
+ sub.setVnfProductsFromProviders(vnfProductsFromProviders);
+ return sub;
+ }
+
+ private PkgmSubscription buildPkgmSubscription() {
+ final PkgmSubscription pkgmSubscription = new PkgmSubscription();
+ final PkgmNotificationsFilter pkgmNotificationsFilter = new PkgmNotificationsFilter();
+ final LinkSelf linkSelf = new LinkSelf();
+
+ pkgmSubscription.setId(ID);
+ pkgmSubscription.setCallbackUri(msbEndpoint + "/" + pkgmSubscription.getId().toString());
+ pkgmSubscription.setFilter(pkgmNotificationsFilter);
+ pkgmSubscription.setLinks(linkSelf);
+ return pkgmSubscription;
+ }
+
+ private PkgmSubscriptionRequest postSubscriptionForTest() {
+ final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
+ final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
+
+ mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
+ .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
+ return pkgmSubscriptionRequest;
+ }
+
+ private HttpHeaders buildHttpHeaders(final String uri) throws URISyntaxException {
+ final HttpHeaders headers = new HttpHeaders();
+ final URI myUri = new URI(uri);
+ headers.setLocation(myUri);
+ return headers;
+ }
+
+ private String getAbsolutePath(final String path) {
+ final File file = new File(path);
+ return file.getAbsolutePath();
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/TestApplication.java b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/TestApplication.java
new file mode 100755
index 0000000000..152d3136f1
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/TestApplication.java
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnfmadapter.rest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.cache.annotation.EnableCaching;
+
+@EnableCaching
+@SpringBootApplication(scanBasePackages = {"org.onap.so"})
+@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class})
+public class TestApplication {
+
+ public static void main(final String[] args) {
+ new SpringApplication(TestApplication.class).run(args);
+ }
+
+}
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/application.yaml b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/application.yaml
new file mode 100644
index 0000000000..cdb6662191
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/application.yaml
@@ -0,0 +1,61 @@
+# Copyright © 2019 Nordix Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+spring:
+ security:
+ usercredentials:
+ - username: test
+ password: '$2a$12$Zi3AuYcZoZO/gBQyUtST2.F5N6HqcTtaNci2Et.ufsQhski56srIu'
+ role: BPEL-Client
+ - username: vnfm
+ password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+ role: BPEL-Client
+ main:
+ allow-bean-definition-overriding: true
+
+mso:
+ key: 07a7159d3bf51a0e53be7a8f89699be7
+
+aai:
+ auth: 2A11B07DB6214A839394AA1EC5844695F5114FC407FF5422625FB00175A3DCB8A1FF745F22867EFA72D5369D599BBD88DA8BED4233CF5586
+ endpoint: https://aai.onap:8443
+ version: v15
+
+sdc:
+ username: sdcUser
+ password: sdcPassword
+ key: adadadadad
+ endpoint: http://sdc.onap/1234A
+
+
+vnfmadapter:
+ endpoint: https://so-vnfm-adapter.onap:30406
+
+
+#Actuator
+management:
+ endpoints:
+ web:
+ base-path: /manage
+ exposure:
+ include: "*"
+ metrics:
+ se-global-registry: false
+ export:
+ prometheus:
+ enabled: true # Whether exporting of metrics to Prometheus is enabled.
+ step: 1m # Step size (i.e. reporting frequency) to use.
+
+etsi-catalog-manager:
+ vnfpkgm:
+ endpoint: http://msb-iag.onap:80/api/vnfpkgm/v1
diff --git a/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/requests/SubscriptionRequest.json b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/requests/SubscriptionRequest.json
new file mode 100644
index 0000000000..c38466f8e5
--- /dev/null
+++ b/adapters/etsi-sol003-adapter/etsi-sol003-package-management/etsi-sol003-package-management-adapter/src/test/resources/requests/SubscriptionRequest.json
@@ -0,0 +1,45 @@
+{
+ "filter":
+ {
+ "notificationTypes": [
+ "VnfPackageOnboardingNotification"
+ ],
+ "vnfProductsFromProviders": [
+ {
+ "vnfProvider": "EST",
+ "vnfProducts": [
+ {
+ "vnfProductName": "VnfProducts",
+ "versions": [
+ {
+ "vnfSoftwareVersion": "vnfSoftwareVersion",
+ "vnfdVersions": [
+ "version1"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "vnfdId": [
+ "VNFDID"
+ ],
+ "vnfPkgId": [
+ "VNFPKGID"
+ ],
+ "operationalState": ["ENABLED"]
+ },
+ "callbackUri": "http://so-vnfm-adapter:9093/api/vnfpkgm/v1/subscriptions",
+ "authentication":
+ {
+ "authType": [
+ "BASIC"
+ ],
+ "paramsBasic":
+ {
+ "userName": "vnfm",
+ "password": "vnfm"
+ }
+ }
+}