summaryrefslogtreecommitdiffstats
path: root/pomba/network-discovery/src/main/java
diff options
context:
space:
mode:
authorBrad Benesch <brad.benesch@amdocs.com>2018-07-12 14:26:26 -0400
committerBrad Benesch <brad.benesch@amdocs.com>2018-07-23 15:02:36 -0400
commit92c73de0f57aee2ada5f5c85b960c4c8ce7adf85 (patch)
tree66038237e070b13a82b1ceb7e7b0d98ba15fe576 /pomba/network-discovery/src/main/java
parent17ac3b089df1cc33ced623ab4150edcacd4381c6 (diff)
Initial code for network discovery microservice
Issue-ID: SDNC-317 Change-Id: I09d44de02283079471de0084da07793cb3d7820c Signed-off-by: Brad Benesch <brad.benesch@amdocs.com>
Diffstat (limited to 'pomba/network-discovery/src/main/java')
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java44
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java85
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/AuthorizationConfiguration.java41
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/CallbackConfiguration.java74
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java86
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/JerseyConfiguration.java66
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/WebConfiguration.java44
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringService.java35
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java299
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestService.java103
-rw-r--r--pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java132
11 files changed, 1009 insertions, 0 deletions
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java
new file mode 100644
index 0000000..eb2d9fd
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@SpringBootApplication
+@ComponentScan(basePackages = {"org.onap.sdnc.apps.pomba.networkdiscovery"})
+@EnableAsync
+@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
+public class Application extends SpringBootServletInitializer {
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(Application.class);
+ }
+
+ public static void main(String[] args) throws Exception {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java
new file mode 100644
index 0000000..6cc3592
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java
@@ -0,0 +1,85 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery;
+
+import javax.ws.rs.core.Response.Status;
+
+public class ApplicationException extends Exception {
+ public static enum Error {
+ GENERAL_FAILURE("NET.0001", "An error occurred: %s"),
+ MISSING_PARAM("NET.0002", "Missing required parameter %s"),
+ UNAUTHORIZED("NET.0003", "Unauthorized");
+
+ private final String responseCode;
+ private final String message;
+
+ private Error(String responseCode, String message) {
+ this.responseCode = responseCode;
+ this.message = message;
+ }
+
+ public String getMessage(Object... args) {
+ return String.format(this.message, args);
+ }
+
+ public String getResponseCode() {
+ return this.responseCode;
+ }
+ }
+
+ private static final long serialVersionUID = -4874149714911165454L;
+
+ private final Status httpStatus;
+ private String responseCode;
+
+ public ApplicationException(String message) {
+ this(message, Status.INTERNAL_SERVER_ERROR);
+ }
+
+ public ApplicationException(Error errorCode, Status httpStatus, Object... args) {
+ super(errorCode.getMessage(args));
+ if (httpStatus == null) {
+ throw new NullPointerException("httpStatus");
+ }
+
+ this.responseCode = errorCode.getResponseCode();
+ this.httpStatus = httpStatus;
+ }
+
+ public ApplicationException(String message, Status httpStatus) {
+ super(message);
+ if (httpStatus == null) {
+ throw new NullPointerException("httpStatus");
+ }
+ this.httpStatus = httpStatus;
+ }
+
+ public ApplicationException(String message, Exception cause) {
+ super(message, cause);
+ this.httpStatus = Status.INTERNAL_SERVER_ERROR;
+ }
+
+ public Status getHttpStatus() {
+ return this.httpStatus;
+ }
+
+ public String getResponseCode() {
+ return this.responseCode;
+ }
+
+}
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/AuthorizationConfiguration.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/AuthorizationConfiguration.java
new file mode 100644
index 0000000..5204a48
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/AuthorizationConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+
+package org.onap.sdnc.apps.pomba.networkdiscovery;
+
+import java.util.Base64;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AuthorizationConfiguration {
+
+ @Value("${basicAuth.username:admin}")
+ private String username;
+
+ @Value("${basicAuth.password:admin}")
+ private String password;
+
+ @Bean(name="basicAuthHeader")
+ public String getBasicAuthHeader() {
+ return "Basic " + Base64.getEncoder().encodeToString((this.username + ":" + this.password).getBytes());
+ }
+
+
+}
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/CallbackConfiguration.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/CallbackConfiguration.java
new file mode 100644
index 0000000..30d872f
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/CallbackConfiguration.java
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CallbackConfiguration {
+ /** Use same object mapper as embedded tomcat server */
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Value("${callback.keyStorePath:}")
+ private String keyStorePath;
+
+ @Value("${callback.keyStorePassword:}")
+ private String keyStorePassword;
+
+ @Value("${callback.connectionTimeout:5000}")
+ private int connectionTimeout;
+
+ @Value("${callback.readTimeout:60000}")
+ private int readTimeout;
+
+ @Value("${callback.username:}")
+ private String basicAuthUsername;
+
+ @Value("${callback.password:}")
+ private String basicAuthPassword;
+
+ @Bean(name="callbackClient")
+ public Client getClient() throws Exception {
+ ClientConfig configuration = new ClientConfig()
+ .property(ClientProperties.CONNECT_TIMEOUT, this.connectionTimeout)
+ .property(ClientProperties.READ_TIMEOUT, this.readTimeout)
+ .register(new JacksonJaxbJsonProvider(objectMapper, null));
+
+ // TODO set up SSL if configured
+// if (useSsl) {
+// setupSecureSocketLayerClientConfig(clientConfig);
+// }
+ // Finally, create and initialize our client...
+ Client client = ClientBuilder.newClient(configuration);
+
+ // ...and return it to the caller.
+ return client;
+ }
+
+
+}
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java
new file mode 100644
index 0000000..0a08577
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java
@@ -0,0 +1,86 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import org.onap.aai.restclient.client.RestClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+@Configuration
+public class EnricherConfiguration {
+ @Autowired
+ private Environment env;
+
+ @Value("${enricher.url}")
+ private String url;
+
+ @Value("${enricher.keyStorePath}")
+ private String keyStorePath;
+
+ @Value("${enricher.keyStorePassword}")
+ private String keyStorePassword;
+
+ @Value("${enricher.connectionTimeout:5000}")
+ private int connectionTimeout;
+
+ @Value("${enricher.readTimeout:60000}")
+ private int readTimeout;
+
+ @Bean(name="enricherClient")
+ public RestClient restClient() {
+ return new RestClient()
+ .validateServerHostname(false)
+ .validateServerCertChain(false)
+ .connectTimeoutMs(this.connectionTimeout)
+ .readTimeoutMs(this.readTimeout)
+ .clientCertFile(this.keyStorePath)
+ .clientCertPassword(this.keyStorePassword);
+ }
+
+ @Bean(name="enricherBaseUrl")
+ public String getURL() {
+ return this.url;
+ }
+
+ @Bean(name="enricherTypeURLs")
+ public Map<String, String> enricherTypeURLs() {
+
+ Map<String, String> result = new HashMap<>();
+ String types = this.env.getProperty("enricher.types");
+ if (types == null) {
+ return result;
+ }
+
+ StringTokenizer tokenizer = new StringTokenizer(types, ", ");
+ while (tokenizer.hasMoreTokens()) {
+ String type = tokenizer.nextToken();
+ String url = this.env.getProperty("enricher.type." + type + ".url");
+ result.put(type, url);
+ }
+
+ return result;
+ }
+
+
+}
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/JerseyConfiguration.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/JerseyConfiguration.java
new file mode 100644
index 0000000..5d93f64
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/JerseyConfiguration.java
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import java.util.logging.Logger;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.filter.LoggingFilter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.onap.sdnc.apps.pomba.networkdiscovery.service.rs.RestServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+@Component
+@ApplicationPath("/")
+public class JerseyConfiguration extends ResourceConfig {
+ private static final Logger log = Logger.getLogger(JerseyConfiguration.class.getName());
+
+ @Bean
+ @Primary
+ public ObjectMapper objectMapper() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
+ objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
+ return objectMapper;
+ }
+
+ @Autowired
+ public JerseyConfiguration() {
+ register(RestServiceImpl.class);
+ property(ServletProperties.FILTER_FORWARD_ON_404, true);
+ register(new LoggingFilter(log, true));
+ }
+
+ @Bean
+ public Client jerseyClient() {
+ return ClientBuilder.newClient(new ClientConfig());
+ }
+}
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/WebConfiguration.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/WebConfiguration.java
new file mode 100644
index 0000000..7a7bbd9
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/WebConfiguration.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@Configuration
+public class WebConfiguration {
+
+ @Bean
+ public WebMvcConfigurerAdapter forwardToIndex() {
+ return new WebMvcConfigurerAdapter() {
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/swagger").setViewName(
+ "redirect:/swagger/index.html");
+ registry.addViewController("/swagger/").setViewName(
+ "redirect:/swagger/index.html");
+ registry.addViewController("/docs").setViewName(
+ "redirect:/docs/html/index.html");
+ registry.addViewController("/docs/").setViewName(
+ "redirect:/docs/html/index.html");
+ }
+ };
+ }
+} \ No newline at end of file
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringService.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringService.java
new file mode 100644
index 0000000..e0f50f6
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringService.java
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery.service;
+
+import java.util.List;
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;
+import org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.NetworkDiscoveryResponse;
+
+public interface SpringService {
+
+ public NetworkDiscoveryResponse findbyResourceIdAndType(String transactionId,
+ String requestId,
+ String resourceType,
+ List<String> resourceIds,
+ String notificationURL,
+ String notificationAuthorization,
+ ONAPLogAdapter adapter)
+ throws ApplicationException;
+}
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java
new file mode 100644
index 0000000..3230a52
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java
@@ -0,0 +1,299 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery.service;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.io.IOException;
+import java.io.StringReader;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import javax.annotation.PreDestroy;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.restclient.client.RestClient;
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;
+import org.onap.logging.ref.slf4j.ONAPLogAdapter.RequestBuilder;
+import org.onap.logging.ref.slf4j.ONAPLogConstants.InvocationMode;
+import org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Attribute;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.DataQuality;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.NetworkDiscoveryNotification;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.NetworkDiscoveryResponse;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Resource;
+import org.onap.sdnc.apps.pomba.networkdiscovery.service.rs.RestService;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+@Service
+public class SpringServiceImpl implements SpringService {
+ private static final String ENRICHER_HEADER_APPLICATION = "X-FromAppId";
+ private static final String ENRICHER_HEADER_TRANSACTION = "X-TransactionId";
+
+ private static final int DEFAULT_WORKER_THREADS = 3;
+
+ private ExecutorService executor = Executors.newFixedThreadPool(
+ Integer.getInteger("discovery.threads", DEFAULT_WORKER_THREADS),
+ new ThreadFactoryBuilder().setNameFormat("discovery-worker-%d").build());
+
+ @Autowired
+ private RestClient enricherClient;
+
+ @Autowired
+ private String enricherBaseUrl;
+
+ @javax.annotation.Resource
+ private Client callbackClient;
+
+ @javax.annotation.Resource
+ private Map<String, String> enricherTypeURLs;
+
+ private DocumentBuilder parser;
+
+
+ public SpringServiceImpl() throws ParserConfigurationException {
+ this.parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ }
+
+ @Override
+ public NetworkDiscoveryResponse findbyResourceIdAndType(String transactionId,
+ String requestId,
+ String resourceType,
+ List<String> resourceIds,
+ String notificationURL,
+ String notificationAuthorization,
+ ONAPLogAdapter adapter) throws ApplicationException {
+
+ NetworkDiscoveryResponse response = new NetworkDiscoveryResponse();
+ response.setRequestId(requestId);
+
+ String enricherURL = this.enricherTypeURLs.get(resourceType);
+ // check if resourceType is supported
+ if (enricherURL == null) {
+ // don't know what to do with this - return empty response
+ response.setCode(Status.NO_CONTENT.getStatusCode());
+ response.setMessage("Unsupported resourceType " + resourceType);
+ response.setAckFinalIndicator(true);
+ return response;
+ }
+
+ // schedule discovery of specified resources
+ Runnable task = new ResourceTask(transactionId, requestId, resourceType, resourceIds,
+ notificationURL, notificationAuthorization, enricherURL, adapter);
+ this.executor.submit(task);
+
+ response.setCode(Status.ACCEPTED.getStatusCode());
+ response.setMessage(Status.ACCEPTED.getReasonPhrase());
+ response.setAckFinalIndicator(false);
+ return response;
+ }
+
+ @PreDestroy
+ public void shutdown() {
+ this.executor.shutdown();
+ }
+
+ private List<Attribute> toAttributeList(String xml) throws SAXException, IOException {
+ // TODO don't return raw A&AI attributes but coerce to swagger-defined enums
+ Document doc = this.parser.parse(new InputSource(new StringReader(xml)));
+ NodeList children = doc.getDocumentElement().getChildNodes();
+ List<Attribute> result = new ArrayList<>();
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Attribute attr = new Attribute();
+ attr.setName(((Element)child).getTagName());
+ attr.setValue(((Element)child).getTextContent());
+ attr.setDataQuality(DataQuality.ok());
+ result.add(attr);
+ }
+ }
+ return result;
+ }
+
+ private void sendNotification(String url, String authorization, Object notification, ONAPLogAdapter adapter) {
+
+ Invocation.Builder request = this.callbackClient
+ .target(url)
+ .request()
+ .accept(MediaType.TEXT_PLAIN_TYPE);
+
+ if (authorization != null) {
+ request.header(HttpHeaders.AUTHORIZATION, authorization);
+ }
+ Logger log = adapter.unwrap();
+ adapter.invoke(new RequestBuilderWrapper(request), InvocationMode.SYNCHRONOUS);
+ try {
+ // native client marshaller doesn't skip null fields
+ // so manually marshal notification to json
+
+ if (log.isDebugEnabled()) {
+ StringBuilder debugRequest = new StringBuilder("REQUEST:\n");
+ debugRequest.append("URL: ").append(url).append("\n");
+ debugRequest.append("Payload: ").append(notification).append("\n");
+// if (headers != null) {
+// debugRequest.append("Headers: ");
+// for (Entry<String, List<String>> header : headers.entrySet()) {
+// debugRequest.append("\n\t").append(header.getKey()).append(":");
+// for (String headerEntry : header.getValue()) {
+// debugRequest.append("\"").append(headerEntry).append("\" ");
+// }
+// }
+// }
+ log.debug(debugRequest.toString());
+ }
+
+ Response result = request.post(Entity.json(notification));
+
+ adapter.unwrap().info("request at url = {} resulted in http response: {}", url, result.getStatusInfo().getStatusCode() + " " + result.getStatusInfo().getReasonPhrase());
+
+ if (log.isDebugEnabled()) {
+ StringBuilder debugResponse = new StringBuilder("RESPONSE:\n");
+ debugResponse.append("Result: ").append(result.getStatus()).append("\n");
+ String content = result.hasEntity() ? result.getEntity().toString() : null;
+ if (result.getStatus() >= 300) {
+ debugResponse.append("Failure Cause: ").append(content).append("\n");
+ } else {
+ debugResponse.append("Payload: ").append(content).append("\n");
+ }
+ if (result.getHeaders() != null) {
+ debugResponse.append("Headers: ");
+ for (Entry<String, List<Object>> header : result.getHeaders().entrySet()) {
+ debugResponse.append("\n\t").append(header.getKey()).append(":");
+ for (Object headerEntry : header.getValue()) {
+ debugResponse.append("\"").append(headerEntry).append("\" ");
+ }
+ }
+ }
+ log.debug(debugResponse.toString());
+ }
+
+ } catch (Exception x) {
+ log.error("Error during {} operation to endpoint at url = {} with error = {}",
+ "POST", url, x.getLocalizedMessage());
+ }
+ }
+
+ private class ResourceTask implements Runnable {
+ private final String transactionId;
+ private final String requestId;
+ private final String resourceType;
+ private final List<String> resourceIds;
+ private final String notificationURL;
+ private final String notificationAuthorization;
+ private final String resourceURL;
+ private final ONAPLogAdapter adapter;
+
+ public ResourceTask(String transactionId,
+ String requestId,
+ String resourceType,
+ List<String> resourceIds,
+ String notificationURL,
+ String notificationAuthorization,
+ String resourceURL,
+ ONAPLogAdapter adapter) {
+ this.transactionId = transactionId;
+ this.requestId = requestId;
+ this.resourceType = resourceType;
+ this.resourceIds = resourceIds;
+ this.notificationURL = notificationURL;
+ this.notificationAuthorization = notificationAuthorization;
+ this.resourceURL = resourceURL;
+ this.adapter = adapter;
+ }
+
+ @Override
+ public void run() {
+ NetworkDiscoveryNotification notification = new NetworkDiscoveryNotification();
+ notification.setRequestId(this.requestId);
+
+ List<Resource> resources = null;
+ MessageFormat format = new MessageFormat(SpringServiceImpl.this.enricherBaseUrl + this.resourceURL);
+ MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
+ headers.add(ENRICHER_HEADER_APPLICATION, RestService.SERVICE_NAME);
+ headers.add(ENRICHER_HEADER_TRANSACTION, this.transactionId);
+ for (String resourceId : this.resourceIds) {
+ String url = format.format(new Object[] { resourceId });
+ OperationResult result = SpringServiceImpl.this.enricherClient.get(url, headers, MediaType.APPLICATION_XML_TYPE);
+
+ Resource resource = new Resource();
+ resource.setType(this.resourceType);
+ resource.setId(resourceId);
+ if (resources == null) {
+ resources = new ArrayList<>();
+ notification.setResources(resources);
+ }
+ resources.add(resource);
+
+ if (result.wasSuccessful()) {
+ resource.setDataQuality(DataQuality.ok());
+ try {
+ resource.setAttributeList(toAttributeList(result.getResult()));
+ } catch (Exception x) {
+ resource.setDataQuality(DataQuality.error(x.getMessage()));
+ }
+ }
+ else {
+ resource.setDataQuality(DataQuality.error(result.getFailureCause()));
+ }
+ }
+ notification.setCode(Status.OK.getStatusCode());
+ notification.setMessage(Status.OK.getReasonPhrase());
+ notification.setAckFinalIndicator(true);
+
+ // call client back with resource details
+ sendNotification(this.notificationURL, this.notificationAuthorization, notification, adapter);
+ }
+ }
+
+ private static class RequestBuilderWrapper implements RequestBuilder<RequestBuilderWrapper> {
+ private Invocation.Builder builder;
+ private RequestBuilderWrapper(Invocation.Builder builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public RequestBuilderWrapper setHeader(String name, String value) {
+ this.builder.header(name, value);
+ return this;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestService.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestService.java
new file mode 100644
index 0000000..57fbb53
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestService.java
@@ -0,0 +1,103 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery.service.rs;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import io.swagger.annotations.Authorization;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.NetworkDiscoveryResponse;
+
+
+@Api(protocols="http", tags= {"resource"})
+@Path("{version: v1}/network")
+@Produces(MediaType.APPLICATION_JSON)
+public interface RestService {
+
+ public static final String SERVICE_NAME = "network-discovery";
+
+ @GET
+ @Path("/resource")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ApiOperation(
+ value = "Get Network Information",
+ notes = "Retrieve information from primary data sources",
+ response = NetworkDiscoveryResponse.class,
+ authorizations = @Authorization("basicAuth")
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = 200, message = "Request has completed and no more information is forthcoming."),
+ @ApiResponse(code = 202, message = "Request has been accepted and more information will be posted to notificationURL."),
+ @ApiResponse(code = 400, message = "Missing mandatory field in the request or HTTP header."),
+ @ApiResponse(code = 404, message = "Requested resource was not found."),
+ @ApiResponse(code = 500, message = "Request failed due to internal error")
+ })
+ public Response findbyResourceIdAndType(@Context
+ HttpServletRequest request,
+
+ @PathParam("version")
+ @ApiParam(required=true, defaultValue="v1", allowableValues="v1")
+ String version,
+
+ @HeaderParam(HttpHeaders.AUTHORIZATION)
+ @ApiParam(hidden=true)
+ String authorization,
+
+ @HeaderParam(ONAPLogConstants.Headers.PARTNER_NAME)
+ @ApiParam(required=true)
+ String xFromAppId,
+
+ @HeaderParam(ONAPLogConstants.Headers.REQUEST_ID)
+ String xTransactionId,
+
+ @QueryParam("requestId")
+ @ApiParam(required=true)
+ String requestId,
+
+ @QueryParam("resourceType")
+ @ApiParam(required=true)
+ String resourceType,
+
+ @QueryParam("resourceId")
+ @ApiParam(required=true)
+ List<String> resourceIds,
+
+ @QueryParam("notificationURL")
+ @ApiParam(required=true)
+ String notificationURL) throws ApplicationException;
+
+} \ No newline at end of file
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java
new file mode 100644
index 0000000..94c7492
--- /dev/null
+++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java
@@ -0,0 +1,132 @@
+/*
+ * ============LICENSE_START===================================================
+ * Copyright (c) 2018 Amdocs
+ * ============================================================================
+ * 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.
+ * ============LICENSE_END=====================================================
+ */
+package org.onap.sdnc.apps.pomba.networkdiscovery.service.rs;
+
+import static org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException.Error.GENERAL_FAILURE;
+import static org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException.Error.MISSING_PARAM;
+import static org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException.Error.UNAUTHORIZED;
+
+import java.util.List;
+import java.util.UUID;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.Response.Status;
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.onap.logging.ref.slf4j.ONAPLogConstants.ResponseStatus;
+import org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException;
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.NetworkDiscoveryResponse;
+import org.onap.sdnc.apps.pomba.networkdiscovery.service.SpringService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RestServiceImpl implements RestService {
+
+ private static Logger log = LoggerFactory.getLogger(RestService.class);
+
+ @Autowired
+ private SpringService service;
+
+ @Resource(name="basicAuthHeader")
+ private String basicAuthHeader;
+
+ public RestServiceImpl() {
+ }
+
+ @Override
+ public Response findbyResourceIdAndType(HttpServletRequest request,
+ String version,
+ String authorization,
+ String fromAppId,
+ String transactionId,
+ String requestId,
+ String resourceType,
+ List<String> resourceIds,
+ String notificationURL) throws ApplicationException {
+
+ ONAPLogAdapter adapter = new ONAPLogAdapter(log);
+ adapter.getServiceDescriptor().setServiceName(SERVICE_NAME);
+ adapter.entering(request);
+ try {
+
+ if (version == null) {
+ // only unit tests can pass null here
+ // url matching will guarantee non-null in real server
+ version = "v1";
+ }
+
+ if (!this.basicAuthHeader.equals(authorization)) {
+ throw new ApplicationException(UNAUTHORIZED, Status.UNAUTHORIZED);
+ }
+ if ((fromAppId == null) || fromAppId.trim().isEmpty()) {
+ throw new ApplicationException(MISSING_PARAM, Status.BAD_REQUEST, ONAPLogConstants.Headers.PARTNER_NAME);
+ }
+ if (requestId == null || requestId.isEmpty()) {
+ throw new ApplicationException(MISSING_PARAM, Status.BAD_REQUEST, "requestId");
+ }
+ if (notificationURL == null) {
+ throw new ApplicationException(MISSING_PARAM, Status.BAD_REQUEST, "notificationURL");
+ }
+ if (resourceType == null || resourceType.isEmpty()) {
+ throw new ApplicationException(MISSING_PARAM, Status.BAD_REQUEST, "resourceType");
+ }
+ if (resourceIds == null || resourceIds.isEmpty()) {
+ throw new ApplicationException(MISSING_PARAM, Status.BAD_REQUEST, "resourceIds");
+ }
+
+ if (transactionId == null || transactionId.isEmpty()) {
+ transactionId = UUID.randomUUID().toString();
+ log.debug("transactionId is missing; using newly generated value: " + transactionId);
+ }
+
+ // just reuse received Authorization header in callback
+ NetworkDiscoveryResponse response = this.service.findbyResourceIdAndType(transactionId,
+ requestId, resourceType, resourceIds, notificationURL, authorization, adapter);
+ adapter.getResponseDescriptor().setResponseStatus(ResponseStatus.COMPLETED);
+ return Response.ok(response).build();
+
+ } catch (ApplicationException x) {
+ adapter.getResponseDescriptor()
+ .setResponseCode(x.getResponseCode())
+ .setResponseStatus(ResponseStatus.ERROR);
+ log.error(x.getMessage(), x);
+ ResponseBuilder builder = Response.status(x.getHttpStatus()).entity(x.getMessage());
+ if (authorization == null) {
+ builder.header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"network-discovery\"");
+ }
+ return builder.build();
+
+ } catch (Exception x) {
+ adapter.getResponseDescriptor()
+ .setResponseCode(GENERAL_FAILURE.getResponseCode())
+ .setResponseStatus(ResponseStatus.ERROR);
+ log.error(GENERAL_FAILURE.getMessage(x), x);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(x.getMessage()).build();
+ } finally {
+ adapter.exiting();
+ }
+
+ }
+
+}