major re-structuring 49/1049/3
authorSerban Jora <sj2381@att.com>
Fri, 23 Feb 2018 12:54:53 +0000 (07:54 -0500)
committerSerban Jora <sj2381@att.com>
Fri, 23 Feb 2018 20:43:48 +0000 (15:43 -0500)
Separates between federation and local interface with respect to
network configuration, authorization and availabl REST API.
Switches to a spring application composition based on explicit
configuration rather than component scanning.
Moves to CDS 1.13
(fixed Chris remarks)

Change-Id: I676fe4b45abdcbe081742dcceb6a2e52b9361065
Signed-off-by: Serban Jora <sj2381@att.com>
Issue-ID: ACUMOS-276

76 files changed:
gateway/application-acumosa.properties [new file with mode: 0644]
gateway/application-acumosb.properties [new file with mode: 0644]
gateway/application-gateway.properties
gateway/application-test.properties [new file with mode: 0644]
gateway/application.properties
gateway/pom.xml
gateway/src/main/java/org/acumos/federation/gateway/Application.java
gateway/src/main/java/org/acumos/federation/gateway/adapter/PeerGateway.java
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/ONAP.java
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/ONAPAdapterCondition.java
gateway/src/main/java/org/acumos/federation/gateway/cds/PeerStatus.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/cds/SubscriptionScope.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/cds/ValidationStatus.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/common/API.java
gateway/src/main/java/org/acumos/federation/gateway/common/AbstractClient.java [moved from gateway/src/main/java/org/acumos/federation/gateway/service/impl/AbstractClient.java with 95% similarity]
gateway/src/main/java/org/acumos/federation/gateway/common/Clients.java [moved from gateway/src/main/java/org/acumos/federation/gateway/service/impl/Clients.java with 54% similarity]
gateway/src/main/java/org/acumos/federation/gateway/common/FederationClient.java [moved from gateway/src/main/java/org/acumos/federation/gateway/service/impl/FederationClient.java with 61% similarity]
gateway/src/main/java/org/acumos/federation/gateway/common/JSONTags.java
gateway/src/main/java/org/acumos/federation/gateway/common/JsonResponse.java
gateway/src/main/java/org/acumos/federation/gateway/config/AdapterCondition.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/AdapterCondition.java with 97% similarity]
gateway/src/main/java/org/acumos/federation/gateway/config/AdapterConfiguration.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/config/FederationConfiguration.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/config/FederationInterfaceConfiguration.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/config/GatewayCondition.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/GatewayCondition.java with 97% similarity]
gateway/src/main/java/org/acumos/federation/gateway/config/GatewayConfiguration.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/config/InterfaceConfiguration.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/HttpClientConfiguration.java with 55% similarity]
gateway/src/main/java/org/acumos/federation/gateway/config/InterfaceConfigurationBuilder.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/HttpClientConfigurationBuilder.java with 68% similarity]
gateway/src/main/java/org/acumos/federation/gateway/config/LocalConfiguration.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/config/LocalInterfaceConfiguration.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/GatewayConfiguration.java with 78% similarity]
gateway/src/main/java/org/acumos/federation/gateway/controller/CatalogController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerCatalogController.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerPingController.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerSubscriptionController.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeersController.java [moved from gateway/src/main/java/org/acumos/federation/gateway/controller/PeerController.java with 72% similarity]
gateway/src/main/java/org/acumos/federation/gateway/controller/PingController.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/controller/RegistrationController.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/security/AuthenticationConfiguration.java [moved from gateway/src/main/java/org/acumos/federation/gateway/security/X509AuthenticationFilter.java with 56% similarity]
gateway/src/main/java/org/acumos/federation/gateway/security/Priviledge.java
gateway/src/main/java/org/acumos/federation/gateway/security/X509ResourceFilter.java.noneed [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/LocalWatchService.java [moved from gateway/src/main/java/org/acumos/federation/gateway/util/LocalWatchService.java with 96% similarity]
gateway/src/main/java/org/acumos/federation/gateway/service/PeerService.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/AbstractServiceImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/AbstractServiceLocalImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/CatalogServiceImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/CatalogServiceLocalImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/PeerServiceImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/PeerServiceLocalImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/PeerSubscriptionServiceImpl.java
gateway/src/main/java/org/acumos/federation/gateway/task/PeerSubscriptionTask.java [moved from gateway/src/main/java/org/acumos/federation/gateway/task/PeerCommunicationTask.java with 59% similarity]
gateway/src/main/java/org/acumos/federation/gateway/task/PeerSubscriptionTaskScheduler.java [moved from gateway/src/main/java/org/acumos/federation/gateway/task/PeerCommunicationTaskScheduler.java with 62% similarity]
gateway/src/main/java/org/acumos/federation/gateway/task/TaskConfiguration.java [new file with mode: 0644]
gateway/src/main/resources/application-gateway.properties [deleted file]
gateway/src/main/resources/application.properties [deleted file]
gateway/src/main/resources/logback.xml
gateway/src/main/resources/peerssubscriptions.json [deleted file]
gateway/src/main/resources/server-keystore.jks [deleted file]
gateway/src/main/resources/server-public.cer [deleted file]
gateway/src/main/resources/server-truststore.jks [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/ControllerTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/PeerGatewayTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/TaskTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/TestAdapter.java [moved from gateway/src/main/java/org/acumos/federation/gateway/adapter/Ghost.java with 68% similarity]
gateway/src/test/java/org/acumos/federation/gateway/test/TestAdapterCondition.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/GhostAdapterCondition.java with 82% similarity]
gateway/src/test/java/org/acumos/federation/gateway/test/TestAdapterConfiguration.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/FederationClientConfiguration.java with 65% similarity]
gateway/src/test/resources/acumosa-peers.json
gateway/src/test/resources/acumosb-peers.json
gateway/src/test/resources/application-acumosa.properties
gateway/src/test/resources/application-acumosb.properties
gateway/src/test/resources/docker-compose-test.yml
gateway/src/test/resources/docker-compose.yml
gateway/src/test/resources/mockPeerSolutionRevisionArtifactsResponse.json
gateway/src/test/resources/mockPeerSolutionRevisionsResponse.json
gateway/src/test/resources/mockPeerSolutionsResponse.json
gateway/src/test/resources/task-test-peers.json
gateway/src/test/resources/test-peers.json
pom.xml

diff --git a/gateway/application-acumosa.properties b/gateway/application-acumosa.properties
new file mode 100644 (file)
index 0000000..108e0df
--- /dev/null
@@ -0,0 +1,27 @@
+#pretend we are an adapter so that we can use local peer config
+federation.instance=adapter
+federation.instance.name=test
+#federation.instance=gateway
+#federation.instance.name=acumosa
+
+federation.address = 10.0.2.67
+federation.server.port = 9001
+federation.ssl.key-store = classpath:acumosa.pkcs12
+federation.ssl.key-store-password = acumosa
+federation.ssl.key-store-type = PKCS12
+federation.ssl.key-password = acumosa
+federation.ssl.trust-store = classpath:acumosTrustStore.jks
+federation.ssl.trust-store-password = acumos
+
+local.address = 127.0.0.1
+local.server.port = 9011
+local.ssl.key-store = classpath:acumosa.pkcs12
+local.ssl.key-store-password = acumosa
+local.ssl.key-store-type = PKCS12
+local.ssl.key-password = acumosa
+local.ssl.trust-store = classpath:acumosTrustStore.jks
+local.ssl.trust-store-password = acumos
+
+#replace 
+peersLocal.source=classpath:/acumosa-peers.json
+catalogLocal.source=classpath:/acumosa-catalog.json
diff --git a/gateway/application-acumosb.properties b/gateway/application-acumosb.properties
new file mode 100644 (file)
index 0000000..c15e0d4
--- /dev/null
@@ -0,0 +1,27 @@
+#pretend we are an adapter so that we can use local peer config
+federation.instance=adapter
+federation.instance.name=test
+#federation.instance=gateway
+#federation.instance.name=acumosb
+
+federation.address = 10.0.2.67
+federation.server.port = 9002
+federation.ssl.key-store = classpath:acumosb.pkcs12
+federation.ssl.key-store-password = acumosb
+federation.ssl.key-store-type = PKCS12
+federation.ssl.key-password = acumosb
+federation.ssl.trust-store = classpath:acumosTrustStore.jks
+federation.ssl.trust-store-password = acumos
+
+local.address = 127.0.0.1
+local.server.port = 9022
+local.ssl.key-store = classpath:acumosb.pkcs12
+local.ssl.key-store-password = acumosb
+local.ssl.key-store-type = PKCS12
+local.ssl.key-password = acumosb
+local.ssl.trust-store = classpath:acumosTrustStore.jks
+local.ssl.trust-store-password = acumos
+
+peersLocal.source=classpath:/acumosb-peers.json
+catalogLocal.source=classpath:/acumosb-catalog.json
+
index dc7994e..cae584f 100644 (file)
@@ -4,6 +4,10 @@ federation.instance=gateway
 federation.instance.name=Acumos
 federation.operator=d468656f-57d0-46e3-9f94-7ffa4f66dc03
 
+federation.server.port = 9111
+federation.address = 10.0.2.67
+local.server.port = 9222
+
 # CDMS REST endpoints are protected by HTTP Basic Authentication
 #Common Data Source Configuration
 cdms.client.url=http://localhost:8002/ccds
diff --git a/gateway/application-test.properties b/gateway/application-test.properties
new file mode 100644 (file)
index 0000000..128d226
--- /dev/null
@@ -0,0 +1,14 @@
+# REST endpoint configuration; i.e., where this server listens
+federation.server.port = 9191
+federation.address = 10.0.2.67
+local.server.port = 9292
+
+
+#Instance of this component could be gateway or adapter
+#Based on the value configured, the behavior of this instance will vary.
+federation.instance=adapter
+federation.instance.name=test
+
+#local config
+peersLocal.source=file:///home/jora/src/acumos/gerrit/federation-latest/gateway/src/test/resources/acumosa-peers.json
+catalogLocal.source=file:///home/jora/src/acumos/gerrit/federation-latest/gateway/src/test/resources/acumosa-catalog.json
index 5144396..4c5d9f2 100644 (file)
@@ -1,6 +1,6 @@
 # REST endpoint configuration; i.e., where this server listens
 #server.address=127.0.0.1
-server.port=8084
+#server.port=9084
 server.contextPath=/
 
 #Task executor that run every x seconds
index a2df3e6..7cac725 100644 (file)
@@ -5,14 +5,14 @@
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.acumos.federation</groupId>
        <artifactId>gateway</artifactId>
-       <version>1.0.0-SNAPSHOT</version>
+       <version>1.1.0-SNAPSHOT</version>
        <name>Federation Gateway</name>
        <description>Federated Acumos Interface for inter-acumos and ONAP communication</description>
 
        <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
-               <version>1.5.4.RELEASE</version>
+               <version>1.5.10.RELEASE</version>
                <!-- silence warning about parent relative path -->
                <relativePath />
        </parent>
@@ -24,7 +24,6 @@
                <start-class>org.acumos.federation.gateway.Application</start-class>
                <!-- Jenkins invokes mvn with argument -Dbuild.number=${BUILD_NUMBER} -->
                <build.number>0</build.number>
-               <!-- tests require database to be running -->
                <skipTests>false</skipTests>
                <!-- dependencies versions -->
                <slf4j.version>1.7.25</slf4j.version>
@@ -56,7 +55,7 @@
                <dependency>
                        <groupId>org.acumos.common-dataservice</groupId>
                        <artifactId>cmn-data-svc-client</artifactId>
-                       <version>1.12.0</version>
+                       <version>1.13.1</version>
                </dependency>
                <dependency>
                        <groupId>org.json</groupId>
                                                                <assembly>
                                                                        <inline>
                                                                                <files>
-                                                                                       <file>
-                                                                                               <source>application.properties.template</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>application.properties</destName>
-                                                                                       </file>
-                                                                                       <file>
-                                                                                               <source>src/test/resources/ist-acumosa.pkcs12</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>ist-acumosa.pkcs12</destName>
-                                                                                       </file>
-                                                                                       <file>
-                                                                                               <source>src/test/resources/ist-acumosb.pkcs12</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>ist-acumosb.pkcs12</destName>
-                                                                                       </file>
-                                                                                       <file>
-                                                                                               <source>src/test/resources/acumosTrustStore.jks</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>acumosTrustStore.jks</destName>
-                                                                                       </file>
                                                                                        <file>
                                                                                                <source>target/${project.artifactId}-${project.version}.${project.packaging}</source>
                                                                                                <outputDirectory />
                                                                <!-- This is the same CMD used in a Dockerfile -->
                                                                <cmd>
                                                                        <!-- CDATA prevents Eclipse formatter from breaking line -->
-                                                                       <shell><![CDATA[cd /maven; java -Djavax.net.debug=ssl -Djava.security.egd=file:/dev/./urandom -jar ${project.artifactId}-${project.version}.${project.packaging}]]></shell>
+                                                                       <shell><![CDATA[cd /maven; java -Xms128m -Xmx512m -Djava.security.egd=file:/dev/./urandom -jar ${project.artifactId}-${project.version}.${project.packaging}]]></shell>
                                                                </cmd>
                                                        </build>
                                                </image>
                                                <image>
-                                                       <!-- Specify a tag to avoid default tag "latest" -->
                                                        <name>federation-gateway-test:${project.version}</name>
                                                        <build>
                                                                <from>frolvlad/alpine-oraclejdk8:slim</from>
                                                                <tags>
-                                                                       <!-- Add tag with build number -->
                                                                        <tag>${project.version}-b${build.number}</tag>
                                                                </tags>
                                                                <assembly>
                                                                        <inline>
                                                                                <files>
                                                                                        <file>
-                                                                                               <source>application.properties.template</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>application.properties</destName>
-                                                                                       </file>
-                                                                                       <!-- need the following two for server config -->
-                                                                                       <file>
-                                                                                               <source>src/test/resources/acumosa.pkcs12</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>acumosa.pkcs12</destName>
-                                                                                       </file>
-                                                                                       <file>
-                                                                                               <source>src/test/resources/acumosb.pkcs12</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>acumosb.pkcs12</destName>
-                                                                                       </file>
-                                                                                       <file>
-                                                                                               <source>src/test/resources/acumosTrustStore.jks</source>
-                                                                                               <outputDirectory />
-                                                                                               <destName>acumosTrustStore.jks</destName>
-                                                                                       </file>
-                                                                                       <file>
-                                                                                               <source>target/${project.artifactId}-${project.version}.${project.packaging}</source>
+                                                                                               <source>target/${project.artifactId}-${project.version}.${project.packaging}.original</source>
                                                                                                <outputDirectory />
+                                                                                               <!-- <destName>target/${project.artifactId}-${project.version}.${project.packaging}</destName> -->
                                                                                        </file>
                                                                                        <file>
                                                                                                <source>target/${project.artifactId}-${project.version}-tests.${project.packaging}</source>
                                                                                </files>
                                                                                <fileSets>
                                                                                        <fileSet>
-                                                                                               <directory>${project.build.directory}/deps/</directory>
+                                                                                               <!-- <directory>${project.build.directory}/deps/</directory> -->
+                                                                                               <directory>target/deps/</directory>
                                                                                                <outputDirectory>/libs/</outputDirectory>
                                                                                                <includes>
                                                                                                        <include>*</include>
                                                                </assembly>
                                                                <cmd>
                                                                        <!-- CDATA prevents Eclipse formatter from breaking line -->
-                                                                       <shell><![CDATA[cd /maven; java -Xms128m -Xmx512m -cp ${project.artifactId}-${project.version}.${project.packaging}:${project.artifactId}-${project.version}-tests.${project.packaging}:/libs/* -Djavax.net.debug=ssl:handshake -Djavax.net.ssl.trustStore=/app/certs/acumosTrustStore.jks -Djavax.net.ssl.trustStorePassword=acumos -Djava.security.egd=file:/dev/./urandom org.springframework.boot.loader.PropertiesLauncher]]></shell>
-                                                                       <!-- <shell>cd /maven; java -cp ${project.artifactId}-${project.version}.${project.packaging}:${project.artifactId}-${project.version}-tests.${project.packaging}:/libs/* 
-                                                                               -Djavax.net.debug=ssl:handshake -Djavax.net.ssl.trustStore=acumosTrustStore.jks 
-                                                                               -Djavax.net.ssl.trustStorePassword=acumos -Djava.security.egd=file:/dev/./urandom 
-                                                                               org.springframework.boot.loader.PropertiesLauncher</shell> -->
+                                                                       <shell><![CDATA[cd /maven; java -Xms128m -Xmx512m -cp ${project.artifactId}-${project.version}.${project.packaging}.original:${project.artifactId}-${project.version}-tests.${project.packaging}:/libs/* -Djava.security.egd=file:/dev/./urandom org.springframework.boot.loader.PropertiesLauncher]]></shell>
                                                                </cmd>
                                                        </build>
                                                </image>
index a1d3b05..14edee0 100644 (file)
 
 package org.acumos.federation.gateway;
 
+import java.io.IOException;
+
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.config.GatewayConfiguration;
+import org.acumos.federation.gateway.config.AdapterConfiguration;
+import org.acumos.federation.gateway.config.LocalConfiguration;
+import org.acumos.federation.gateway.config.FederationConfiguration;
 
-import org.springframework.beans.BeansException;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -34,22 +39,62 @@ import org.springframework.context.ApplicationContextAware;
 import org.springframework.core.env.ConfigurableEnvironment;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
+import org.springframework.boot.Banner;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+import org.springframework.web.context.support.StandardServletEnvironment;
+
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 /**
  * 
- *
+ * Configuration classes are also Conponents so they are subject to Component scanning.
  */
+@SpringBootApplication
 @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,
                DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
-@SpringBootApplication
-public class Application implements ApplicationContextAware {
+@EnableConfigurationProperties
+@ComponentScan(basePackages = "org.acumos.federation",
+                                                        useDefaultFilters = false,
+                                                        includeFilters =
+                                                               @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,
+                                                                                                                                                       classes={org.acumos.federation.gateway.config.GatewayConfiguration.class,
+                                                                                                                                                                                        org.acumos.federation.gateway.config.AdapterConfiguration.class}))
+public class Application {
 
        private final static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(Application.class);
 
+       /**
+        * We should be able to swap the LocalConfiguration in the case of adapters.
+        */
+       public static void main(String[] args) throws Exception {
+    
+               SpringApplicationBuilder gatewayBuilder =
+                       new SpringApplicationBuilder(Application.class)
+                                                                                       .bannerMode(Banner.Mode.OFF)
+                                                                                       .web(false);
+               ApplicationContext fedCtx =
+                               gatewayBuilder.child(FederationConfiguration.class)
+                                                                                       .bannerMode(Banner.Mode.OFF)
+                                                                                       .web(true)
+                                                                                       .run(args);
+               ApplicationContext localCtx =
+                               gatewayBuilder.child(LocalConfiguration.class)
+                                                                                       .bannerMode(Banner.Mode.OFF)
+                                                                                       .web(true)
+                                                                                       .run(args);
+
+       }
+
        public static final String CONFIG_ENV_VAR_NAME = "SPRING_APPLICATION_JSON";
 
-       public static void main(String[] args) throws Exception {
+       private static void checkEnvironmentConfig() throws IOException {
                final String springApplicationJson = System.getenv(CONFIG_ENV_VAR_NAME);
                if (springApplicationJson != null && springApplicationJson.contains("{")) {
                        final ObjectMapper mapper = new ObjectMapper();
@@ -59,12 +104,5 @@ public class Application implements ApplicationContextAware {
                } else {
                        logger.warn("main: no configuration found in environment {}", CONFIG_ENV_VAR_NAME);
                }
-               SpringApplication.run(Application.class, args);
        }
-
-       @Override
-       public void setApplicationContext(ApplicationContext context) throws BeansException {
-               ((ConfigurableEnvironment) context.getEnvironment()).setActiveProfiles("src");
-       }
-
 }
index ee95bf3..c0f93b6 100644 (file)
@@ -36,18 +36,24 @@ import org.acumos.cds.domain.MLPPeer;
 import org.acumos.cds.domain.MLPPeerSubscription;
 import org.acumos.cds.domain.MLPSolution;
 import org.acumos.cds.domain.MLPSolutionRevision;
-import org.acumos.federation.gateway.common.GatewayCondition;
+
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.config.GatewayCondition;
 import org.acumos.federation.gateway.event.PeerSubscriptionEvent;
-import org.acumos.federation.gateway.service.impl.Clients;
-import org.acumos.federation.gateway.service.impl.FederationClient;
+import org.acumos.federation.gateway.common.Clients;
+import org.acumos.federation.gateway.common.FederationClient;
 import org.acumos.federation.gateway.util.Errors;
 import org.acumos.federation.gateway.util.Utils;
+import org.acumos.federation.gateway.cds.SubscriptionScope;
+
 import org.acumos.nexus.client.data.UploadArtifactInfo;
+
 import org.springframework.beans.factory.BeanInitializationException;
 import org.springframework.beans.factory.annotation.Autowired;
 //import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.Profile;
 import org.springframework.context.annotation.Conditional;
 import org.springframework.context.event.EventListener;
 import org.springframework.core.env.Environment;
@@ -58,33 +64,38 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.client.HttpStatusCodeException;
 
 @Component("peergateway")
-// @Scope("singleton")
-@ConfigurationProperties(prefix = "federation")
-@Conditional(GatewayCondition.class)
+@Scope("singleton")
+@Conditional({GatewayCondition.class})
 public class PeerGateway {
 
-       private final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PeerGateway.class);
+       private final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(PeerGateway.class);
        private TaskExecutor taskExecutor;
        @Autowired
        private Environment env;
        @Autowired
        private Clients clients;
 
+       public PeerGateway() {
+               log.trace(EELFLoggerDelegate.debugLogger, "PeerGateway::new");
+       }
+
        @PostConstruct
        public void initGateway() {
-               logger.debug(EELFLoggerDelegate.debugLogger, "initPeerGateway");
+               log.trace(EELFLoggerDelegate.debugLogger, "initPeerGateway");
 
                /* make sure an operator was specified and that it is a declared user */
                if (null == this.env.getProperty("federation.operator")) {
                        throw new BeanInitializationException("Missing 'federation.operator' configuration");
-               } else {
+               } 
+               else {
                        try {
-                               if (null == this.clients.getClient().getUser(this.env.getProperty("federation.operator"))) {
-                                       logger.warn(EELFLoggerDelegate.errorLogger,
+                               if (null == this.clients.getCDSClient().getUser(this.env.getProperty("federation.operator"))) {
+                                       log.warn(EELFLoggerDelegate.errorLogger,
                                                        "'federation.operator' does not point to an existing user");
                                }
-                       } catch (/* HttpStatusCode */Exception dx) {
-                               logger.warn(EELFLoggerDelegate.errorLogger, "failed to verify 'federation.operator' value", dx);
+                       }
+                       catch (/* HttpStatusCode */Exception dx) {
+                               log.warn(EELFLoggerDelegate.errorLogger, "failed to verify 'federation.operator' value", dx);
                        }
                }
 
@@ -95,12 +106,12 @@ public class PeerGateway {
                ((ThreadPoolTaskExecutor) this.taskExecutor).initialize();
 
                // Done
-               logger.debug(EELFLoggerDelegate.debugLogger, "PeerGateway available");
+               log.trace(EELFLoggerDelegate.debugLogger, "PeerGateway available");
        }
 
        @PreDestroy
        public void cleanupGateway() {
-               logger.debug(EELFLoggerDelegate.debugLogger, "PeerGateway destroyed");
+               log.trace(EELFLoggerDelegate.debugLogger, "PeerGateway destroyed");
        }
 
        protected String getOwnerId(MLPPeerSubscription theSubscription/*
@@ -112,7 +123,7 @@ public class PeerGateway {
 
        @EventListener
        public void handlePeerSubscriptionUpdate(PeerSubscriptionEvent theEvent) {
-               logger.info(EELFLoggerDelegate.debugLogger, "received peer subscription update event " + theEvent);
+               log.info(EELFLoggerDelegate.debugLogger, "received peer subscription update event {}", theEvent);
                taskExecutor.execute(
                                new PeerGatewayUpdateTask(theEvent.getPeer(), theEvent.getSubscription(), theEvent.getSolutions()));
        }
@@ -136,8 +147,8 @@ public class PeerGateway {
 
                public void run() {
 
-                       logger.info(EELFLoggerDelegate.debugLogger, "Received peer " + this.peer + " solutions: " + this.solutions);
-                       ICommonDataServiceRestClient cdsClient = PeerGateway.this.clients.getClient();
+                       log.info(EELFLoggerDelegate.debugLogger, "Received peer " + this.peer + " solutions: " + this.solutions);
+                       ICommonDataServiceRestClient cdsClient = PeerGateway.this.clients.getCDSClient();
                        for (MLPSolution peerSolution : this.solutions) {
                                // Check if the Model already exists in the Local Acumos
                                MLPSolution localSolution = null;
@@ -145,7 +156,7 @@ public class PeerGateway {
                                        localSolution = cdsClient.getSolution(peerSolution.getSolutionId());
                                } catch (HttpStatusCodeException x) {
                                        if (!Errors.isCDSNotFound(x)) {
-                                               logger.warn(EELFLoggerDelegate.errorLogger, "Failed to check if solution with id "
+                                               log.warn(EELFLoggerDelegate.errorLogger, "Failed to check if solution with id "
                                                                + peerSolution.getSolutionId() + " exists locally, skipping for now", x);
                                                continue;
                                        }
@@ -153,7 +164,7 @@ public class PeerGateway {
 
                                try {
                                        if (localSolution == null) {
-                                               logger.info(EELFLoggerDelegate.debugLogger, "Solution Id : " + peerSolution.getSolutionId()
+                                               log.info(EELFLoggerDelegate.debugLogger, "Solution Id : " + peerSolution.getSolutionId()
                                                                + " does not exists locally, adding it to local catalog ");
                                                localSolution = createMLPSolution(peerSolution, cdsClient);
                                        } else {
@@ -163,14 +174,14 @@ public class PeerGateway {
                                        mapSolution(localSolution, cdsClient);
                                } catch (Exception x) {
                                        x.printStackTrace();
-                                       logger.warn(EELFLoggerDelegate.debugLogger,
+                                       log.warn(EELFLoggerDelegate.debugLogger,
                                                        "Mapping of acumos solution failed for: " + peerSolution, x);
                                }
                        }
                }
 
                private MLPSolution createMLPSolution(MLPSolution peerMLPSolution, ICommonDataServiceRestClient cdsClient) {
-                       logger.info(EELFLoggerDelegate.debugLogger,
+                       log.info(EELFLoggerDelegate.debugLogger,
                                        "Creating Local MLP Solution for peer solution " + peerMLPSolution);
                        MLPSolution localSolution = new MLPSolution();
                        localSolution.setSolutionId(peerMLPSolution.getSolutionId());
@@ -190,12 +201,14 @@ public class PeerGateway {
                        try {
                                cdsClient.createSolution(localSolution);
                                return localSolution;
-                       } catch (HttpStatusCodeException restx) {
-                               logger.error(EELFLoggerDelegate.debugLogger,
+                       }
+                       catch (HttpStatusCodeException restx) {
+                               log.error(EELFLoggerDelegate.errorLogger,
                                                "createSolution CDS call failed. CDS message is " + restx.getResponseBodyAsString(), restx);
                                return null;
-                       } catch (Exception x) {
-                               logger.error(EELFLoggerDelegate.debugLogger, "createMLPSolution unexpected failure", x);
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "createMLPSolution unexpected failure", x);
                                return null;
                        }
                }
@@ -214,13 +227,15 @@ public class PeerGateway {
                        try {
                                cdsClient.createSolutionRevision(solutionRevision);
                                return solutionRevision;
-                       } catch (HttpStatusCodeException restx) {
-                               logger.error(EELFLoggerDelegate.debugLogger,
+                       }
+                       catch (HttpStatusCodeException restx) {
+                               log.error(EELFLoggerDelegate.errorLogger,
                                                "createSolutionRevision CDS call failed. CDS message is " + restx.getResponseBodyAsString(),
                                                restx);
                                return null;
-                       } catch (Exception x) {
-                               logger.error(EELFLoggerDelegate.debugLogger, "createSolutionRevision unexpected failure", x);
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "createSolutionRevision unexpected failure", x);
                                return null;
                        }
                }
@@ -244,12 +259,14 @@ public class PeerGateway {
                                cdsClient.createArtifact(artifact);
                                cdsClient.addSolutionRevisionArtifact(theSolutionId, theRevisionId, mlpArtifact.getArtifactId());
                                return artifact;
-                       } catch (HttpStatusCodeException restx) {
-                               logger.error(EELFLoggerDelegate.debugLogger,
+                       }
+                       catch (HttpStatusCodeException restx) {
+                               log.error(EELFLoggerDelegate.errorLogger,
                                                "createArtifact CDS call failed. CDS message is " + restx.getResponseBodyAsString(), restx);
                                return null;
-                       } catch (Exception x) {
-                               logger.error(EELFLoggerDelegate.debugLogger, "createArtifact unexpected failure", x);
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "createArtifact unexpected failure", x);
                                return null;
                        }
                }
@@ -272,7 +289,7 @@ public class PeerGateway {
 
                private MLPSolution updateMLPSolution(MLPSolution peerMLPSolution, MLPSolution localMLPSolution,
                                ICommonDataServiceRestClient cdsClient) {
-                       logger.info(EELFLoggerDelegate.debugLogger,
+                       log.info(EELFLoggerDelegate.debugLogger,
                                        "Updating Local MLP Solution for peer solution " + peerMLPSolution);
 
                        if (!peerMLPSolution.getSolutionId().equals(localMLPSolution.getSolutionId()))
@@ -293,7 +310,7 @@ public class PeerGateway {
                                String newOwnerId = getOwnerId(this.sub);
                                if (!newOwnerId.equals(localMLPSolution.getOwnerId())) {
                                        // is this solution being updated as part of different/new subscription?
-                                       logger.warn(EELFLoggerDelegate.errorLogger, "updating solution " + localMLPSolution.getSolutionId()
+                                       log.warn(EELFLoggerDelegate.errorLogger, "updating solution " + localMLPSolution.getSolutionId()
                                                        + " as part of subscription " + this.sub.getSubId() + " triggers an ownership change");
                                }
                                localMLPSolution.setOwnerId(newOwnerId);
@@ -303,7 +320,7 @@ public class PeerGateway {
                                String newSourceId = this.peer.getPeerId();
                                if (!newSourceId.equals(localMLPSolution.getSourceId())) {
                                        // we will see this if a solution is available in more than one peer
-                                       logger.warn(EELFLoggerDelegate.errorLogger, "updating solution " + localMLPSolution.getSolutionId()
+                                       log.warn(EELFLoggerDelegate.errorLogger, "updating solution " + localMLPSolution.getSolutionId()
                                                        + " as part of subscription " + this.sub.getSubId() + " triggers a source change");
                                }
                                localMLPSolution.setSourceId(newSourceId);
@@ -312,12 +329,14 @@ public class PeerGateway {
                        try {
                                cdsClient.updateSolution(localMLPSolution);
                                return localMLPSolution;
-                       } catch (HttpStatusCodeException restx) {
-                               logger.error(EELFLoggerDelegate.debugLogger,
+                       }
+                       catch (HttpStatusCodeException restx) {
+                               log.error(EELFLoggerDelegate.errorLogger,
                                                "updateSolution CDS call failed. CDS message is " + restx.getResponseBodyAsString(), restx);
                                return null;
-                       } catch (Exception x) {
-                               logger.error(EELFLoggerDelegate.debugLogger, "updateSolution unexpected failure", x);
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "updateSolution unexpected failure", x);
                                return null;
                        }
                }
@@ -342,9 +361,10 @@ public class PeerGateway {
                        List<MLPSolutionRevision> peerRevisions = null;
                        try {
                                peerRevisions = (List<MLPSolutionRevision>) fedClient.getSolutionRevisions(theSolution.getSolutionId())
-                                               .getResponseBody();
-                       } catch (Exception x) {
-                               logger.warn(EELFLoggerDelegate.errorLogger, "Failed to retrieve acumos revisions for solution "
+                                               .getContent();
+                       }
+                       catch (Exception x) {
+                               log.warn(EELFLoggerDelegate.errorLogger, "Failed to retrieve acumos revisions for solution "
                                                + theSolution.getSolutionId() + " from peer " + this.peer, x);
                                throw x;
                        }
@@ -352,7 +372,7 @@ public class PeerGateway {
                        // this should not happen as any solution should have at least one
                        // revision (but that's an assumption on how on-boarding works)
                        if (peerRevisions == null || peerRevisions.size() == 0) {
-                               logger.warn(EELFLoggerDelegate.debugLogger, "No revisions were retrieved");
+                               log.warn(EELFLoggerDelegate.debugLogger, "No revisions were retrieved");
                                return;
                        }
 
@@ -362,9 +382,10 @@ public class PeerGateway {
                        List<MLPSolutionRevision> cdsRevisions = Collections.EMPTY_LIST;
                        try {
                                cdsRevisions = cdsClient.getSolutionRevisions(theSolution.getSolutionId());
-                       } catch (HttpStatusCodeException restx) {
+                       }
+                       catch (HttpStatusCodeException restx) {
                                if (!Errors.isCDSNotFound(restx)) {
-                                       logger.error(EELFLoggerDelegate.debugLogger,
+                                       log.error(EELFLoggerDelegate.errorLogger,
                                                        "getSolutionRevisions CDS call failed. CDS message is " + restx.getResponseBodyAsString(),
                                                        restx);
                                        throw restx;
@@ -390,22 +411,25 @@ public class PeerGateway {
                                List<MLPArtifact> peerArtifacts = null;
                                try {
                                        peerArtifacts = (List<MLPArtifact>) fedClient
-                                                       .getArtifacts(theSolution.getSolutionId(), peerRevision.getRevisionId()).getResponseBody();
-                               } catch (Exception x) {
-                                       logger.warn(EELFLoggerDelegate.debugLogger, "Failed to retrieve peer acumos artifacts", x);
+                                                       .getArtifacts(theSolution.getSolutionId(), peerRevision.getRevisionId()).getContent();
+                               }
+                               catch (Exception x) {
+                                       log.warn(EELFLoggerDelegate.errorLogger, "Failed to retrieve peer acumos artifacts", x);
                                        throw x;
                                }
 
                                List<MLPArtifact> cdsArtifacts = Collections.EMPTY_LIST;
                                if (localRevision == null) {
                                        localRevision = createMLPSolutionRevision(peerRevision, cdsClient);
-                               } else {
+                               }
+                               else {
                                        try {
                                                cdsArtifacts = cdsClient.getSolutionRevisionArtifacts(theSolution.getSolutionId(),
                                                                localRevision.getRevisionId());
-                                       } catch (HttpStatusCodeException restx) {
+                                       }
+                                       catch (HttpStatusCodeException restx) {
                                                if (!Errors.isCDSNotFound(restx)) {
-                                                       logger.error(EELFLoggerDelegate.debugLogger,
+                                                       log.error(EELFLoggerDelegate.errorLogger,
                                                                        "getArtifact CDS call failed. CDS message is " + restx.getResponseBodyAsString(),
                                                                        restx);
                                                        throw restx;
@@ -428,7 +452,8 @@ public class PeerGateway {
                                        if (localArtifact == null) {
                                                localArtifact = createMLPArtifact(theSolution.getSolutionId(), localRevision.getRevisionId(),
                                                                peerArtifact, cdsClient);
-                                       } else {
+                                       }
+                                       else {
                                                if (!peerArtifact.getVersion().equals(localArtifact.getVersion())) {
                                                        // update local artifact
                                                        copyMLPArtifact(peerArtifact, localArtifact);
@@ -436,9 +461,7 @@ public class PeerGateway {
                                                }
                                        }
 
-                                       // TODO: with CDS 1.13 check the subscription scope to decide if
-                                       // content is to be downloaded
-                                       boolean doContent = true;
+                                       boolean doContent = (SubscriptionScope.Full == SubscriptionScope.forCode(this.sub.getScopeType()));
                                        if (doContent) {
                                                // TODO: we are trying to access the artifact by its identifier which
                                                // is fine in the common case but the uri specified in the artifact
@@ -446,9 +469,9 @@ public class PeerGateway {
                                                Resource artifactContent = null;
                                                try {
                                                        artifactContent = fedClient.downloadArtifact(peerArtifact.getArtifactId());
-                                               } catch (Exception x) {
-                                                       logger.warn(EELFLoggerDelegate.debugLogger, "Failed to retrieve acumos artifact content",
-                                                                       x);
+                                               }
+                                               catch (Exception x) {
+                                                       log.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve acumos artifact content", x);
                                                }
 
                                                UploadArtifactInfo uploadInfo = null;
@@ -459,8 +482,9 @@ public class PeerGateway {
                                                                                                localArtifact.getName(), /* probably wrong */
                                                                                                localArtifact.getVersion(), "", /* should receive this from peer */
                                                                                                artifactContent.contentLength(), artifactContent.getInputStream());
-                                                       } catch (Exception x) {
-                                                               logger.warn(EELFLoggerDelegate.debugLogger,
+                                                       }
+                                                       catch (Exception x) {
+                                                               log.error(EELFLoggerDelegate.errorLogger,
                                                                                "Failed to push artifact content to local Nexus repo", x);
                                                        }
                                                }
@@ -476,8 +500,9 @@ public class PeerGateway {
                                        if (doUpdate) {
                                                try {
                                                        cdsClient.updateArtifact(localArtifact);
-                                               } catch (HttpStatusCodeException restx) {
-                                                       logger.error(EELFLoggerDelegate.debugLogger,
+                                               }
+                                               catch (HttpStatusCodeException restx) {
+                                                       log.error(EELFLoggerDelegate.errorLogger,
                                                                        "updateArtifact CDS call failed. CDS message is " + restx.getResponseBodyAsString(),
                                                                        restx);
                                                }
index 9fc6b65..01dad6d 100644 (file)
@@ -42,8 +42,8 @@ import org.acumos.federation.gateway.adapter.onap.sdc.ASDC.LifecycleState;
 import org.acumos.federation.gateway.adapter.onap.sdc.ASDCException;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.event.PeerSubscriptionEvent;
-import org.acumos.federation.gateway.service.impl.Clients;
-import org.acumos.federation.gateway.service.impl.FederationClient;
+import org.acumos.federation.gateway.common.Clients;
+import org.acumos.federation.gateway.common.FederationClient;
 import org.apache.commons.io.IOUtils;
 import org.json.JSONArray;
 import org.json.JSONObject;
@@ -51,6 +51,7 @@ import org.springframework.beans.factory.BeanInitializationException;
 import org.springframework.beans.factory.annotation.Autowired;
 //import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Scope;
 import org.springframework.context.annotation.Conditional;
 import org.springframework.context.event.EventListener;
 import org.springframework.core.task.TaskExecutor;
@@ -60,18 +61,22 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.client.HttpClientErrorException;
 
 @Component("onap")
-// @Scope("singleton")
+@Scope("singleton")
 @ConfigurationProperties(prefix = "onap")
 @Conditional(ONAPAdapterCondition.class)
 public class ONAP {
 
-       private final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ONAP.class);
+       private final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(ONAP.class);
        private ASDC asdc = new ASDC();
        private String asdcOperator;
        private TaskExecutor taskExecutor;
        @Autowired
        private Clients clients;
 
+       public ONAP() {
+               log.debug(EELFLoggerDelegate.debugLogger, "ONAP::new");
+       }
+
        public void setSdcUri(URI theUri) {
                this.asdc.setUri(theUri);
        }
@@ -86,7 +91,7 @@ public class ONAP {
 
        @PostConstruct
        public void initOnap() {
-               logger.debug(EELFLoggerDelegate.debugLogger, "initOnap");
+               log.trace(EELFLoggerDelegate.debugLogger, "initOnap");
 
                if (this.asdc.getUri() == null)
                        throw new BeanInitializationException("Forgot to configure the SDC uri ('onap.sdcUri') ??");
@@ -103,17 +108,17 @@ public class ONAP {
                cleanup();
 
                // Done
-               logger.debug(EELFLoggerDelegate.debugLogger, "Onap available");
+               log.trace(EELFLoggerDelegate.debugLogger, "Onap available");
        }
 
        @PreDestroy
        public void cleanupOnap() {
-               logger.debug(EELFLoggerDelegate.debugLogger, "Onap destroyed");
+               log.trace(EELFLoggerDelegate.debugLogger, "Onap destroyed");
        }
 
        @EventListener
        public void handlePeerSubscriptionUpdate(PeerSubscriptionEvent theEvent) {
-               logger.info(EELFLoggerDelegate.debugLogger, "received peer subscription update event " + theEvent);
+               log.info(EELFLoggerDelegate.debugLogger, "received peer subscription update event " + theEvent);
                taskExecutor.execute(new ONAPPushTask(theEvent.getPeer(), theEvent.getSolutions()));
        }
 
@@ -136,18 +141,20 @@ public class ONAP {
                        JSONArray sdcAssets = null;
                        try {
                                sdcAssets = asdc.getAssets(AssetType.resource, JSONArray.class, "Generic", "Abstract").waitForResult();
-                       } catch (Throwable x) {
-                               logger.warn(EELFLoggerDelegate.debugLogger, "Failed to list ONAP SDC assets: " + x.getCause(), x);
+                       }
+                       catch (Throwable x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "Failed to list ONAP SDC assets: " + x.getCause(), x);
                                // if this is a 404 NotFound, continue, otherwise, fail
                                if (x instanceof ASDCException && x.getCause() instanceof HttpClientErrorException
                                                && ((HttpClientErrorException) x.getCause()).getStatusCode() == HttpStatus.NOT_FOUND) {
                                        sdcAssets = new JSONArray();
-                               } else
+                               }
+                               else
                                        return;
                        }
-                       // logger.info(EELFLoggerDelegate.debugLogger, "Retrieved ONAP SDC assets: " +
+                       // log.info(EELFLoggerDelegate.debugLogger, "Retrieved ONAP SDC assets: " +
                        // sdcAssets);
-                       // logger.info(EELFLoggerDelegate.debugLogger, "Received Acumos solutions: " +
+                       // log.info(EELFLoggerDelegate.debugLogger, "Received Acumos solutions: " +
                        // this.solutions);
 
                        for (MLPSolution acumosSolution : this.solutions) {
@@ -157,7 +164,8 @@ public class ONAP {
                                        if (sdcAsset == null) {
                                                // new solution
                                                sdcAsset = createSdcAsset(acumosSolution);
-                                       } else {
+                                       }
+                                       else {
                                                // ONAP.this.asdc.checkoutResource(UUID.fromString(sdcAsset.getString("artifactUUID")),
                                                // ONAP.this.asdcOperator, "updated solution import");
                                                sdcAsset = updateSdcAsset(sdcAsset, acumosSolution);
@@ -166,8 +174,9 @@ public class ONAP {
                                        // ONAP.this.asdc.checkinResource(UUID.fromString(sdcAsset.getString("artifactUUID")),
                                        // ONAP.this.asdcOperator, "solution imported " + " the acumos revision number
                                        // ");
-                               } catch (Exception x) {
-                                       logger.warn(EELFLoggerDelegate.debugLogger,
+                               }
+                               catch (Exception x) {
+                                       log.error(EELFLoggerDelegate.errorLogger,
                                                        "Mapping of acumos solution failed for: " + acumosSolution + ": " + x);
                                }
                        }
@@ -185,7 +194,7 @@ public class ONAP {
                }
 
                public JSONObject createSdcAsset(MLPSolution theSolution) throws Exception {
-                       logger.info(EELFLoggerDelegate.debugLogger, "Creating ONAP SDC VF for solution " + theSolution);
+                       log.info(EELFLoggerDelegate.debugLogger, "Creating ONAP SDC VF for solution " + theSolution);
 
                        String description = null;// theSolution.getDescription();
                        if (description == null)
@@ -209,8 +218,9 @@ public class ONAP {
                                                .withOperator(ONAP.this.asdcOperator/* theSolution.getOwnerId() */) // probably won't work, SDC
                                                                                                                                                                                        // expects an att uuid
                                                .execute().waitForResult();
-                       } catch (Exception x) {
-                               logger.warn(EELFLoggerDelegate.debugLogger, "Failed to create ONAP SDC VF", x);
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "Failed to create ONAP SDC VF", x);
                                throw x;
                        }
                }
@@ -226,7 +236,7 @@ public class ONAP {
                 * @return SDC Asset info
                 */
                public JSONObject updateSdcAsset(JSONObject theAssetInfo, MLPSolution theSolution) {
-                       logger.info(EELFLoggerDelegate.debugLogger,
+                       log.info(EELFLoggerDelegate.debugLogger,
                                        "Updating ONAP SDC VF " + theAssetInfo.optString("uuid") + " for Acumosb solution " + theSolution);
                        return theAssetInfo;
                }
@@ -239,18 +249,20 @@ public class ONAP {
                        List<MLPSolutionRevision> acumosRevisions = null;
                        try {
                                acumosRevisions = (List<MLPSolutionRevision>) fedClient
-                                               .getSolutionRevisions(theSolution.getSolutionId()).getResponseBody();
-                       } catch (Exception x) {
-                               logger.warn(EELFLoggerDelegate.errorLogger, "Failed to retrieve acumos revisions: " + x);
+                                               .getSolutionRevisions(theSolution.getSolutionId()).getContent();
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve acumos revisions: " + x);
                                throw x;
                        }
 
                        List<MLPArtifact> acumosArtifacts = null;
                        try {
                                acumosArtifacts = (List<MLPArtifact>) fedClient.getArtifacts(theSolution.getSolutionId(),
-                                               acumosRevisions.get(acumosRevisions.size() - 1).getRevisionId()).getResponseBody();
-                       } catch (Exception x) {
-                               logger.warn(EELFLoggerDelegate.debugLogger, "Failed to retrieve acumos artifacts" + x);
+                                               acumosRevisions.get(acumosRevisions.size() - 1).getRevisionId()).getContent();
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve acumos artifacts" + x);
                                throw x;
                        }
 
@@ -258,8 +270,9 @@ public class ONAP {
                                theAssetInfo = ONAP.this.asdc
                                                .getAsset(AssetType.resource, UUID.fromString(theAssetInfo.getString("uuid")), JSONObject.class)
                                                .waitForResult();
-                       } catch (Exception x) {
-                               logger.warn(EELFLoggerDelegate.debugLogger,
+                       }
+                       catch (Exception x) {
+                               log.error(EELFLoggerDelegate.errorLogger,
                                                "Failed to retrieve ONAP SDC asset metadata for " + theAssetInfo.getString("uuid") + " : " + x);
                                throw x;
                        }
@@ -276,8 +289,8 @@ public class ONAP {
                        Map<MLPArtifact, JSONObject> updatedArtifacts = new HashMap<MLPArtifact, JSONObject>();
                        // List<JSONObject> oldArtifacts = new LinkedList<JSONObject>();
 
-                       logger.info(EELFLoggerDelegate.debugLogger, "Acumos artifacts: " + acumosArtifacts);
-                       logger.info(EELFLoggerDelegate.debugLogger, "ONAP SDC artifacts: " + sdcArtifacts);
+                       log.info(EELFLoggerDelegate.debugLogger, "Acumos artifacts: " + acumosArtifacts);
+                       log.info(EELFLoggerDelegate.debugLogger, "ONAP SDC artifacts: " + sdcArtifacts);
 
                        for (MLPArtifact acumosArtifact : acumosArtifacts) {
                                boolean found = false;
@@ -300,14 +313,14 @@ public class ONAP {
                                        newArtifacts.add(acumosArtifact);
                        }
 
-                       logger.warn(EELFLoggerDelegate.debugLogger, "New SDC artifacts: " + newArtifacts);
+                       log.info(EELFLoggerDelegate.debugLogger, "New SDC artifacts: " + newArtifacts);
                        for (MLPArtifact acumosArtifact : newArtifacts) {
                                try {
                                        byte[] content = IOUtils.toByteArray(new URI(acumosArtifact.getUri()));
                                        if (content == null)
                                                throw new Exception("Unable to fetch artifact content from " + acumosArtifact.getUri());
                                        if (content.length == 0)
-                                               logger.warn(EELFLoggerDelegate.debugLogger,
+                                               log.warn(EELFLoggerDelegate.debugLogger,
                                                                "Acumos artifact has empty content, not acceptable in ONAP SDC");
                                        // more sophisticated mapping needed here
                                        asdc.createAssetArtifact(AssetType.resource, UUID.fromString(theAssetInfo.getString("uuid")))
@@ -318,12 +331,13 @@ public class ONAP {
                                                        .withDescription(acumosArtifact.getArtifactId() + "@"
                                                                        + acumosArtifact.getVersion()/* acumosArtifact.getDescription() */)
                                                        .execute().waitForResult();
-                               } catch (Exception x) {
-                                       logger.warn(EELFLoggerDelegate.debugLogger, "Failed to create ONAP SDC VF Artifact", x);
+                               }
+                               catch (Exception x) {
+                                       log.error(EELFLoggerDelegate.errorLogger, "Failed to create ONAP SDC VF Artifact", x);
                                }
                        }
 
-                       logger.warn(EELFLoggerDelegate.debugLogger, "Updated SDC artifacts: " + updatedArtifacts.keySet());
+                       log.warn(EELFLoggerDelegate.debugLogger, "Updated SDC artifacts: " + updatedArtifacts.keySet());
                        for (Map.Entry<MLPArtifact, JSONObject> updateEntry : updatedArtifacts.entrySet()) {
                                MLPArtifact acumosArtifact = updateEntry.getKey();
                                try {
@@ -337,8 +351,9 @@ public class ONAP {
                                                        .withDescription(acumosArtifact.getArtifactId() + "@"
                                                                        + acumosArtifact.getVersion()/* acumosArtifact.getDescription() */)
                                                        .execute().waitForResult();
-                               } catch (Exception x) {
-                                       logger.warn(EELFLoggerDelegate.debugLogger, "Failed to update ONAP SDC VF Artifact", x);
+                               }
+                               catch (Exception x) {
+                                       log.error(EELFLoggerDelegate.errorLogger, "Failed to update ONAP SDC VF Artifact", x);
                                }
                        }
 
@@ -359,14 +374,15 @@ public class ONAP {
                                        deletedArtifacts.add(sdcArtifact);
                                }
                        }
-                       logger.warn(EELFLoggerDelegate.debugLogger, "Deleted SDC artifacts: " + deletedArtifacts);
+                       log.warn(EELFLoggerDelegate.debugLogger, "Deleted SDC artifacts: " + deletedArtifacts);
                        for (JSONObject sdcArtifact : deletedArtifacts) {
                                try {
                                        asdc.deleteAssetArtifact(AssetType.resource, UUID.fromString(theAssetInfo.getString("uuid")),
                                                        UUID.fromString(sdcArtifact.getString("artifactUUID"))).withOperator(ONAP.this.asdcOperator)
                                                        .execute().waitForResult();
-                               } catch (Exception x) {
-                                       logger.warn(EELFLoggerDelegate.debugLogger, "Failed to delete ONAP SDC VF Artifact", x);
+                               }
+                               catch (Exception x) {
+                                       log.error(EELFLoggerDelegate.errorLogger, "Failed to delete ONAP SDC VF Artifact", x);
                                }
                        }
                }
@@ -417,7 +433,7 @@ public class ONAP {
                try {
                        sdcAssets = asdc.getAssets(AssetType.resource, JSONArray.class, "Generic", "Abstract").waitForResult();
                } catch (Throwable x) {
-                       logger.info(EELFLoggerDelegate.debugLogger, "Cleanup failed to list ONAP SDC assets: " + x.getCause(), x);
+                       log.info(EELFLoggerDelegate.debugLogger, "Cleanup failed to list ONAP SDC assets: " + x.getCause(), x);
                }
 
                if (sdcAssets == null)
@@ -430,9 +446,9 @@ public class ONAP {
                                try {
                                        asdc.cycleAsset(AssetType.resource, UUID.fromString(sdcAsset.getString("uuid")),
                                                        LifecycleState.undocheckout, ONAP.this.asdcOperator, null).waitForResult();
-                               } catch (Exception x) {
-                                       logger.info(EELFLoggerDelegate.debugLogger, "Cleanup ONAP SDC asset: " + sdcAsset.optString("uuid"),
-                                                       x);
+                               }
+                               catch (Exception x) {
+                                       log.error(EELFLoggerDelegate.errorLogger, "Cleanup ONAP SDC asset: " + sdcAsset.optString("uuid"), x);
                                }
                        }
                }
index d18aba0..b6712d7 100644 (file)
@@ -24,7 +24,7 @@ import org.springframework.context.annotation.ConditionContext;
 import org.springframework.core.type.AnnotatedTypeMetadata;
 import org.springframework.core.env.Environment;
 
-import org.acumos.federation.gateway.common.AdapterCondition;
+import org.acumos.federation.gateway.config.AdapterCondition;
 
 /**
  */
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/cds/PeerStatus.java b/gateway/src/main/java/org/acumos/federation/gateway/cds/PeerStatus.java
new file mode 100644 (file)
index 0000000..a05d1e7
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.cds;
+
+import java.util.EnumSet;
+import org.acumos.cds.domain.MLPPeerStatus;
+import org.acumos.cds.PeerStatusCode;
+
+/**
+ * Supplements the CDS representation of a peer status information.
+ * Not needed but I did not notice the equivalent class in CDS .. To be removed once the set of
+ * values in CDS is updated.
+ */
+public enum PeerStatus {
+
+       Active(PeerStatusCode.AC.name()),
+       Inactive(PeerStatusCode.IN.name()),
+       Requested(PeerStatusCode.PA.name()),/* the 'peer' has made a request to be registered with this Acumos instance (pending active)  */
+       Renounced(PeerStatusCode.PR.name()),  /* the peer has made a request to be unregistered as a peer of this Acumos instance (pending remove) */
+       Declined(PeerStatusCode.RM.name()) /* (removed) */
+       ;
+
+       private String                          code;
+       //private MLPPeerStatus mlp;
+
+       private PeerStatus(String theCode) {
+               this.code = theCode;
+               //mlp = new MLPPeerStatus(theCode, name());
+       }
+
+       public String code() {
+               return this.code;
+       }
+
+       //public MLPPeerStatus mlp() {
+       //      return this.mlp;
+       //}
+
+       public static PeerStatus forCode(final String theCode) {
+               return EnumSet.allOf(PeerStatus.class)
+                                               .stream()
+                                               .filter(status -> status.code().equals(theCode))
+                                               .findFirst()
+                                               .orElse(null);
+       }
+}
+
+
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/cds/SubscriptionScope.java b/gateway/src/main/java/org/acumos/federation/gateway/cds/SubscriptionScope.java
new file mode 100644 (file)
index 0000000..f3bf68f
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.cds;
+
+import java.util.EnumSet;
+import org.acumos.cds.domain.MLPSubscriptionScopeType;
+
+/**
+ * Supplements the CDS representation of a subscription scope information.
+ */
+public enum SubscriptionScope {
+
+       Reference("RF"),
+       Full("FL"),
+       ;
+
+       private String                          code;
+       //private MLPPeerStatus mlp;
+
+       private SubscriptionScope(String theCode) {
+               this.code = theCode;
+               //mlp = new MLPSubscriptionScopeType(theCode, name());
+       }
+
+       public String code() {
+               return this.code;
+       }
+
+       //public MLPPeerStatus mlp() {
+       //      return this.mlp;
+       //}
+
+       public static SubscriptionScope forCode(final String theCode) {
+               return EnumSet.allOf(SubscriptionScope.class)
+                                               .stream()
+                                               .filter(status -> status.code().equals(theCode))
+                                               .findFirst()
+                                               .orElse(null);
+       }
+}
+
+
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/cds/ValidationStatus.java b/gateway/src/main/java/org/acumos/federation/gateway/cds/ValidationStatus.java
new file mode 100644 (file)
index 0000000..a64b116
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.cds;
+
+import java.util.EnumSet;
+import org.acumos.cds.domain.MLPValidationStatus;
+
+/**
+ * Supplements the CDS representation of a solution validation status information.
+ */
+public enum ValidationStatus {
+
+       Passed("PS"),
+       NotValidated("NV")
+       ;
+
+       private String                                                  code;
+       //private MLPValidationStatus   mlp;
+
+       private ValidationStatus(String theCode) {
+               this.code = theCode;
+               //mlp = new MLPValidationStatus();
+       }
+
+       public String code() {
+               return this.code;
+       }
+
+       //public MLPValidationStatus mlp() {
+       //      return this.mlp;
+       //}
+
+       public static ValidationStatus forCode(final String theCode) {
+               return EnumSet.allOf(ValidationStatus.class)
+                                               .stream()
+                                               .filter(status -> status.code().equals(theCode))
+                                               .findFirst()
+                                               .orElse(null);
+       }
+}
+
+
index 7d30a4b..b064202 100644 (file)
@@ -31,12 +31,16 @@ import org.springframework.web.util.UriComponentsBuilder;
  */
 public enum API {
 
-       SOLUTIONS(Paths.SOLUTIONS, Queries.SOLUTIONS), SOLUTION_DETAIL(Paths.SOLUTION_DETAILS), SOLUTION_REVISIONS(
-                       Paths.SOLUTION_REVISIONS), SOLUTION_REVISION_DETAILS(
-                                       Paths.SOLUTION_REVISION_DETAILS), SOLUTION_REVISION_ARTIFACTS(
-                                                       Paths.SOLUTION_REVISION_ARTIFACTS), ARTIFACT_DETAILS(
-                                                                       Paths.ARTIFACT_DETAILS), ARTIFACT_DOWNLOAD(
-                                                                                       Paths.ARTIFACT_DOWNLOAD), PEERS(Paths.PEERS);
+       SOLUTIONS(Paths.SOLUTIONS, Queries.SOLUTIONS),
+       SOLUTION_DETAIL(Paths.SOLUTION_DETAILS),
+       SOLUTION_REVISIONS(Paths.SOLUTION_REVISIONS),
+       SOLUTION_REVISION_DETAILS(Paths.SOLUTION_REVISION_DETAILS),
+       SOLUTION_REVISION_ARTIFACTS(Paths.SOLUTION_REVISION_ARTIFACTS),
+       ARTIFACT_DETAILS(Paths.ARTIFACT_DETAILS),
+       ARTIFACT_DOWNLOAD(Paths.ARTIFACT_DOWNLOAD),
+       PEERS(Paths.PEERS),
+       SUBSCRIPTION(Paths.SUBSCRIPTION),
+       PING(Paths.PING);
 
        private String path;
        private String[] query;
@@ -79,7 +83,7 @@ public enum API {
         *            URL
         * @return URI
         */
-       public UriComponentsBuilder buildUri(String theHttpUrl) {
+       public UriComponentsBuilder uriBuilder(String theHttpUrl) {
                UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(theHttpUrl).path(this.path);
                if (this.query != null) {
                        for (String queryParam : this.query) {
@@ -99,7 +103,7 @@ public enum API {
         *            parameters
         * @return URI
         */
-       public UriComponentsBuilder buildUri(String theHttpUrl, Collection<String> theParams) {
+       public UriComponentsBuilder uriBuilder(String theHttpUrl, Collection<String> theParams) {
                UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(theHttpUrl).path(this.path);
                if (this.query != null) {
                        for (String queryParam : this.query) {
@@ -115,7 +119,7 @@ public enum API {
         * the params include both path and query params.
         */
        public URI buildUri(String theHttpUrl, Map<String, ?> theParams) {
-               return buildUri(theHttpUrl, theParams.keySet()).buildAndExpand(theParams).encode().toUri();
+               return uriBuilder(theHttpUrl, theParams.keySet()).buildAndExpand(theParams).encode().toUri();
        }
 
        /**
@@ -128,7 +132,16 @@ public enum API {
         * @return URI
         */
        public URI buildUri(String theHttpUrl, String... theParams) {
-               return buildUri(theHttpUrl).buildAndExpand(theParams).encode().toUri();
+               return uriBuilder(theHttpUrl).buildAndExpand(theParams).encode().toUri();
+       }
+
+       public static class Roots {
+
+               public static final String FEDERATION = "/";
+               /**
+                * Maybe too particular but at this point all LOCAL interface operations are with respect to one peer
+                */
+               public static final String LOCAL = "/peer/{peerId}";
        }
 
        public static class Paths {
@@ -143,10 +156,13 @@ public enum API {
                public static final String ARTIFACT_DETAILS = "/artifacts/{artifactId}";
                public static final String ARTIFACT_DOWNLOAD = "/artifacts/{artifactId}/download";
 
+               public static final String SUBSCRIPTION = "/subscription/{subscriptionId}";
+
                public static final String PEERS = "/peers";
+               public static final String PING = "/ping";
 
-               // public static final String PEER_SUBSCRIBE = "/peer/subscribe";
-               // public static final String PEER_UNSUBSCRIBE = "/peer/unsubscribe";
+               public static final String PEER_REGISTER = "/peer/register";
+               public static final String PEER_UNREGISTER = "/peer/unregister";
        }
 
        public static class QueryParameters {
@@ -18,7 +18,7 @@
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.service.impl;
+package org.acumos.federation.gateway.common;
 
 import java.net.MalformedURLException;
 import java.net.URI;
@@ -43,7 +43,7 @@ import org.springframework.web.util.UriComponentsBuilder;
  */
 public abstract class AbstractClient {
 
-       protected final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(getClass().getName());
+       protected final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
 
        protected final String baseUrl;
        protected final RestTemplate restTemplate;
@@ -65,7 +65,8 @@ public abstract class AbstractClient {
                try {
                        url = new URL(theTarget);
                        this.baseUrl = url.toExternalForm();
-               } catch (MalformedURLException ex) {
+               }
+               catch (MalformedURLException ex) {
                        throw new RuntimeException("Failed to parse targedt URL", ex);
                }
 
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.service.impl;
+package org.acumos.federation.gateway.common;
 
-import org.acumos.cds.client.CommonDataServiceRestClientImpl;
-import org.acumos.cds.client.ICommonDataServiceRestClient;
-import org.acumos.nexus.client.NexusArtifactClient;
-import org.acumos.nexus.client.RepositoryLocation;
 import org.apache.http.client.HttpClient;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.Import;
 import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Component;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+
+import org.acumos.nexus.client.NexusArtifactClient;
+import org.acumos.nexus.client.RepositoryLocation;
+
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.config.InterfaceConfiguration;
+import org.acumos.federation.gateway.config.LocalInterfaceConfiguration;
+import org.acumos.federation.gateway.config.FederationInterfaceConfiguration;
+
+import org.acumos.cds.client.CommonDataServiceRestClientImpl;
+import org.acumos.cds.client.ICommonDataServiceRestClient;
 
 /**
  * Unique entry point for building clients: peer access clients, cds clients
  */
 @Component("clients")
 @Scope("singleton")
-public class Clients implements ApplicationContextAware {
+public class Clients {
 
        @Autowired
-       protected Environment env;
+       private Environment env;
+       @Autowired
+       private ApplicationContext appCtx = null;
+       @Autowired
+       private LocalInterfaceConfiguration localConfig = null;
+       @Autowired
+       private FederationInterfaceConfiguration federationConfig = null;
 
-       protected ApplicationContext appCtx = null;
+       private final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
 
-       public void setApplicationContext(ApplicationContext theAppContext) {
-               this.appCtx = theAppContext;
+       public Clients() {
+               log.trace(EELFLoggerDelegate.debugLogger, "Clients::new");
        }
-
+       
        /**
         * @return The standard CDS client
         */
-       public ICommonDataServiceRestClient getClient() {
-               return new CommonDataServiceRestClientImpl(env.getProperty("cdms.client.url"),
-                               env.getProperty("cdms.client.username"), env.getProperty("cdms.client.password"));
+       public ICommonDataServiceRestClient getCDSClient() {
+
+               RestTemplateBuilder builder =
+                       new RestTemplateBuilder()
+                               .requestFactory(new HttpComponentsClientHttpRequestFactory( 
+                                                                                                       /*(HttpClient)this.appCtx.getBean("localClient")*/
+                                                                                                       localConfig.buildClient()))
+                               //.rootUri(env.getProperty("cdms.client.url"))
+                               .basicAuthorization(env.getProperty("cdms.client.username"),
+                                                                                                               env.getProperty("cdms.client.password"));
+
+                       return new CommonDataServiceRestClientImpl(
+                               env.getProperty("cdms.client.url"), builder.build());
+               //return new CommonDataServiceRestClientImpl(
+               //              env.getProperty("cdms.client.url"),
+               //              env.getProperty("cdms.client.username"),
+               //              env.getProperty("cdms.client.password"));
        }
 
+       /**
+        * Build a client for the given peer uri
+        */
        public FederationClient getFederationClient(String thePeerURI) {
-               return new FederationClient(thePeerURI, (HttpClient) this.appCtx.getBean("federationClient"));
+               return new FederationClient(thePeerURI, /*(HttpClient)this.appCtx.getBean("federationClient")*/federationConfig.buildClient());
        }
 
+       /** */
        public NexusArtifactClient getNexusClient() {
                RepositoryLocation repositoryLocation = new RepositoryLocation();
 
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.service.impl;
+package org.acumos.federation.gateway.common;
 
 import java.net.URI;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import org.acumos.cds.domain.MLPPeer;
 import org.acumos.cds.domain.MLPArtifact;
 import org.acumos.cds.domain.MLPSolution;
 import org.acumos.cds.domain.MLPSolutionRevision;
@@ -59,6 +60,31 @@ public class FederationClient extends AbstractClient {
                super(theTarget, theClient);
        }
 
+       /**
+        */
+       public JsonResponse<MLPPeer> ping()
+                       throws HttpStatusCodeException {
+               URI uri = API.PING.buildUri(this.baseUrl);
+               log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
+               ResponseEntity<JsonResponse<MLPPeer>> response = null;
+               try {
+                       response = restTemplate.exchange(uri, HttpMethod.GET, null,
+                                       new ParameterizedTypeReference<JsonResponse<MLPPeer>>() {
+                                       });
+               }
+               catch (HttpStatusCodeException x) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " failed" + ((response == null) ? "" : (" " + response)), x);
+                       throw x;
+               }
+               catch (Throwable t) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
+               }
+               finally {
+                       log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
+               }
+               return response == null ? null : response.getBody();
+       }       
+
        /**
         * 
         * @param theSelection
@@ -76,25 +102,55 @@ public class FederationClient extends AbstractClient {
                        selectorParam = theSelection == null ? null
                                        // : UriUtils.encodeQueryParam(Utils.mapToJsonString(theSelection),"UTF-8");
                                        : Base64Utils.encodeToString(Utils.mapToJsonString(theSelection).getBytes("UTF-8"));
-               } catch (Exception x) {
+               }
+               catch (Exception x) {
                        throw new IllegalArgumentException("Cannot process the selection argument", x);
                }
 
                URI uri = API.SOLUTIONS.buildUri(this.baseUrl, selectorParam == null ? Collections.EMPTY_MAP
                                : Collections.singletonMap(API.QueryParameters.SOLUTIONS_SELECTOR, selectorParam));
-               logger.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
+               log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
                ResponseEntity<JsonResponse<List<MLPSolution>>> response = null;
                try {
                        response = restTemplate.exchange(uri, HttpMethod.GET, null,
                                        new ParameterizedTypeReference<JsonResponse<List<MLPSolution>>>() {
                                        });
-               } catch (HttpStatusCodeException x) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " failed.", x);
+               }
+               catch (HttpStatusCodeException x) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " failed" + ((response == null) ? "" : (" " + response)), x);
                        throw x;
-               } catch (Throwable t) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " unexpected failure.", t);
-               } finally {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
+               }
+               catch (Throwable t) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
+               }
+               finally {
+                       log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
+               }
+               return response == null ? null : response.getBody();
+       }
+
+       /**
+        */
+       public JsonResponse<MLPSolution> getSolution(String theSolutionId)
+                       throws HttpStatusCodeException {
+
+               URI uri = API.SOLUTION_DETAIL.buildUri(this.baseUrl, theSolutionId);
+               log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
+               ResponseEntity<JsonResponse<MLPSolution>> response = null;
+               try {
+                       response = restTemplate.exchange(uri, HttpMethod.GET, null,
+                                       new ParameterizedTypeReference<JsonResponse<MLPSolution>>() {
+                                       });
+               }
+               catch (HttpStatusCodeException x) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " failed" + ((response == null) ? "" : (" " + response)), x);
+                       throw x;
+               }
+               catch (Throwable t) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
+               }
+               finally {
+                       log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
                }
                return response == null ? null : response.getBody();
        }
@@ -112,19 +168,22 @@ public class FederationClient extends AbstractClient {
                        throws HttpStatusCodeException {
 
                URI uri = API.SOLUTION_REVISIONS.buildUri(this.baseUrl, theSolutionId);
-               logger.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
+               log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
                ResponseEntity<JsonResponse<List<MLPSolutionRevision>>> response = null;
                try {
                        response = restTemplate.exchange(uri, HttpMethod.GET, null,
                                        new ParameterizedTypeReference<JsonResponse<List<MLPSolutionRevision>>>() {
                                        });
-               } catch (HttpStatusCodeException x) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " failed.", x);
+               }
+               catch (HttpStatusCodeException x) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " failed" + ((response == null) ? "" : (" " + response)), x);
                        throw x;
-               } catch (Throwable t) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " unexpected failure.", t);
-               } finally {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
+               }
+               catch (Throwable t) {
+                       log.info(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
+               }
+               finally {
+                       log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
                }
                return response == null ? null : response.getBody();
        }
@@ -142,19 +201,22 @@ public class FederationClient extends AbstractClient {
        public JsonResponse<List<MLPArtifact>> getArtifacts(String theSolutionId, String theRevisionId)
                        throws HttpStatusCodeException {
                URI uri = API.SOLUTION_REVISION_ARTIFACTS.buildUri(this.baseUrl, theSolutionId, theRevisionId);
-               logger.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
+               log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
                ResponseEntity<JsonResponse<List<MLPArtifact>>> response = null;
                try {
                        response = restTemplate.exchange(uri, HttpMethod.GET, null,
                                        new ParameterizedTypeReference<JsonResponse<List<MLPArtifact>>>() {
                                        });
-               } catch (HttpStatusCodeException x) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " failed.", x);
+               }
+               catch (HttpStatusCodeException x) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " failed" + ((response == null) ? "" : (" " + response)), x);
                        throw x;
-               } catch (Throwable t) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " unexpected failure.", t);
-               } finally {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
+               }
+               catch (Throwable t) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
+               }
+               finally {
+                       log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
                }
                return response == null ? null : response.getBody();
        }
@@ -168,17 +230,20 @@ public class FederationClient extends AbstractClient {
         */
        public Resource downloadArtifact(String theArtifactId) throws HttpStatusCodeException {
                URI uri = API.ARTIFACT_DOWNLOAD.buildUri(this.baseUrl, theArtifactId);
-               logger.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
+               log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
                ResponseEntity<Resource> response = null;
                try {
                        response = restTemplate.exchange(uri, HttpMethod.GET, null, Resource.class);
-               } catch (HttpStatusCodeException x) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " failed.", x);
+               }
+               catch (HttpStatusCodeException x) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " failed" + ((response == null) ? "" : (" " + response)), x);
                        throw x;
-               } catch (Throwable t) {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " unexpected failure.", t);
-               } finally {
-                       logger.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
+               }
+               catch (Throwable t) {
+                       log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
+               }
+               finally {
+                       log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
                }
 
                if (response == null) {
index bce5857..8ea9308 100644 (file)
@@ -22,20 +22,12 @@ package org.acumos.federation.gateway.common;
 
 public class JSONTags {
 
-       public static final String TAG_STATUS_SUCCESS = "success";
-       public static final String TAG_RESPONSE_STATUS = "status";
+       public static final String TAG_RESPONSE_ERROR = "error";
+       public static final String TAG_RESPONSE_CONTENT = "content";
+       public static final String TAG_RESPONSE_MESSAGE = "message";
+
        public static final String TAG_REQUEST_FROM = "request_from";
        public static final String TAG_REQUEST_ID = "request_id";
-
        public static final String TAG_REQUEST_BODY = "request_body";
-       public static final String TAG_STATUS_FAILURE = "failure";
-
-       public static final String TAG_RESPONSE_DETAIL = "response_detail";
-       public static final String TAG_RESPONSE_BODY = "response_body";
-       public static final String TAG_RESPONSE_MESSAGE = "request";
-       public static final String TAG_RESPONSE_CODE = "response_code";
-       public static final String TAG_ERROR_CODE_SUCCESS = "200";
-       public static final String TAG_ERROR_CODE_FAILURE = "403";
-       public static final String TAG_ERROR_CODE_EXCEPTION = "500";
 
 }
index a18cd4b..8caf452 100644 (file)
@@ -36,64 +36,128 @@ public class JsonResponse<T> implements Serializable {
        private static final long serialVersionUID = -2934104266393591755L;
 
        /**
-        * Json property status.
+        * Was there an error ?
         */
-       @JsonProperty(value = JSONTags.TAG_RESPONSE_STATUS)
-       private Boolean status;
+       @JsonProperty(value = JSONTags.TAG_RESPONSE_ERROR)
+       //private Boolean error;
+       private String error;
 
        /**
-        * Json property responseDetail.
+        * Additional information.
         */
-       @JsonProperty(value = JSONTags.TAG_RESPONSE_DETAIL)
-       private String responseDetail;
+       @JsonProperty(value = JSONTags.TAG_RESPONSE_MESSAGE)
+       private String message;
 
        /**
-        * Json property responseCode.
+        * Response content.
         */
-       @JsonProperty(value = JSONTags.TAG_RESPONSE_CODE)
-       private String responseCode;
+       @JsonProperty(value = JSONTags.TAG_RESPONSE_CONTENT)
+       private T content;
+/*
+       public Boolean isError() {
+               return this.error;
+       }
 
-       /**
-        * Json property responseBody. It represents the type of generic object.
-        */
-       @JsonProperty(value = JSONTags.TAG_RESPONSE_BODY)
-       private T responseBody;
+       public void setError(Boolean isError) {
+               this.error = isError;
+       }
+*/
+       public String getError() {
+               return this.error;
+       }
 
-       public Boolean getStatus() {
-               return status;
+       public void setError(String theError) {
+               this.error = theError;
        }
 
-       public void setStatus(Boolean status) {
-               this.status = status;
+       public String getMessage() {
+               return this.message;
        }
 
-       public String getResponseDetail() {
-               return responseDetail;
+       public void setMessage(String theMessage) {
+               this.message = theMessage;
        }
 
-       public void setResponseDetail(String responseDetail) {
-               this.responseDetail = responseDetail;
+       public T getContent() {
+               return this.content;
        }
 
-       public String getResponseCode() {
-               return responseCode;
+       public void setContent(T theContent) {
+               this.content = theContent;
        }
 
-       public void setResponseCode(String responseCode) {
-               this.responseCode = responseCode;
+       public String toString() {
+               return new StringBuilder("JsonResponse")
+                                                               .append(System.identityHashCode(this))
+                                                               .append('(')
+                                                               .append(this.error)
+                                                               .append(',')
+                                                               .append(this.message == null ? "null" : this.message)
+                                                               .append(',')
+                                                               .append(this.content == null ? "null" : this.content)
+                                                               .append(')')
+                                                               .toString();
        }
 
-       public T getResponseBody() {
-               return responseBody;
+       /**
+        */
+       public static class JsonResponseBuilder<T> {
+
+               private JsonResponse<T> response = new JsonResponse();
+
+               public JsonResponseBuilder() {
+                       this.response.setError(Boolean.FALSE.toString());
+               }
+
+               public JsonResponseBuilder<T>   withMessage(String theMessage) {
+                       this.response.setMessage(theMessage);
+                       return this;
+               }
+               
+               public JsonResponseBuilder<T>   withContent(T theContent) {
+                       this.response.setContent(theContent);
+                       return this;
+               }
+
+               public JsonResponse<T> build() {
+                       return this.response;
+               }
        }
 
-       public void setResponseBody(T responseBody) {
-               this.responseBody = responseBody;
+       /** */
+       public static <T> JsonResponseBuilder<T> buildResponse() {
+               return new JsonResponseBuilder<T>();
        }
 
-       public String toString() {
-               return new StringBuilder("JsonResponse").append(System.identityHashCode(this)).append('(')
-                               .append(this.responseCode).append(' ').append(this.responseDetail).append(", ")
-                               .append(this.responseBody == null ? "null" : this.responseBody).append(')').toString();
+       /**
+        */
+       public static class JsonErrorResponseBuilder<T> {
+
+               private JsonResponse<T> response = new JsonResponse();
+
+               public JsonErrorResponseBuilder() {
+                       this.response.setError(Boolean.TRUE.toString());
+                       this.response.setContent(null);
+               }
+
+               public JsonErrorResponseBuilder<T>      withMessage(String theMessage) {
+                       this.response.setMessage(theMessage);
+                       return this;
+               }
+               
+               public JsonErrorResponseBuilder<T>      withError(Throwable theError) {
+                       this.response.setMessage(theError.toString());
+                       return this;
+               }
+
+               public JsonResponse<T> build() {
+                       return this.response;
+               }
+       }
+       
+       /** */
+       public static <T> JsonErrorResponseBuilder<T> buildErrorResponse() {
+               return new JsonErrorResponseBuilder<T>();
        }
+
 }
@@ -18,7 +18,7 @@
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.common;
+package org.acumos.federation.gateway.config;
 
 import org.springframework.context.annotation.Condition;
 import org.springframework.context.annotation.ConditionContext;
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/config/AdapterConfiguration.java b/gateway/src/main/java/org/acumos/federation/gateway/config/AdapterConfiguration.java
new file mode 100644 (file)
index 0000000..a2b43e8
--- /dev/null
@@ -0,0 +1,87 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Profile;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import org.acumos.federation.gateway.service.CatalogService;
+import org.acumos.federation.gateway.service.PeerSubscriptionService;
+import org.acumos.federation.gateway.service.PeerService;
+import org.acumos.federation.gateway.service.LocalWatchService;
+
+import org.acumos.federation.gateway.service.impl.CatalogServiceLocalImpl;
+import org.acumos.federation.gateway.service.impl.PeerServiceLocalImpl;
+import org.acumos.federation.gateway.common.Clients;
+
+import org.acumos.federation.gateway.task.TaskConfiguration;
+
+/**
+ * Specifies common configuration required by the federation adapter.
+ * This is not a full configuration as the main component (the actual adapter) is
+ * not specified.
+ */
+@Configuration
+//@EnableAutoConfiguration
+@Import(TaskConfiguration.class)
+@EnableConfigurationProperties({FederationInterfaceConfiguration.class,
+                                                                                                                               LocalInterfaceConfiguration.class})
+//@Profile({"adapter"})
+@Conditional({AdapterCondition.class})
+@EnableScheduling
+public abstract class AdapterConfiguration  {
+
+       private PeerServiceLocalImpl peerSubSrv = new PeerServiceLocalImpl();
+
+       @Bean
+       public CatalogService catalogService() {
+               return new CatalogServiceLocalImpl();
+       }
+
+       @Bean
+       public PeerService peerService() {
+               return this.peerSubSrv;
+       }
+       
+       @Bean
+       public PeerSubscriptionService peerSubscriptionService() {
+       //      return new PeerServiceLocalImpl(); //another instance ??
+               return this.peerSubSrv;
+       }
+
+       @Bean
+       public LocalWatchService watchService() {
+               return new LocalWatchService();
+       }
+
+       @Bean
+       public Clients clients() {
+               return new Clients();
+       }
+
+}
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/config/FederationConfiguration.java b/gateway/src/main/java/org/acumos/federation/gateway/config/FederationConfiguration.java
new file mode 100644 (file)
index 0000000..d7c4a31
--- /dev/null
@@ -0,0 +1,113 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+//import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.controller.CatalogController;
+import org.acumos.federation.gateway.controller.PeersController;
+import org.acumos.federation.gateway.controller.PingController;
+import org.acumos.federation.gateway.security.AuthenticationConfiguration;
+
+import org.apache.http.client.HttpClient;
+
+import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
+import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
+import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
+
+/**
+ * Provide those beans used in the interaction with other peers (federation)
+ */
+@Configuration
+@Import(AuthenticationConfiguration.class)
+@EnableAutoConfiguration
+//@ConfigurationProperties(prefix = "federation", ignoreInvalidFields = true)
+public class FederationConfiguration {
+
+       @Autowired
+       private FederationInterfaceConfiguration interfaceConfig;
+       private EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
+
+       public FederationConfiguration() {
+       }
+
+       @Bean
+       public CatalogController catalogServer() {
+               return new CatalogController();
+       }
+       
+       @Bean
+       public PeersController peersServer() {
+               return new PeersController();
+       }
+
+       @Bean
+       public PingController pingServer() {
+               return new PingController();
+       }
+
+       /**
+   * Build a client for interacting with peers through the defined
+        * federation interface.
+        * We assume the same configuration takes place for client and server
+        * roles when interacting with peers: we'll assume the same identity, use the
+        * same network interface, etc. If this ever needs to change we can pick
+        * the values from a separate configuration properties set.
+        */
+       @Bean
+  @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+       //@ConfigurationProperties(prefix = "server", ignoreInvalidFields = true)
+       public HttpClient federationClient() {
+               log.debug(EELFLoggerDelegate.debugLogger, this + "::federationClient from " + this.interfaceConfig);
+               return this.interfaceConfig.buildClient();
+       }
+
+/*
+       @Bean
+       public EmbeddedServletContainerFactory federationServer() {
+               TomcatEmbeddedServletContainerFactory tomcat =
+                       new TomcatEmbeddedServletContainerFactory();
+               tomcat.addAdditionalTomcatConnectors(this.interfaceConfig.buildConnector());
+               return tomcat;
+       }
+*/
+       @Bean
+       public EmbeddedServletContainerCustomizer federationServer() {
+               log.debug(EELFLoggerDelegate.debugLogger, this + "::federationServer from " + this.interfaceConfig);
+               return new EmbeddedServletContainerCustomizer() {
+                       @Override
+                       public void customize(ConfigurableEmbeddedServletContainer theContainer) {
+                               FederationConfiguration.this.interfaceConfig.configureContainer(theContainer);
+                       }
+               }; 
+       }
+       
+}
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/config/FederationInterfaceConfiguration.java b/gateway/src/main/java/org/acumos/federation/gateway/config/FederationInterfaceConfiguration.java
new file mode 100644 (file)
index 0000000..7787918
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.config;
+
+import org.springframework.stereotype.Component;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Defines a specific external configuration prefix for the federation interface.
+ */
+@Component
+@ConfigurationProperties(prefix = "federation")
+public class FederationInterfaceConfiguration extends InterfaceConfiguration {
+
+}
@@ -18,7 +18,7 @@
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.common;
+package org.acumos.federation.gateway.config;
 
 import org.springframework.context.annotation.Condition;
 import org.springframework.context.annotation.ConditionContext;
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/config/GatewayConfiguration.java b/gateway/src/main/java/org/acumos/federation/gateway/config/GatewayConfiguration.java
new file mode 100644 (file)
index 0000000..d19c06a
--- /dev/null
@@ -0,0 +1,86 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Profile;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import org.acumos.federation.gateway.service.CatalogService;
+import org.acumos.federation.gateway.service.PeerSubscriptionService;
+import org.acumos.federation.gateway.service.PeerService;
+
+import org.acumos.federation.gateway.service.impl.CatalogServiceImpl;
+import org.acumos.federation.gateway.service.impl.PeerSubscriptionServiceImpl;
+import org.acumos.federation.gateway.service.impl.PeerServiceImpl;
+import org.acumos.federation.gateway.common.Clients;
+
+import org.acumos.federation.gateway.adapter.PeerGateway;
+
+import org.acumos.federation.gateway.task.TaskConfiguration;
+
+
+/**
+ * Specifies common configuration required by the federation gateway.
+ * Lists/provides all the beans required in running a federation gateway.
+ */
+@Configuration
+//@EnableAutoConfiguration
+@Import(TaskConfiguration.class)
+@EnableConfigurationProperties({FederationInterfaceConfiguration.class,
+                                                                                                                               LocalInterfaceConfiguration.class})
+//@Profile({"gateway"})
+@Conditional({GatewayCondition.class})
+@EnableScheduling
+public class GatewayConfiguration {
+
+       @Bean
+       public PeerGateway gateway() {
+               return new PeerGateway();
+       }
+
+       @Bean
+       public CatalogService catalogService() {
+               return new CatalogServiceImpl();
+       }
+
+       @Bean
+       public PeerService peerService() {
+               return new PeerServiceImpl();
+       }
+       
+       @Bean
+       public PeerSubscriptionService peerSubscriptionService() {
+               return new PeerSubscriptionServiceImpl();
+       }
+
+       @Bean
+       public Clients clients() {
+               return new Clients();
+       }
+
+}
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.common;
+package org.acumos.federation.gateway.config;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import java.net.URI;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+
+import java.security.KeyStore;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.stereotype.Component;
 import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
+import org.springframework.boot.context.embedded.Ssl;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Scope;
@@ -29,18 +49,14 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ResourceLoader;
 import org.springframework.core.io.DefaultResourceLoader;
 
-import java.net.URI;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-
-import java.security.KeyStore;
-
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
 import org.apache.http.client.HttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.protocol.HttpContext;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.config.Registry;
@@ -58,46 +74,72 @@ import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
 //import org.apache.http.ssl.SSLContextBuilder;
 import org.apache.http.conn.ssl.SSLContexts;
 import org.apache.http.conn.ssl.SSLContextBuilder;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+
+
+import org.apache.catalina.connector.Connector;
+import org.apache.coyote.http11.Http11NioProtocol;
 
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 
-@Configuration
-// @PropertySource("classpath:configprops.properties")
-@ConfigurationProperties(prefix = "client")
-public class HttpClientConfiguration {
+@Component
+public class InterfaceConfiguration {
 
        @Autowired
        private ResourceLoader resourceLoader;
 
        protected final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
 
-       private String username;
-       private String passwd;
-       private int poolSize = 10;
-       private SSL ssl;
+       //private int poolSize = 10;
+
+       private String                  address;
+       private InetAddress     inetAddress;
+       private SSL             ssl;
+       private Client  client;
+       private Server  server; 
+
+       public InterfaceConfiguration() {
+               log.info(EELFLoggerDelegate.debugLogger, this + "::new");
+       }
+
+/*
+       public int getPoolSize() {
+               return this.poolSize;
+       }
 
-       public String getUsername() {
-               return this.username;
+       public void setPoolSize(int thePoolSize) {
+               this.poolSize = thePoolSize;
+       }
+*/
+       @PostConstruct
+       public void initInterface() {
+               log.info(EELFLoggerDelegate.debugLogger, this + "::init");
+       }       
+
+       public String getAddress() {
+               return this.address;
        }
 
-       public void setUsername(String theUsername) {
-               this.username = theUsername;
+       public void setAddress(String theAddress) throws UnknownHostException {
+               this.inetAddress = InetAddress.getByName(theAddress);
+               this.address = theAddress;
        }
 
-       public String getPassword() {
-               return this.username;
+       public Client getClient() {
+               return this.client;
        }
 
-       public void setPassword(String thePassword) {
-               this.passwd = thePassword;
+       public void setClient(Client theClient) {
+               this.client = theClient;
        }
 
-       public int getPoolSize() {
-               return this.poolSize;
+       public Server getServer() {
+               return this.server;
        }
 
-       public void setPoolSize(int thePoolSize) {
-               this.poolSize = thePoolSize;
+       public void setServer(Server theServer) {
+               this.server = theServer;
        }
 
        public SSL getSSL() {
@@ -108,6 +150,69 @@ public class HttpClientConfiguration {
                this.ssl = theSSL;
        }
 
+       protected boolean hasSSL() {
+               return this.ssl != null;
+       }
+
+       protected boolean hasServer() {
+               return this.server != null;
+       }
+
+       protected boolean hasClient() {
+               return this.client != null &&
+                                        this.client.getUsername() != null &&
+                                        this.client.getPassword() != null;
+       }
+
+       protected boolean hasAddress() {
+               return this.address != null;
+       }
+
+       /**
+        */
+       public static class Client {
+
+               private String username;
+               private String passwd;
+
+               public String getUsername() {
+                       return this.username;
+               }
+
+               public void setUsername(String theUsername) {
+                       this.username = theUsername;
+               }
+
+               public String getPassword() {
+                       return this.username;
+               }
+
+               public void setPassword(String thePassword) {
+                       this.passwd = thePassword;
+               }
+
+       }
+
+       /**
+        */
+       public static class Server {
+       
+               private int             port;
+       
+               public int getPort() {
+                       return this.port;
+               }
+
+               public void setPort(int thePort) {
+                       this.port = thePort;
+               }
+
+       }
+
+       /**
+        * Security information for this endpoint, applies to both client and server
+        * usage.
+        */
        public static class SSL {
 
                private String keyStore;
@@ -117,6 +222,7 @@ public class HttpClientConfiguration {
                private String trustStore;
                private String trustStoreType = "JKS";
                private String trustStorePasswd;
+               private String clientAuth = "need";
 
                public String getKeyStore() {
                        return this.keyStore;
@@ -184,6 +290,14 @@ public class HttpClientConfiguration {
                                                                                                                                                         */;
                }
 
+               public String getClientAuth() {
+                       return this.clientAuth;
+               }
+
+               public void setClientAuth(String theClientAuth) {
+                       this.clientAuth = theClientAuth;
+               }
+
                public String toString() {
                        return new StringBuilder("").append("SSL(").append(this.keyStore).append(",").append(this.keyStoreType)
                                        .append(",").append(this.keyAlias).append("/").append(this.trustStore).append(",")
@@ -192,7 +306,79 @@ public class HttpClientConfiguration {
        }
 
        public String toString() {
-               return new StringBuilder("").append("ClientConfiguration(").append(this.ssl).append(")").toString();
+               return new StringBuilder("")
+                       .append(super.toString())
+                       .append("(")
+                       .append(this.address)
+                       .append(",")
+                       .append(this.server)
+                       .append(",")
+                       .append(this.ssl)
+                       .append(")")
+                       .toString();
+       }
+
+       /**
+        * Configure the existing/default/a servlet container with the configuration
+        * information of this interface.
+        * @param theContainer the servlet container to be configured
+        * @return ConfigurableEmbeddedServletContainer the container, configured
+        */
+       public ConfigurableEmbeddedServletContainer configureContainer(
+                                                                               ConfigurableEmbeddedServletContainer theContainer) {
+               if (hasServer()) {
+                       theContainer.setPort(this.server.getPort());
+               }
+               if (hasAddress()) {
+                       theContainer.setAddress(this.inetAddress);
+               }
+               if (hasSSL()) {
+                       Ssl cssl = new Ssl();
+                       cssl.setEnabled(true);
+                       cssl.setProtocol("TLSv1.2");
+                       cssl.setKeyStore(this.ssl.getKeyStore());
+                       cssl.setKeyStorePassword(this.ssl.getKeyStorePassword());
+                       cssl.setKeyStoreType(this.ssl.getKeyStoreType());
+                       cssl.setTrustStore(this.ssl.getTrustStore());
+                       cssl.setTrustStorePassword(this.ssl.getTrustStorePassword());
+                       cssl.setTrustStoreType(this.ssl.getTrustStoreType());
+                       cssl.setKeyAlias(this.ssl.getKeyAlias());
+                       cssl.setClientAuth(Ssl.ClientAuth.valueOf(this.ssl.clientAuth.toUpperCase()));
+                       theContainer.setSsl(cssl);
+               }
+               return theContainer;
+       }
+
+       /**
+        * Build a tomcat connector (server) based on the configuration information.
+        *
+        * Should we even allow the constrcution of a non-secure connector ?
+        *
+        * @return tomcat nio connector
+        */
+       public Connector buildConnector() {
+
+               if (!hasServer()) {
+                       throw new IllegalArgumentException("No server information available");
+               }
+
+               Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
+               Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
+               connector.setScheme(hasSSL() ? "https" : "http");
+               connector.setSecure(hasSSL());
+               connector.setPort(this.server.getPort());
+               if (hasAddress()) {
+                       protocol.setAddress(this.inetAddress);
+               }
+               if (hasSSL()) {
+                       protocol.setSSLEnabled(true);
+                       protocol.setKeystoreFile(this.ssl.getKeyStore());
+                       protocol.setKeystorePass(this.ssl.getKeyStorePassword());
+                       protocol.setTruststoreFile(this.ssl.getTrustStore());
+                       protocol.setTruststorePass(this.ssl.getTrustStorePassword());
+                       protocol.setKeyAlias(this.ssl.getKeyAlias());
+               }
+               return connector;
        }
 
        public HttpClient buildClient() {
@@ -208,26 +394,56 @@ public class HttpClientConfiguration {
                } else {
                        KeyStore keyStore = null;
                        if (this.ssl.hasKeyStoreInfo()) {
+                               InputStream keyStoreSource = null;
+                               try {
+                                       keyStoreSource = this.resourceLoader.getResource(this.ssl.keyStore).getURL().openStream();
+                               }
+                               catch (FileNotFoundException rnfx) {
+                                       try {
+                                               keyStoreSource = new FileInputStream(this.ssl.keyStore);
+                                       }
+                                       catch (FileNotFoundException fnfx) {
+                                               throw new IllegalStateException("Failed to find key store " + this.ssl.keyStore);
+                                       }
+                               }
+                               catch (IOException iox) {
+                                       throw new IllegalStateException("Error loading key material: " + iox, iox);
+                               }
+
                                try {
                                        keyStore = KeyStore.getInstance(this.ssl.keyStoreType);
-                                       keyStore.load(this.resourceLoader.getResource(this.ssl.keyStore).getURL().openStream(),
-                                                       // new URI(this.ssl.keyStore).toURL().openStream(),
-                                                       this.ssl.keyStorePasswd.toCharArray());
+                                       keyStore.load(keyStoreSource,   this.ssl.keyStorePasswd.toCharArray());
                                        log.info(EELFLoggerDelegate.debugLogger, "Loaded key store: " + this.ssl.keyStore);
-                               } catch (Exception x) {
+                               }
+                               catch (Exception x) {
                                        throw new IllegalStateException("Error loading key material: " + x, x);
                                }
                        }
 
                        KeyStore trustStore = null;
                        if (this.ssl.hasTrustStoreInfo()) {
+                               InputStream trustStoreSource = null;
+                               try {
+                                       trustStoreSource = this.resourceLoader.getResource(this.ssl.trustStore).getURL().openStream();
+                               }
+                               catch (FileNotFoundException rnfx) {
+                                       try {
+                                               trustStoreSource = new FileInputStream(this.ssl.trustStore);
+                                       }
+                                       catch (FileNotFoundException fnfx) {
+                                               throw new IllegalStateException("Failed to find trust store " + this.ssl.keyStore);
+                                       }
+                               }
+                               catch (IOException iox) {
+                                       throw new IllegalStateException("Error loading trust material: " + iox, iox);
+                               }
+
                                try {
                                        trustStore = KeyStore.getInstance(this.ssl.trustStoreType);
-                                       trustStore.load(this.resourceLoader.getResource(this.ssl.trustStore).getURL().openStream(),
-                                                       // new URI(this.ssl.trustStore).toURL().openStream(),
-                                                       this.ssl.trustStorePasswd.toCharArray());
+                                       trustStore.load(trustStoreSource,       this.ssl.trustStorePasswd.toCharArray());
                                        log.info(EELFLoggerDelegate.debugLogger, "Loaded trust store: " + this.ssl.trustStore);
-                               } catch (Exception x) {
+                               }
+                               catch (Exception x) {
                                        throw new IllegalStateException("Error loading trust material: " + x, x);
                                }
                        }
@@ -276,9 +492,9 @@ public class HttpClientConfiguration {
                 */
 
                CredentialsProvider credsProvider = null;
-               if (this.username != null && this.passwd != null) {
+               if (hasClient()) {
                        credsProvider = new BasicCredentialsProvider();
-                       credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(this.username, this.passwd));
+                       credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(this.client.getUsername(), this.client.getPassword()));
                        log.info(EELFLoggerDelegate.debugLogger, "Credentials configured");
                } else {
                        log.info(EELFLoggerDelegate.debugLogger, "No credentials were provided");
@@ -295,6 +511,15 @@ public class HttpClientConfiguration {
                if (credsProvider != null)
                        clientBuilder.setDefaultCredentialsProvider(credsProvider);
 
+               if (hasAddress()) {
+                       clientBuilder.setRoutePlanner(
+                               new HttpRoutePlanner() {
+                                       public HttpRoute determineRoute(HttpHost theTarget, HttpRequest theRequest, HttpContext theContext) {
+                                               return new HttpRoute(theTarget, InterfaceConfiguration.this.inetAddress, hasSSL());
+                                       }
+                               });
+               }
+
                return clientBuilder.build();
        }
 }
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.common;
+package org.acumos.federation.gateway.config;
 
-public class HttpClientConfigurationBuilder
+public class InterfaceConfigurationBuilder
 // <A extends HttpClientConfigurationBuilder<A,T>,
 // T extends HttpClientConfiguration>
 {
 
-       private /* T */HttpClientConfiguration config = newConfig();
+       private /* T */InterfaceConfiguration config = newConfig();
 
-       protected /* A */HttpClientConfigurationBuilder builder() {
+       protected /* A */InterfaceConfigurationBuilder builder() {
                return this;
        }
 
-       protected /* T */HttpClientConfiguration newConfig() {
-               return new HttpClientConfiguration();
+       protected /* T */InterfaceConfiguration newConfig() {
+               return new InterfaceConfiguration();
        }
 
-       public /* T */HttpClientConfiguration buildConfig() {
+       public /* T */InterfaceConfiguration buildConfig() {
                return this.config;
        }
 
-       public HttpClientConfigurationBuilder/* A */ withUsername(String theUsername) {
-               this.config.setUsername(theUsername);
-               return builder();
-       }
-
-       public HttpClientConfigurationBuilder/* A */ withPassword(String thePassword) {
-               this.config.setPassword(thePassword);
-               return builder();
-       }
-
-       public HttpClientConfigurationBuilder/* A */ withPoolSize(int thePoolSize) {
-               this.config.setPoolSize(thePoolSize);
-               return builder();
-       }
-
-       public HttpClientConfigurationBuilder/* A */ withSSL(HttpClientConfiguration.SSL theSSL) {
+       public InterfaceConfigurationBuilder/* A */ withSSL(InterfaceConfiguration.SSL theSSL) {
                this.config.setSSL(theSSL);
                return builder();
        }
 
+       /** */
        public static class SSLBuilder {
 
-               private HttpClientConfiguration.SSL ssl = new HttpClientConfiguration.SSL();
+               private InterfaceConfiguration.SSL ssl = new InterfaceConfiguration.SSL();
 
                public SSLBuilder withKeyStore(String theKeyStore) {
                        this.ssl.setKeyStore(theKeyStore);
@@ -98,7 +84,7 @@ public class HttpClientConfigurationBuilder
                        return this;
                }
 
-               public HttpClientConfiguration.SSL build() {
+               public InterfaceConfiguration.SSL build() {
                        return this.ssl;
                }
        }
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/config/LocalConfiguration.java b/gateway/src/main/java/org/acumos/federation/gateway/config/LocalConfiguration.java
new file mode 100644 (file)
index 0000000..d1c847f
--- /dev/null
@@ -0,0 +1,118 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+
+import org.apache.http.client.HttpClient;
+
+import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
+import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
+import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
+
+
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.controller.PeerPingController;
+import org.acumos.federation.gateway.controller.PeerCatalogController;
+import org.acumos.federation.gateway.controller.PeerSubscriptionController;
+import org.acumos.federation.gateway.security.AuthenticationConfiguration;
+
+/**
+ * Provides the neans used in interactions with the local Acumos system
+ */
+@Configuration
+@Import(AuthenticationConfiguration.class)
+@EnableAutoConfiguration
+//@ConfigurationProperties(prefix = "local", ignoreInvalidFields = true)
+public class LocalConfiguration /* implements ApplicationContextAware */ {
+
+       @Autowired
+       private LocalInterfaceConfiguration interfaceConfig;
+       private EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
+
+       public LocalConfiguration() {
+       }
+
+       @Bean
+       public PeerPingController peerPingServer() {
+               return new PeerPingController();
+       }
+
+       @Bean
+       public PeerCatalogController peerCatalogServer() {
+               return new PeerCatalogController();
+       }
+
+       @Bean
+       public PeerSubscriptionController peerSubscriptionServer() {
+               return new PeerSubscriptionController();
+       }
+       /**
+   * Build a client for interacting with other local Acumos components
+        * through the local interface.
+        * We assume the same configuration takes place for client and server
+        * roles when interacting with peers: we'll assume the same identity, use the
+        * same network interface, etc. If this ever needs to change we can pick
+        * the values from a separate configuration properties set.
+        */
+       @Bean
+  @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+       public HttpClient localClient() {
+               log.debug(EELFLoggerDelegate.debugLogger, this + "::localClient from " + this.interfaceConfig);
+               return interfaceConfig.buildClient();
+       }
+
+       /**
+        * Build a servlet container running on the local interface for serving
+        * local interface requests (see controllers built here).
+        */
+       /*
+       @Bean
+       public EmbeddedServletContainerFactory localServer() {
+               TomcatEmbeddedServletContainerFactory tomcat =
+                       new TomcatEmbeddedServletContainerFactory();
+               tomcat.addAdditionalTomcatConnectors(this.interfaceConfig.buildConnector());
+               return tomcat;
+       }
+       */
+
+       @Bean
+       public EmbeddedServletContainerCustomizer localServer() {
+               log.debug(EELFLoggerDelegate.debugLogger, this + "::localServer from " + this.interfaceConfig);
+               return new EmbeddedServletContainerCustomizer() {
+                       @Override
+                       public void customize(ConfigurableEmbeddedServletContainer theContainer) {
+                               LocalConfiguration.this.interfaceConfig.configureContainer(theContainer);
+                       }
+               };
+       } 
+       
+}
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.common;
+package org.acumos.federation.gateway.config;
 
+import org.springframework.stereotype.Component;
 import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
 
-@Configuration
-@EnableConfigurationProperties({ FederationClientConfiguration.class })
-public class GatewayConfiguration {
+/**
+ * Defines a specific external configuration prefix for the local interface.
+ */
+@Component
+@ConfigurationProperties(prefix = "local")
+public class LocalInterfaceConfiguration extends InterfaceConfiguration {
 
 }
index 9400e1e..1d2d6ea 100644 (file)
@@ -59,7 +59,7 @@ import io.swagger.annotations.ApiOperation;
  *
  */
 @Controller
-@RequestMapping("/")
+@RequestMapping(API.Roots.FEDERATION)
 public class CatalogController extends AbstractController {
 
        private static final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(CatalogController.class.getName());
@@ -85,7 +85,7 @@ public class CatalogController extends AbstractController {
                        HttpServletResponse theHttpResponse,
                        @RequestParam(value = API.QueryParameters.SOLUTIONS_SELECTOR, required = false) String theSelector) {
                JsonResponse<List<MLPSolution>> response = null;
-               List<MLPSolution> peerCatalogSolutions = null;
+               List<MLPSolution> solutions = null;
                log.debug(EELFLoggerDelegate.debugLogger, API.Paths.SOLUTIONS);
                try {
                        response = new JsonResponse<List<MLPSolution>>();
@@ -94,22 +94,20 @@ public class CatalogController extends AbstractController {
                        if (theSelector != null)
                                selector = Utils.jsonStringToMap(new String(Base64Utils.decodeFromString(theSelector), "UTF-8"));
 
-                       peerCatalogSolutions = catalogService.getSolutions(selector, new ControllerContext());
-                       if (peerCatalogSolutions != null) {
-                               response.setResponseBody(peerCatalogSolutions);
-                               response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
-                               response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
-                               response.setStatus(true);
-                               theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                               log.debug(EELFLoggerDelegate.debugLogger, "getSolutions: size is " + peerCatalogSolutions.size());
-                       }
-               } catch (Exception e) {
-                       response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
-                       response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
-                       response.setStatus(false);
-                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       log.error(EELFLoggerDelegate.errorLogger, "Exception occurred fetching Solutions for Market Place Catalog",
-                                       e);
+                       solutions = catalogService.getSolutions(selector, new ControllerContext());
+                       response = JsonResponse.<List<MLPSolution>> buildResponse()
+                                                                                                               .withMessage("available public solution for given filter")
+                                                                                                               .withContent(solutions)
+                                                                                                               .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+                       log.debug(EELFLoggerDelegate.debugLogger, "getSolutions: provided {} solutions", solutions == null ? 0 : solutions.size());
+               }
+               catch (Exception x) {
+                       response = JsonResponse.<List<MLPSolution>> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "Exception occurred fetching Solutions for Market Place Catalog", x);
                }
                return response;
        }
@@ -125,21 +123,19 @@ public class CatalogController extends AbstractController {
                MLPSolution solution = null;
                log.debug(EELFLoggerDelegate.debugLogger, API.Paths.SOLUTION_DETAILS + ": " + theSolutionId);
                try {
-                       response = new JsonResponse<MLPSolution>();
                        solution = catalogService.getSolution(theSolutionId, new ControllerContext());
-                       if (solution != null) {
-                               response.setResponseBody(solution);
-                               response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
-                               response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
-                               response.setStatus(true);
-                               theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                       }
-               } catch (Exception e) {
-                       response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
-                       response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
-                       response.setStatus(false);
-                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       log.error(EELFLoggerDelegate.errorLogger, "An error occurred fetching solution " + theSolutionId, e);
+                       response = JsonResponse.<MLPSolution> buildResponse()
+                                                                                                               .withMessage("solution details")
+                                                                                                               .withContent(solution)
+                                                                                                               .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+               }
+               catch (Exception x) {
+                       response = JsonResponse.<MLPSolution> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error occurred while fetching solution " + theSolutionId, x);
                }
                return response;
        }
@@ -162,23 +158,21 @@ public class CatalogController extends AbstractController {
                List<MLPSolutionRevision> solutionRevisions = null;
                log.debug(EELFLoggerDelegate.debugLogger, API.Paths.SOLUTION_REVISIONS);
                try {
-                       response = new JsonResponse<List<MLPSolutionRevision>>();
                        solutionRevisions = catalogService.getSolutionRevisions(theSolutionId, new ControllerContext());
-                       if (solutionRevisions != null) {
-                               response.setResponseBody(solutionRevisions);
-                               response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
-                               response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
-                               response.setStatus(true);
-                               theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                               log.debug(EELFLoggerDelegate.debugLogger, "getSolutionsRevisions: size is {} ",
-                                               solutionRevisions.size());
-                       }
-               } catch (Exception e) {
-                       response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
-                       response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
-                       response.setStatus(false);
-                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       log.error(EELFLoggerDelegate.errorLogger, "Exception Occurred Fetching Solution Revisions", e);
+                       response = JsonResponse.<List<MLPSolutionRevision>> buildResponse()
+                                                                                                               .withMessage("solution revisions")
+                                                                                                               .withContent(solutionRevisions)
+                                                                                                               .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+                       log.debug(EELFLoggerDelegate.debugLogger, "getSolutionsRevisions for solution {} provided {} revisions",
+                                               theSolutionId, solutionRevisions == null ? 0 : solutionRevisions.size());
+               }
+               catch (Exception x) {
+                       response = JsonResponse.<List<MLPSolutionRevision>> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error occured while fetching solution " + theSolutionId + " revisions", x);
                }
                return response;
        }
@@ -195,7 +189,7 @@ public class CatalogController extends AbstractController {
         */
        @CrossOrigin
        @PreAuthorize("hasAuthority('CATALOG_ACCESS')")
-       @ApiOperation(value = "Invoked by Peer Acumos to get Solution Revision details from the Catalog of the local Acumos Instance .", response = MLPSolutionRevision.class)
+       @ApiOperation(value = "Invoked by peer Acumos to get solution revision details from the local Acumos Instance .", response = MLPSolutionRevision.class)
        @RequestMapping(value = {
                        API.Paths.SOLUTION_REVISION_DETAILS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
@@ -206,22 +200,20 @@ public class CatalogController extends AbstractController {
                log.debug(EELFLoggerDelegate.debugLogger,
                                API.Paths.SOLUTION_REVISION_DETAILS + "(" + theSolutionId + "," + theRevisionId + ")");
                try {
-                       response = new JsonResponse<MLPSolutionRevision>();
                        solutionRevision = catalogService.getSolutionRevision(theSolutionId, theRevisionId,
                                        new ControllerContext());
-                       if (solutionRevision != null) {
-                               response.setResponseBody(solutionRevision);
-                               response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
-                               response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
-                               response.setStatus(true);
-                               theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                       }
-               } catch (Exception e) {
-                       response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
-                       response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
-                       response.setStatus(false);
-                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       log.error(EELFLoggerDelegate.errorLogger, "Exception Occurred Fetching Solution Revision", e);
+                       response = JsonResponse.<MLPSolutionRevision> buildResponse()
+                                                                                                               .withMessage("solution revision details")
+                                                                                                               .withContent(solutionRevision)
+                                                                                                               .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+               }
+               catch (Exception x) {
+                       response = JsonResponse.<MLPSolutionRevision> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error occured while fetching solution " + theSolutionId + " revision " + theRevisionId + " details", x);
                }
                return response;
        }
@@ -239,7 +231,7 @@ public class CatalogController extends AbstractController {
         */
        @CrossOrigin
        @PreAuthorize("hasAuthority('CATALOG_ACCESS')")
-       @ApiOperation(value = "Invoked by Peer Acumos to get a list of Solution Revision Artifacts from the Catalog of the local Acumos Instance .", response = MLPArtifact.class, responseContainer = "List")
+       @ApiOperation(value = "Invoked by Peer Acumos to get a list of solution revision artifacts from the local Acumos Instance .", response = MLPArtifact.class, responseContainer = "List")
        @RequestMapping(value = {
                        API.Paths.SOLUTION_REVISION_ARTIFACTS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
@@ -248,42 +240,41 @@ public class CatalogController extends AbstractController {
                        @PathVariable("revisionId") String theRevisionId) {
                JsonResponse<List<MLPArtifact>> response = null;
                List<MLPArtifact> solutionRevisionArtifacts = null;
+               ControllerContext context = new ControllerContext();
                log.debug(EELFLoggerDelegate.debugLogger,
                                API.Paths.SOLUTION_REVISION_ARTIFACTS + "(" + theSolutionId + "," + theRevisionId + ")");
                try {
                        response = new JsonResponse<List<MLPArtifact>>();
-                       solutionRevisionArtifacts = catalogService.getSolutionRevisionArtifacts(theSolutionId, theRevisionId,
-                                       new ControllerContext());
-                       if (solutionRevisionArtifacts != null) {
+                       solutionRevisionArtifacts = catalogService.getSolutionRevisionArtifacts(theSolutionId, theRevisionId, context);
+                       if (solutionRevisionArtifacts != null &&
+                                       !context.getPeer().getPeerInfo().isLocal()) {
                                // re-encode the artifact uri
-                               {
-                                       for (MLPArtifact artifact : solutionRevisionArtifacts) {
-                                               // sooo cumbersome
-                                               URI requestUri = new URI(theHttpRequest.getRequestURL().toString());
-                                               URI artifactUri = API.ARTIFACT_DOWNLOAD
-                                                               .buildUri(
-                                                                               new URI(requestUri.getScheme(), null, requestUri.getHost(),
-                                                                                               requestUri.getPort(), null, null, null).toString(),
-                                                                               artifact.getArtifactId());
-                                               log.debug(EELFLoggerDelegate.debugLogger,
-                                                               "getSolutionRevisionArtifacts: content uri " + artifactUri);
-                                               artifact.setUri(artifactUri.toString());
-                                       }
+                               for (MLPArtifact artifact : solutionRevisionArtifacts) {
+                                       // sooo cumbersome
+                                       URI requestUri = new URI(theHttpRequest.getRequestURL().toString());
+                                       URI artifactUri = API.ARTIFACT_DOWNLOAD
+                                                       .buildUri(
+                                                                       new URI(requestUri.getScheme(), null, requestUri.getHost(),
+                                                                                       requestUri.getPort(), null, null, null).toString(),
+                                                                       artifact.getArtifactId());
+                                       log.debug(EELFLoggerDelegate.debugLogger,       "getSolutionRevisionArtifacts: content uri " + artifactUri);
+                                       artifact.setUri(artifactUri.toString());
                                }
-                               response.setResponseBody(solutionRevisionArtifacts);
-                               response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
-                               response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
-                               response.setStatus(true);
-                               theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                               log.debug(EELFLoggerDelegate.debugLogger, "getSolutionRevisionArtifacts: size is {} ",
-                                               solutionRevisionArtifacts.size());
                        }
-               } catch (Exception e) {
-                       response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
-                       response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
-                       response.setStatus(false);
-                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       log.error(EELFLoggerDelegate.errorLogger, "Failed to fetch solution revision artifacts", e);
+                       response = JsonResponse.<List<MLPArtifact>> buildResponse()
+                                                                                                       .withMessage("solution revision artifacts")
+                                                                                                       .withContent(solutionRevisionArtifacts)
+                                                                                                       .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+                       log.debug(EELFLoggerDelegate.debugLogger, "getSolutionRevisionArtifacts provided {} artifacts",
+                                               solutionRevisionArtifacts == null ? 0 : solutionRevisionArtifacts.size());
+               } 
+               catch (Exception x) {
+                       response = JsonResponse.<List<MLPArtifact>> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error occured while fetching solution " + theSolutionId + " revision " + theRevisionId + " artifacts", x);
                }
                return response;
        }
@@ -313,10 +304,11 @@ public class CatalogController extends AbstractController {
                        theHttpResponse.setHeader("Pragma", "no-cache");
                        theHttpResponse.setHeader("Expires", "0");
                        theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-               } catch (Exception e) {
-                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+               } 
+               catch (Exception x) {
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        log.error(EELFLoggerDelegate.errorLogger,
-                                       "Exception Occurred downloading a artifact for a Solution in Market Place Catalog", e);
+                                       "An error occurred while downloading artifact " + theArtifactId, x);
                }
                return inputStreamResource;
        }
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/controller/PeerCatalogController.java b/gateway/src/main/java/org/acumos/federation/gateway/controller/PeerCatalogController.java
new file mode 100644 (file)
index 0000000..b8c2d83
--- /dev/null
@@ -0,0 +1,137 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.controller;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.acumos.cds.domain.MLPPeer;
+import org.acumos.cds.domain.MLPSolution;
+import org.acumos.federation.gateway.common.API;
+import org.acumos.federation.gateway.common.Clients;
+import org.acumos.federation.gateway.common.JSONTags;
+import org.acumos.federation.gateway.common.JsonResponse;
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.security.Peer;
+import org.acumos.federation.gateway.service.PeerService;
+import org.acumos.federation.gateway.service.ServiceContext;
+import org.acumos.federation.gateway.util.Utils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.http.MediaType;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.Base64Utils;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * Provides an interface for the local Acumos components to query a peer's catalog.
+ * Limited to solution level information. 
+ *
+ */
+@Controller
+@RequestMapping(API.Roots.LOCAL)
+public class PeerCatalogController extends AbstractController {
+
+       @Autowired
+       private Clients clients;
+       @Autowired
+       private PeerService peerService;
+
+       /**
+        * Provides access 
+        * @param theHttpResponse
+        *            HttpServletResponse
+        * @param theSelector
+        *            Solutions selector
+        * @return List of Published ML Solutions in JSON format.
+        */
+       @CrossOrigin
+       @PreAuthorize("hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).PEER_ACCESS)")
+       @ApiOperation(value = "Invoked by local Acumos to get a list of solutions available from a peer Acumos instance .", response = MLPSolution.class, responseContainer = "List")
+       @RequestMapping(value = { API.Paths.SOLUTIONS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @ResponseBody
+       public JsonResponse<List<MLPSolution>> getSolutions(
+                       /* HttpServletRequest theHttpRequest, */
+                       HttpServletResponse theHttpResponse,
+                       @PathVariable("peerId") String thePeerId,
+                       @RequestParam(value = API.QueryParameters.SOLUTIONS_SELECTOR, required = false) String theSelector) {
+               log.debug(EELFLoggerDelegate.debugLogger, API.Roots.LOCAL + "" + API.Paths.SOLUTIONS);
+               JsonResponse<List<MLPSolution>> response = null;
+               try {
+                       MLPPeer peer = this.peerService.getPeerById(thePeerId);
+                       Map<String, Object> selector = null;
+                       if (theSelector != null)
+                               selector = Utils.jsonStringToMap(new String(Base64Utils.decodeFromString(theSelector), "UTF-8"));
+                       response = this.clients.getFederationClient(peer.getApiUrl()).getSolutions(selector);
+                       
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+               }
+               //catch (ServiceException sx) {}
+               catch (Exception x) {
+                       response = JsonResponse.<List<MLPSolution>> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error occurred while processing a local peer solutions request for peer " + thePeerId, x);
+               }
+               return response;
+       }
+
+       @CrossOrigin
+       @PreAuthorize("hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).PEER_ACCESS)")
+       @ApiOperation(value = "Invoked by local Acumos to get detailed solution information from the catalog of a peer acumos Instance.", response = MLPSolution.class)
+       @RequestMapping(value = { API.Paths.SOLUTION_DETAILS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @ResponseBody
+       public JsonResponse<MLPSolution> getSolutionDetails(
+                       HttpServletResponse theHttpResponse,
+                       @PathVariable("peerId") String thePeerId,
+                       @PathVariable(value = "solutionId") String theSolutionId) {
+               log.debug(EELFLoggerDelegate.debugLogger, API.Roots.LOCAL + "" + API.Paths.SOLUTION_DETAILS);
+               JsonResponse<MLPSolution> response = null;
+               try {
+                       MLPPeer peer = this.peerService.getPeerById(thePeerId);
+                       response = this.clients.getFederationClient(peer.getApiUrl()).getSolution(theSolutionId);
+                       
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+               }
+               catch (Exception x) {
+                       response = JsonResponse.<MLPSolution> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error occurred while fetching solution " + theSolutionId + " from peer " + thePeerId, x);
+               }
+               return response;
+       }
+}
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/controller/PeerPingController.java b/gateway/src/main/java/org/acumos/federation/gateway/controller/PeerPingController.java
new file mode 100644 (file)
index 0000000..0c10750
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.controller;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.acumos.cds.domain.MLPPeer;
+import org.acumos.federation.gateway.common.API;
+import org.acumos.federation.gateway.common.Clients;
+import org.acumos.federation.gateway.common.JSONTags;
+import org.acumos.federation.gateway.common.JsonResponse;
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.security.Peer;
+import org.acumos.federation.gateway.service.PeerService;
+import org.acumos.federation.gateway.service.ServiceContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import io.swagger.annotations.ApiOperation;
+
+@Controller
+@RequestMapping(API.Roots.LOCAL)
+public class PeerPingController extends AbstractController {
+
+       @Autowired
+       private Clients clients;
+       @Autowired
+       private PeerService peerService;
+       
+
+       /**
+        * Allows local components to ping a peer.
+        * @param theHttpResponse
+        *            HttpServletResponse
+        * @return The remote peer information
+        */
+       @CrossOrigin
+       @PreAuthorize("hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).PEER_ACCESS)")
+       @ApiOperation(value = "Invoked by local Acumos to get peer Acumos status and information.", response = MLPPeer.class)
+       @RequestMapping(value = { API.Paths.PING }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @ResponseBody
+       public JsonResponse<MLPPeer> ping(
+                       /* HttpServletRequest theHttpRequest, */
+                       HttpServletResponse theHttpResponse,
+                       @PathVariable("peerId") String thePeerId) {
+
+               JsonResponse<MLPPeer> response = new JsonResponse<MLPPeer>();
+               log.debug(EELFLoggerDelegate.debugLogger, API.Roots.LOCAL + "" + API.Paths.PING);
+               try {
+                       MLPPeer peer = this.peerService.getPeerById(thePeerId);
+                       response = this.clients.getFederationClient(peer.getApiUrl()).ping();
+
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+               } 
+               catch (Exception x) {
+                       response = JsonResponse.<MLPPeer> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "Exception occurred during peer ping", x);
+               }
+               return response;
+       }
+
+}
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/controller/PeerSubscriptionController.java b/gateway/src/main/java/org/acumos/federation/gateway/controller/PeerSubscriptionController.java
new file mode 100644 (file)
index 0000000..d27e560
--- /dev/null
@@ -0,0 +1,112 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.controller;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.acumos.cds.domain.MLPPeer;
+import org.acumos.cds.domain.MLPPeerSubscription;
+
+import org.acumos.federation.gateway.common.API;
+import org.acumos.federation.gateway.common.JsonResponse;
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.security.Peer;
+import org.acumos.federation.gateway.service.PeerService;
+import org.acumos.federation.gateway.service.PeerSubscriptionService;
+import org.acumos.federation.gateway.service.ServiceContext;
+import org.acumos.federation.gateway.task.PeerSubscriptionTaskScheduler;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * Servivr offered to local components allowing then to trigger the execution of a subscription.
+ */
+@Controller
+@RequestMapping(API.Roots.LOCAL)
+public class PeerSubscriptionController extends AbstractController {
+
+       @Autowired
+       private PeerService peerService;
+
+       @Autowired
+       private PeerSubscriptionService peerSubscriptionService;
+
+       @Autowired
+       private ApplicationContext appCtx;
+
+       /**
+        * @param theHttpResponse
+        */
+       @CrossOrigin
+       @PreAuthorize("hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).PEER_ACCESS)")
+       @ApiOperation(value = "Invoked by other Acumos components in order to trigger subscription execution", response = String.class)
+       @RequestMapping(value = { API.Paths.SUBSCRIPTION }, method = RequestMethod.POST, produces = APPLICATION_JSON)
+       @ResponseBody
+       public JsonResponse<String> triggerPeerSubscription(
+                       /* HttpServletRequest theHttpRequest, */
+                       HttpServletResponse theHttpResponse,
+                       @PathVariable("peerId") String thePeerId,
+                       @PathVariable("subscriptionId") Long theSubscriptionId) {
+
+               log.debug(EELFLoggerDelegate.debugLogger, API.Roots.LOCAL + "" + API.Paths.SUBSCRIPTION);
+               JsonResponse<String> response = null;
+               try {
+                       response = new JsonResponse<String>();
+                       log.debug(EELFLoggerDelegate.debugLogger, "trigger");
+       
+                       MLPPeer peer = this.peerService.getPeerById(thePeerId);
+                       MLPPeerSubscription subscription = this.peerSubscriptionService.getPeerSubscription(theSubscriptionId);
+                       //coherence check
+                       //subscription.getPeerId().equals(thePeerId);
+
+                       ((PeerSubscriptionTaskScheduler)this.appCtx.getBean("peerSubscriptionTaskScheduler")).runOnce(peer, subscription);
+
+                       response = JsonResponse.<String> buildResponse()
+                                                                                                               .withContent("subscription execution triggered")
+                                                                                                               .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+                       log.debug(EELFLoggerDelegate.debugLogger, "subscription execution triggered");
+               } 
+               catch (Exception x) {
+                       response = JsonResponse.<String> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "On-demand subscription execution failed", x);
+               }
+               return response;
+       }
+
+}
@@ -44,15 +44,14 @@ import org.springframework.web.bind.annotation.ResponseBody;
 import io.swagger.annotations.ApiOperation;
 
 @Controller
-@RequestMapping("/")
-public class PeerController extends AbstractController {
-
-       private static final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(PeerController.class.getName());
+@RequestMapping(API.Roots.FEDERATION)
+public class PeersController extends AbstractController {
 
        @Autowired
        PeerService peerService;
 
        /**
+        * Basic built-in 'discovery' service.
         * @param theHttpResponse
         *            HttpServletResponse
         * @return List of Published ML Solutions in JSON format.
@@ -70,28 +69,20 @@ public class PeerController extends AbstractController {
                List<MLPPeer> peers = null;
                log.debug(EELFLoggerDelegate.debugLogger, API.Paths.PEERS);
                try {
-                       response = new JsonResponse<List<MLPPeer>>();
-                       log.debug(EELFLoggerDelegate.debugLogger, "getPeers");
-
                        peers = peerService.getPeers(new ControllerContext());
-                       /*
-                        * TODO: We only expose simple peers, not the partners. But we only serve this
-                        * service to parners so .. ?? No pb.
-                        */
-                       if (peers != null) {
-                               response.setResponseBody(peers);
-                               response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
-                               response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
-                               response.setStatus(true);
-                               theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                               log.debug(EELFLoggerDelegate.debugLogger, "getPeers: size is " + peers.size());
-                       }
-               } catch (Exception e) {
-                       response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
-                       response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
-                       response.setStatus(false);
-                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       log.error(EELFLoggerDelegate.errorLogger, "Exception Occurred Fetching Peers", e);
+                       response = JsonResponse.<List<MLPPeer>> buildResponse()
+                                                                                                                .withMessage("peers")
+                                                                                                                .withContent(peers)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+                       log.debug(EELFLoggerDelegate.debugLogger, "peers request provided {} peers.", peers == null ? 0 : peers.size());
+               } 
+               catch (Exception x) {
+                       response = JsonResponse.<List<MLPPeer>> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error ooccured while fetching local peers", x);
                }
                return response;
        }
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/controller/PingController.java b/gateway/src/main/java/org/acumos/federation/gateway/controller/PingController.java
new file mode 100644 (file)
index 0000000..e8d3531
--- /dev/null
@@ -0,0 +1,88 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.controller;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.acumos.cds.domain.MLPPeer;
+import org.acumos.federation.gateway.common.API;
+import org.acumos.federation.gateway.common.JSONTags;
+import org.acumos.federation.gateway.common.JsonResponse;
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.security.Peer;
+import org.acumos.federation.gateway.service.PeerService;
+import org.acumos.federation.gateway.service.ServiceContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import io.swagger.annotations.ApiOperation;
+
+@Controller
+@RequestMapping(API.Roots.FEDERATION)
+public class PingController extends AbstractController {
+
+       @Autowired
+       private PeerService peerService;
+
+       /**
+        * Ping service.
+        * @param theHttpResponse
+        *            HttpServletResponse
+        * @return List of Published ML Solutions in JSON format.
+        */
+       @CrossOrigin
+       //@PreAuthorize("") : nothing in particular, any peer has access to this
+       @ApiOperation(value = "Invoked by Peer Acumos to get status and self information.", response = MLPPeer.class)
+       @RequestMapping(value = { API.Paths.PING }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @ResponseBody
+       public JsonResponse<MLPPeer> ping(
+                       /* HttpServletRequest theHttpRequest, */
+                       HttpServletResponse theHttpResponse) {
+
+               JsonResponse<MLPPeer> response = new JsonResponse<MLPPeer>();
+               log.debug(EELFLoggerDelegate.debugLogger, API.Paths.PING);
+               try {
+                       MLPPeer self = peerService.getSelf();
+                       response = JsonResponse.<MLPPeer> buildResponse()
+                                                                                                               .withMessage("ping")
+                                                                                                               .withContent(self)
+                                                                                                               .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_OK);
+               } 
+               catch (Exception x) {
+                       response = JsonResponse.<MLPPeer> buildErrorResponse()
+                                                                                                                .withError(x)
+                                                                                                                .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An error occurred while handling a ping request", x);
+               }
+               return response;
+       }
+
+}
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/controller/RegistrationController.java b/gateway/src/main/java/org/acumos/federation/gateway/controller/RegistrationController.java
new file mode 100644 (file)
index 0000000..4391c84
--- /dev/null
@@ -0,0 +1,146 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.acumos.federation.gateway.controller;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.acumos.cds.domain.MLPPeer;
+import org.acumos.federation.gateway.common.API;
+import org.acumos.federation.gateway.common.JSONTags;
+import org.acumos.federation.gateway.common.JsonResponse;
+import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.security.Peer;
+import org.acumos.federation.gateway.service.PeerService;
+import org.acumos.federation.gateway.service.ServiceContext;
+import org.acumos.federation.gateway.service.ServiceException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * Provide in-band federation handshake interface.
+ */
+@Controller
+@RequestMapping(API.Roots.FEDERATION)
+public class RegistrationController extends AbstractController {
+
+       @Autowired
+       private PeerService peerService;
+
+       /**
+        * @param theHttpResponse
+        *            HttpServletResponse
+        * @return Request status information
+        */
+       @CrossOrigin
+       //@PreAuthorize("hasAuthority('')") //if enabled, this must be opened to anonymous so no such check
+       @ApiOperation(value = "Invoked by another Acumos Instance to request federation.", response = String.class)
+       @RequestMapping(value = { API.Paths.PEER_REGISTER }, method = RequestMethod.POST, produces = APPLICATION_JSON)
+       @ResponseBody
+       public JsonResponse<MLPPeer> registerPeer(
+                       /* HttpServletRequest theHttpRequest, */
+                       HttpServletResponse theHttpResponse) {
+
+               log.debug(EELFLoggerDelegate.debugLogger, API.Paths.PEER_REGISTER);
+               JsonResponse<MLPPeer> response = null;
+               ControllerContext context = new ControllerContext();
+               try {
+                       MLPPeer peer = context.getPeer().getPeerInfo();
+                       peerService.registerPeer(peer);
+
+                       response = JsonResponse.<MLPPeer> buildResponse()
+                                                                       .withMessage("registration request accepted")                                                                                                                                                                                           
+                                                                       .withContent(peer)
+                                                                       .build();
+                                                                       
+                       theHttpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
+                       log.debug(EELFLoggerDelegate.debugLogger, "peer registration request " + peer + " was accepted");
+               }
+               catch (ServiceException sx) {
+                       response = JsonResponse.<MLPPeer> buildErrorResponse()
+                                                                       .withMessage(sx.getMessage())
+                                                                       .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                       log.error(EELFLoggerDelegate.errorLogger, "A service error occured during peer registration", sx);
+               }
+               catch (Exception x) {
+                       response = JsonResponse.<MLPPeer> buildErrorResponse()
+                                                                       .withError(x)
+                                                                       .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An unexpected error occured during peer registration", x);
+               }
+               return response;
+       }
+
+       /**
+        */
+       @CrossOrigin
+       //@PreAuthorize("hasAuthority('')") 
+       @ApiOperation(value = "Invoked by another Acumos Instance to request federation teermination.", response = String.class)
+       @RequestMapping(value = { API.Paths.PEER_UNREGISTER }, method = RequestMethod.POST, produces = APPLICATION_JSON)
+       @ResponseBody
+       public JsonResponse<MLPPeer> unregisterPeer(
+                       /* HttpServletRequest theHttpRequest, */
+                       HttpServletResponse theHttpResponse) {
+
+               log.debug(EELFLoggerDelegate.debugLogger, API.Paths.PEER_REGISTER);
+               JsonResponse<MLPPeer> response = null;
+               ControllerContext context = new ControllerContext();
+               try {
+                       MLPPeer peer = context.getPeer().getPeerInfo();
+                       peerService.unregisterPeer(peer);
+
+                       response = JsonResponse.<MLPPeer> buildResponse()
+                                                                       .withMessage("federation termination request accepted")                                                                                                                                                                                         
+                                                                       .withContent(peer)
+                                                                       .build();
+                                                                       
+                       theHttpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
+                       log.debug(EELFLoggerDelegate.debugLogger, "federation termination request from " + peer + " was registered");
+               }
+               catch (ServiceException sx) {
+                       response = JsonResponse.<MLPPeer> buildErrorResponse()
+                                                                       .withMessage(sx.getMessage())
+                                                                       .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                       log.error(EELFLoggerDelegate.errorLogger, "A service error occured during peer unregister", sx);
+               }
+               catch (Exception x) {
+                       response = JsonResponse.<MLPPeer> buildErrorResponse()
+                                                                       .withError(x)
+                                                                       .build();
+                       theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                       log.error(EELFLoggerDelegate.errorLogger, "An unexpected error occured during peer register", x);
+               }
+               return response;
+       }
+
+}
@@ -22,6 +22,10 @@ package org.acumos.federation.gateway.security;
 
 import java.util.List;
 
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+import javax.naming.InvalidNameException;
+
 import org.acumos.cds.domain.MLPPeer;
 
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
@@ -37,6 +41,7 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
@@ -52,7 +57,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
 @Configuration
 @EnableWebSecurity
 @EnableGlobalMethodSecurity(prePostEnabled = true)
-public class X509AuthenticationFilter extends WebSecurityConfigurerAdapter {
+public class AuthenticationConfiguration extends WebSecurityConfigurerAdapter {
 
        private final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
 
@@ -62,7 +67,7 @@ public class X509AuthenticationFilter extends WebSecurityConfigurerAdapter {
        @Value("${federation.enablePeerAuthentication:true}")
        private boolean securityEnabled;
 
-       public X509AuthenticationFilter() {
+       public AuthenticationConfiguration() {
        }
 
        /*
@@ -77,24 +82,80 @@ public class X509AuthenticationFilter extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
 
-               http.authorizeRequests().anyRequest().authenticated().and().x509().subjectPrincipalRegex("CN=(.*?)(?:,|$)")
-                               .userDetailsService(userDetailsService());
-
+               http.authorizeRequests()
+                                       .anyRequest()
+                                               .authenticated()
+                                               .and()
+                                               .x509()
+                                                       //.x509AuthenticationFilter(new X509AuthenticationFilter() {
+                                                       //              {
+                                                       //                      System.out.println(" *** Set custom principal extractor");
+                                                       //                      setPrincipalExtractor((cert) -> {
+                                                       //                              System.out.println(" *** got principal: " + cert.getSubjectX500Principal().getName());
+                                                       //                              return cert.getSubjectX500Principal().getName(); 
+                                                       //                      });
+                                                       //              }
+                                                       //      })
+                                                       //.subjectPrincipalRegex("CN=(.*?)(?:,|$)")
+                                                       .subjectPrincipalRegex("(.*)")  //select whole subject line
+                                                       .userDetailsService(userDetailsService());
        }
 
-       // @Bean
        public UserDetailsService userDetailsService() {
-               return (username -> {
-                       log.info(EELFLoggerDelegate.debugLogger, " X509 subject : " + username);
-                       List<MLPPeer> mlpPeers = peerService.getPeerBySubjectName(username);
+               return (subject -> {
+                       log.info(EELFLoggerDelegate.debugLogger, " X509 subject : " + subject);
+                       LdapName x500subject = null;
+                       try {
+                               x500subject = new LdapName(subject);
+                       }
+                       catch (InvalidNameException inx) {
+                               log.warn(EELFLoggerDelegate.errorLogger, "Failed to parse subject information : " + subject);
+                               return new Peer(new MLPPeer(), Role.ANY);
+                       }
+
+                       String cn = null,
+                                                email = null,
+                                                ou = null, o = null, st = null, c = null;
+                       for (Rdn rdn :  x500subject.getRdns()) {
+                               if ("CN".equalsIgnoreCase(rdn.getType())) {
+                                       cn = rdn.getValue().toString();
+                               }
+                               else if ("emailaddress".equalsIgnoreCase(rdn.getType())) {
+                                       email = rdn.getValue().toString();
+                               }
+                               else if ("OU".equalsIgnoreCase(rdn.getType())) {
+                                       ou = rdn.getValue().toString();
+                               }
+                               else if ("O".equalsIgnoreCase(rdn.getType())) {
+                                       o = rdn.getValue().toString();
+                               }
+                               else if ("ST".equalsIgnoreCase(rdn.getType())) {
+                                       st = rdn.getValue().toString();
+                               }
+                               else if ("C".equalsIgnoreCase(rdn.getType())) {
+                                       c = rdn.getValue().toString();
+                               }
+                       }
+
+                       List<MLPPeer> mlpPeers = peerService.getPeerBySubjectName(cn);
                        log.info(EELFLoggerDelegate.debugLogger, " Peers matching X509 subject : " + mlpPeers);
                        if (!Utils.isEmptyList(mlpPeers)) {
-                               log.info(EELFLoggerDelegate.debugLogger, " We are providing a matching Use ");
-                               return new Peer(mlpPeers.get(0), Role.PEER);
-                       } else {
+                               MLPPeer mlpPeer = mlpPeers.get(0);
+                               return new Peer(mlpPeer, mlpPeer.isSelf() ? Role.SELF : Role.PEER);
+                       }
+                       else {
                                MLPPeer unknown = new MLPPeer();
                                // set it up with available info
-                               unknown.setSubjectName(username);
+                               unknown.setSubjectName(cn);
+                               unknown.setName(cn);
+                               unknown.setDescription(
+                                       (ou == null ? "" : ou + ",") + (o == null ? "" : o + ",") +
+                                       (st == null ? "" : st + ",") + (c == null ? "" : c + ","));
+                               unknown.setApiUrl("https://" + cn);
+                                       //lookup SRV record
+                               unknown.setContact1(email);
+                               unknown.setLocal(false);
+                               unknown.setSelf(false);
 
                                return new Peer(unknown, Role.ANY);
                        }
index d9396ac..161317b 100644 (file)
@@ -27,21 +27,23 @@ import org.springframework.security.core.GrantedAuthority;
 public enum Priviledge implements GrantedAuthority {
 
        /**
-        * Gives access to catalog items (solutions); coarse at this point, all
+        * Granted to a peer to access catalog items (solutions) and related information; coarse at this point, all
         * (list/read/download) or nothing
         */
        CATALOG_ACCESS,
        /**
-        * Gives access to the local list of peers. In the future we might want to
-        * refine this by defining which peers should be provided (byb some base
-        * selection criteria)
+        * Granted to a peer to request information about the peers registered in the local Acumos system.
         */
        PEERS_ACCESS,
        /**
         * The right to submit a subscription request. This is granted to ANY if so
         * enabled system wide.
         */
-       SUBSCRIPTION;
+       SUBSCRIPTION,
+       /**
+        * granted to local Acumos components to request information from peers.
+        */
+       PEER_ACCESS;
 
        Priviledge() {
        }
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/security/X509ResourceFilter.java.noneed b/gateway/src/main/java/org/acumos/federation/gateway/security/X509ResourceFilter.java.noneed
deleted file mode 100644 (file)
index 0f5a640..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*-
- * ===============LICENSE_START=======================================================
- * Acumos
- * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
- * ===================================================================================
- * This Acumos software file is distributed by AT&T and Tech Mahindra
- * 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
- *  
- * This file 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.acumos.federation.gateway.security;
-
-import java.util.List;
-
-import org.acumos.cds.domain.MLPPeer;
-
-import org.acumos.federation.gateway.config.EELFLoggerDelegate;
-import org.acumos.federation.gateway.service.PeerService;
-import org.acumos.federation.gateway.util.Utils;
-
-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.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.core.authority.AuthorityUtils;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-
-import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
-import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
-import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
-
-/**
- * 
- * X.509 certificate authentication :  verifying the identity of a communication peer when using the HTTPS (HTTP over SSL) protocol.
- *
- */
-
-@Configuration
-@EnableResourceServer
-public class X509ResourceFilter extends ResourceServerConfigurerAdapter {
-       
-       private final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
-
-       @Autowired
-       private PeerService peerService;
-
-       public X509ResourceFilter() {
-       }
-
-       @Override
-       public void configure(ResourceServerSecurityConfigurer resources) {
-               resources
-                       .resourceId("web");
-       }
-
-       @Override
-       public void configure(HttpSecurity http) throws Exception {
-               http
-               .authorizeRequests()
-                       .anyRequest().authenticated()
-               .and()
-                       .x509()
-                               .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
-                               .userDetailsService(userDetailsService());
-       }
-       
-       //@Bean
-       public UserDetailsService userDetailsService() {
-               return (username -> {
-                       log.info(EELFLoggerDelegate.debugLogger, " X509 subject : " + username);
-                       List<MLPPeer> mlpPeers = peerService.getPeer(username);
-                       log.info(EELFLoggerDelegate.debugLogger, " Peers matching X509 subject : " + mlpPeers);
-      if(!Utils.isEmptyList(mlpPeers)) {
-                               log.info(EELFLoggerDelegate.debugLogger, " We are providing a matching Use ");
-                               return new Peer(username, Role.PEER.priviledges());
-                       }
-                       else    {
-                               return new Peer(username, Role.ANY.priviledges());
-                               //return null;
-                       }
-               });
-       }
-}
-
@@ -18,7 +18,7 @@
  * ===============LICENSE_END=========================================================
  */
 
-package org.acumos.federation.gateway.util;
+package org.acumos.federation.gateway.service;
 
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -58,7 +58,6 @@ import org.springframework.beans.factory.BeanInitializationException;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.scheduling.annotation.Scheduled;
 
-import org.acumos.federation.gateway.common.AdapterCondition;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 
 import org.apache.commons.io.IOUtils;
@@ -122,7 +121,7 @@ public class LocalWatchService {
        }
 
        @Scheduled(fixedRateString = "${peer.local.interval:60}000")
-       protected void updatePeersSubscriptionInfo() {
+       protected void updateInfo() {
                logger.info(EELFLoggerDelegate.debugLogger, "ckecking for updates");
                if (this.sourceWatcher == null) {
                        logger.debug(EELFLoggerDelegate.debugLogger, "source watcher not in place");
index e39045a..aa97776 100644 (file)
@@ -118,7 +118,7 @@ public interface PeerService {
         * @throws ServiceException
         *             if anything goes wrong during the check/provisioning process
         */
-       public void subscribePeer(MLPPeer thePeer) throws ServiceException;
+       public void registerPeer(MLPPeer thePeer) throws ServiceException;
 
        /**
         * Optional operation allowing the gateway to update a peer and mark it for
@@ -129,6 +129,6 @@ public interface PeerService {
         * @throws ServiceException
         *             if anything goes wrong during the check/provisioning process
         */
-       public void unsubscribePeer(MLPPeer thePeer) throws ServiceException;
+       public void unregisterPeer(MLPPeer thePeer) throws ServiceException;
 
 }
index 9d05924..1345d06 100644 (file)
@@ -23,6 +23,7 @@ package org.acumos.federation.gateway.service.impl;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
+import org.acumos.federation.gateway.common.Clients;
 
 import org.acumos.cds.client.ICommonDataServiceRestClient;
 
@@ -35,7 +36,7 @@ public abstract class AbstractServiceImpl {
        protected final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
 
        public ICommonDataServiceRestClient getClient() {
-               return clients.getClient();
+               return clients.getCDSClient();
        }
 
 }
index 689fe18..62d52a9 100644 (file)
@@ -29,7 +29,7 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Conditional;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import org.acumos.federation.gateway.util.LocalWatchService;
+import org.acumos.federation.gateway.service.LocalWatchService;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 
 import org.apache.commons.io.IOUtils;
index 5df7523..e627669 100644 (file)
@@ -41,7 +41,6 @@ import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.service.CatalogService;
 import org.acumos.federation.gateway.service.ServiceContext;
 import org.acumos.federation.gateway.util.Utils;
-import org.acumos.federation.gateway.common.GatewayCondition;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 import org.springframework.core.io.InputStreamResource;
@@ -63,7 +62,6 @@ import org.acumos.cds.transport.RestPageResponse;
  *
  */
 @Service
-@Conditional(GatewayCondition.class)
 public class CatalogServiceImpl extends AbstractServiceImpl implements CatalogService {
 
        @Autowired
@@ -94,16 +92,18 @@ public class CatalogServiceImpl extends AbstractServiceImpl implements CatalogSe
                if (theSelector != null)
                        selector.putAll(theSelector);
 
-               List<MLPSolution> solutions = cdsClient.searchSolutions(selector, false);
-               log.debug(EELFLoggerDelegate.debugLogger, "getSolutions: cds solutions " + solutions);
+               //TODO: load all pages ?? 
+               RestPageResponse<MLPSolution> response = 
+                       getClient().searchSolutions(selector, false, null);
+               log.debug(EELFLoggerDelegate.debugLogger, "getSolutions: cds solutions count {}", response.getSize());
 
-               return solutions;
+               return response.getContent();
        }
 
        @Override
        public MLPSolution getSolution(String theSolutionId, ServiceContext theContext) {
 
-               log.debug(EELFLoggerDelegate.debugLogger, "getSolution");
+               log.trace(EELFLoggerDelegate.debugLogger, "getSolution");
                ICommonDataServiceRestClient cdsClient = getClient();
                return cdsClient.getSolution(theSolutionId);
        }
@@ -111,7 +111,7 @@ public class CatalogServiceImpl extends AbstractServiceImpl implements CatalogSe
        @Override
        public List<MLPSolutionRevision> getSolutionRevisions(String theSolutionId, ServiceContext theContext) {
 
-               log.debug(EELFLoggerDelegate.debugLogger, "getSolutionRevisions");
+               log.trace(EELFLoggerDelegate.debugLogger, "getSolutionRevisions");
                ICommonDataServiceRestClient cdsClient = getClient();
                List<MLPSolutionRevision> mlpSolutionRevisions = cdsClient.getSolutionRevisions(theSolutionId);
                return mlpSolutionRevisions;
@@ -121,7 +121,7 @@ public class CatalogServiceImpl extends AbstractServiceImpl implements CatalogSe
        public MLPSolutionRevision getSolutionRevision(String theSolutionId, String theRevisionId,
                        ServiceContext theContext) {
 
-               log.debug(EELFLoggerDelegate.debugLogger, "getSolutionRevision");
+               log.trace(EELFLoggerDelegate.debugLogger, "getSolutionRevision");
                ICommonDataServiceRestClient cdsClient = getClient();
                MLPSolutionRevision mlpSolutionRevision = cdsClient.getSolutionRevision(theSolutionId, theRevisionId);
                return mlpSolutionRevision;
@@ -131,7 +131,7 @@ public class CatalogServiceImpl extends AbstractServiceImpl implements CatalogSe
        public List<MLPArtifact> getSolutionRevisionArtifacts(String theSolutionId, String theRevisionId,
                        ServiceContext theContext) {
 
-               log.debug(EELFLoggerDelegate.debugLogger, "getSolutionRevisionArtifacts");
+               log.trace(EELFLoggerDelegate.debugLogger, "getSolutionRevisionArtifacts");
                ICommonDataServiceRestClient cdsClient = getClient();
                List<MLPArtifact> mlpArtifacts = cdsClient.getSolutionRevisionArtifacts(theSolutionId, theRevisionId);
                return mlpArtifacts;
@@ -162,10 +162,10 @@ public class CatalogServiceImpl extends AbstractServiceImpl implements CatalogSe
                                byteArrayOutputStream.close();
                        }
 
-               } catch (Exception e) {
-                       log.error(EELFLoggerDelegate.errorLogger, "getSolutionRevisionArtifactiContent", e);
                }
-               // TODO Auto-generated method stub
+               catch (Exception x) {
+                       log.error(EELFLoggerDelegate.errorLogger, "getSolutionRevisionArtifactiContent", x);
+               }
                return streamResource;
        }
 
index 3e60274..4610343 100644 (file)
@@ -51,8 +51,6 @@ import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.service.CatalogService;
 import org.acumos.federation.gateway.service.ServiceContext;
 import org.acumos.federation.gateway.util.Utils;
-import org.acumos.federation.gateway.util.LocalWatchService;
-import org.acumos.federation.gateway.common.AdapterCondition;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.BeanInitializationException;
 import org.springframework.core.env.Environment;
@@ -75,7 +73,6 @@ import org.acumos.cds.transport.RestPageResponse;
  */
 @Service
 @ConfigurationProperties(prefix = "catalogLocal")
-@Conditional(AdapterCondition.class)
 public class CatalogServiceLocalImpl extends AbstractServiceLocalImpl implements CatalogService {
 
        private List<FLPSolution> solutions;
index 93e848c..9a8c1d3 100644 (file)
@@ -29,12 +29,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Collections;
 
-import org.acumos.federation.gateway.common.GatewayCondition;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.util.MapBuilder;
 import org.acumos.federation.gateway.service.PeerService;
 import org.acumos.federation.gateway.service.ServiceContext;
 import org.acumos.federation.gateway.service.ServiceException;
+import org.acumos.federation.gateway.cds.PeerStatus;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
@@ -50,7 +50,6 @@ import org.acumos.cds.transport.RestPageResponse;
  *
  */
 @Service
-@Conditional(GatewayCondition.class)
 public class PeerServiceImpl extends AbstractServiceImpl implements PeerService {
 
        /**
@@ -61,7 +60,13 @@ public class PeerServiceImpl extends AbstractServiceImpl implements PeerService
 
        @Override
        public MLPPeer getSelf() {
-               return (MLPPeer) getClient().searchPeers(new MapBuilder().put("isSelf", Boolean.TRUE).build(), false).get(0);
+               RestPageResponse<MLPPeer> response = 
+                       getClient().searchPeers(new MapBuilder().put("isSelf", Boolean.TRUE).build(), false, null);
+               if (response.getSize() != 1) {
+                       log.warn(EELFLoggerDelegate.errorLogger, "Number of peers representing 'self' not 1: " + response.getSize());
+                       return null;
+               }
+               return response.getContent().get(0);
        }
 
        /**
@@ -88,12 +93,12 @@ public class PeerServiceImpl extends AbstractServiceImpl implements PeerService
        @Override
        public List<MLPPeer> getPeerBySubjectName(String theSubjectName, ServiceContext theContext) {
                log.debug(EELFLoggerDelegate.debugLogger, "getPeerBySubjectName");
-               List<MLPPeer> mlpPeers = getClient().searchPeers(new MapBuilder().put("subjectName", theSubjectName).build(),
-                               false);
-               if (mlpPeers != null && mlpPeers.size() > 0) {
-                       log.debug(EELFLoggerDelegate.debugLogger, "getPeerBySubjectName size:{}", mlpPeers.size());
+               RestPageResponse<MLPPeer> response = 
+                       getClient().searchPeers(new MapBuilder().put("subjectName", theSubjectName).build(), false, null);
+               if (response.getSize() != 1) {
+                       log.warn(EELFLoggerDelegate.errorLogger, "getPeerBySubjectName returned more then one peer:{}", response.getSize());
                }
-               return mlpPeers;
+               return response.getContent();
        }
 
        @Override
@@ -107,55 +112,97 @@ public class PeerServiceImpl extends AbstractServiceImpl implements PeerService
        }
 
        @Override
-       public void subscribePeer(MLPPeer thePeer) throws ServiceException {
-               log.debug(EELFLoggerDelegate.debugLogger, "subscribePeer");
+       public void registerPeer(MLPPeer thePeer) throws ServiceException {
+               log.debug(EELFLoggerDelegate.debugLogger, "registerPeer");
 
                String subjectName = thePeer.getSubjectName();
                if (subjectName == null)
                        throw new ServiceException("No subject name is available");
 
                ICommonDataServiceRestClient cdsClient = getClient();
-               List<MLPPeer> mlpPeers = cdsClient.searchPeers(new MapBuilder().put("subjectName", subjectName).build(), false);
-
-               if (mlpPeers != null && mlpPeers.size() > 0) {
-                       throw new ServiceException("Peer with subjectName '" + subjectName + "' already exists: " + mlpPeers);
+               RestPageResponse<MLPPeer> response = 
+                       cdsClient.searchPeers(new MapBuilder().put("subjectName", subjectName).build(), false, null);
+
+               if (response.getSize() != 0) {
+                       //if (response.getSize() == 1) { //should be the only alternative
+                       MLPPeer peer = response.getContent().get(0);
+                       PeerStatus status = PeerStatus.forCode(peer.getStatusCode());
+                       if (null == status) {
+                               throw new ServiceException("Invalid peer status found: " + peer.getStatusCode());
+                       }
+
+                       if (status == PeerStatus.Requested) {
+                               throw new ServiceException("Peer registration request is pending");
+                       }
+                       else if (status == PeerStatus.Active || status == PeerStatus.Inactive) {
+                               log.info(EELFLoggerDelegate.applicationLogger, "registering an active/inactive peer: " + peer);
+                               return;
+                       }
+                       else if (status == PeerStatus.Declined) {
+                               throw new ServiceException("Peer registration request was declined");
+                       }
+                       else if (status == PeerStatus.Renounced) {
+                               throw new ServiceException("Peer unregistration request is pending");
+                       }
+                       throw new ServiceException("Peer with subjectName '" + subjectName + "' already exists: " + peer);
                }
 
-               log.error(EELFLoggerDelegate.debugLogger, "subscribePeer: new peer with subjectName {}, create CDS record",
+               log.error(EELFLoggerDelegate.debugLogger, "registerPeer: new peer with subjectName {}, create CDS record",
                                thePeer.getSubjectName());
-               // waiting on CDS 1.13
-               // thePeer.setStatus(PeerStatus.PENDING);
+               //enforce
+               thePeer.setStatusCode(PeerStatus.Requested.code());
 
                try {
                        cdsClient.createPeer(thePeer);
-               } catch (Exception x) {
+               }
+               catch (Exception x) {
                        throw new ServiceException("Failed to create peer");
                }
        }
 
        @Override
-       public void unsubscribePeer(MLPPeer thePeer) throws ServiceException {
-               log.debug(EELFLoggerDelegate.debugLogger, "unsubscribePeer");
+       public void unregisterPeer(MLPPeer thePeer) throws ServiceException {
+               log.debug(EELFLoggerDelegate.debugLogger, "unregisterPeer");
 
                String subjectName = thePeer.getSubjectName();
                if (subjectName == null)
                        throw new ServiceException("No subject name is available");
 
                ICommonDataServiceRestClient cdsClient = getClient();
-               List<MLPPeer> mlpPeers = cdsClient.searchPeers(new MapBuilder().put("subjectName", subjectName).build(), false);
+               RestPageResponse<MLPPeer> response = 
+                       cdsClient.searchPeers(new MapBuilder().put("subjectName", subjectName).build(), false, null);
+
+               if (response.getSize() != 1) {
+                       throw new ServiceException("Search for peer with subjectName '" + subjectName + "' yielded invalid number of items: " + response);
+               }
 
-               if (mlpPeers != null && mlpPeers.size() != 1) {
-                       throw new ServiceException("No peer with subjectName '" + subjectName + "' found: " + mlpPeers);
+               MLPPeer peer = response.getContent().get(0);
+               PeerStatus status = PeerStatus.forCode(peer.getStatusCode());
+               if (null == status) {
+                       throw new ServiceException("Invalid peer status found: " + peer.getStatusCode());
                }
 
-               log.error(EELFLoggerDelegate.debugLogger, "unsubscribePeer: peer with subjectName {}, update CDS record",
+               if (status == PeerStatus.Requested) {
+                       throw new ServiceException("Peer registration request is pending");
+                       //can we simply delete the peer ??
+               }
+               else if (status == PeerStatus.Declined) {
+                       throw new ServiceException("Peer registration request was declined");
+                       //can we simply delete the peer ??
+               }
+               else if (status == PeerStatus.Renounced) {
+                       throw new ServiceException("Peer unregistration request is pending");
+               }
+               //active/inactive peers moved to renounced
+
+               log.error(EELFLoggerDelegate.debugLogger, "unregisterPeer: peer with subjectName {}, update CDS record",
                                thePeer.getSubjectName());
-               // waiting on CDS 1.13
-               // thePeer.setStatus(PeerStatus.PENDING_REMOVE);
+               thePeer.setStatusCode(PeerStatus.Renounced.code());
 
                try {
                        cdsClient.updatePeer(thePeer);
-               } catch (Exception x) {
+               }
+               catch (Exception x) {
                        throw new ServiceException("Failed to update peer", x);
                }
        }
index 0edfc03..df16992 100644 (file)
@@ -54,8 +54,6 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Conditional;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import org.acumos.federation.gateway.util.LocalWatchService;
-import org.acumos.federation.gateway.common.AdapterCondition;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.service.PeerService;
 import org.acumos.federation.gateway.service.ServiceContext;
@@ -68,7 +66,6 @@ import org.apache.commons.io.IOUtils;
 
 @Service
 @ConfigurationProperties(prefix = "peersLocal")
-@Conditional(AdapterCondition.class)
 public class PeerServiceLocalImpl extends AbstractServiceLocalImpl implements PeerService, PeerSubscriptionService {
 
        private List<FLPPeer> peers;
@@ -100,7 +97,8 @@ public class PeerServiceLocalImpl extends AbstractServiceLocalImpl implements Pe
                                MappingIterator objectIterator = objectReader.readValues(this.resource.getURL());
                                this.peers = objectIterator.readAll();
                                log.info(EELFLoggerDelegate.debugLogger, "loaded " + this.peers.size() + " peers");
-                       } catch (Exception x) {
+                       }
+                       catch (Exception x) {
                                throw new BeanInitializationException("Failed to load solutions catalog from " + this.resource, x);
                        }
                }
@@ -142,21 +140,19 @@ public class PeerServiceLocalImpl extends AbstractServiceLocalImpl implements Pe
        @Override
        public MLPPeer getPeerById(final String thePeerId, ServiceContext theContext) {
                MLPPeer apeer = this.peers.stream().filter(peer -> thePeerId.equals(peer.getPeerId())).findFirst().orElse(null);
-
-               log.debug(EELFLoggerDelegate.errorLogger, "Local peer info, one peer: " + apeer);
-
+               log.info(EELFLoggerDelegate.debugLogger, "Local peer info, one peer: " + apeer);
                return apeer;
        }
 
        /** */
        @Override
-       public void subscribePeer(MLPPeer mlpPeer) {
+       public void registerPeer(MLPPeer mlpPeer) {
                throw new UnsupportedOperationException();
        }
 
        /** */
        @Override
-       public void unsubscribePeer(MLPPeer mlpPeer) {
+       public void unregisterPeer(MLPPeer mlpPeer) {
                throw new UnsupportedOperationException();
        }
 
@@ -165,7 +161,7 @@ public class PeerServiceLocalImpl extends AbstractServiceLocalImpl implements Pe
        public List<MLPPeerSubscription> getPeerSubscriptions(final String thePeerId) {
                FLPPeer peer = this.peers.stream().filter(entry -> thePeerId.equals(entry.getPeerId())).findFirst()
                                .orElse(null);
-               log.info(EELFLoggerDelegate.errorLogger,
+               log.info(EELFLoggerDelegate.debugLogger,
                                "Peer " + thePeerId + " subs:" + (peer == null ? "none" : peer.getSubscriptions()));
                return peer == Collections.EMPTY_LIST ? null : peer.getSubscriptions();
        }
index 1843f17..01668e4 100644 (file)
@@ -26,7 +26,6 @@ package org.acumos.federation.gateway.service.impl;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import org.acumos.federation.gateway.common.GatewayCondition;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.service.PeerSubscriptionService;
 import org.acumos.federation.gateway.util.Utils;
@@ -44,7 +43,6 @@ import org.acumos.cds.transport.RestPageResponse;
  *
  */
 @Service
-@Conditional(GatewayCondition.class)
 public class PeerSubscriptionServiceImpl extends AbstractServiceImpl implements PeerSubscriptionService {
 
        @Autowired
@@ -28,8 +28,8 @@ import org.acumos.cds.domain.MLPSolution;
 import org.acumos.federation.gateway.common.JsonResponse;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.event.PeerSubscriptionEvent;
-import org.acumos.federation.gateway.service.impl.Clients;
-import org.acumos.federation.gateway.service.impl.FederationClient;
+import org.acumos.federation.gateway.common.Clients;
+import org.acumos.federation.gateway.common.FederationClient;
 import org.acumos.federation.gateway.util.Utils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
@@ -39,13 +39,14 @@ import org.springframework.stereotype.Component;
 /**
  * 
  * Peer Acumos Task to Communicate to Remote Acumos and fetch Solutions and
- * Catalogs
+ * Catalogs.
+ * This is a Component/Bean so that it can be autowired.
  */
-@Component("peerSubscriptionTask")
+@Component
 @Scope("prototype")
-public class PeerCommunicationTask implements Runnable {
+public class PeerSubscriptionTask implements Runnable {
 
-       private final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PeerCommunicationTask.class);
+       private final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
 
        @Autowired
        private ApplicationEventPublisher eventPublisher;
@@ -56,10 +57,10 @@ public class PeerCommunicationTask implements Runnable {
        @Autowired
        private Clients clients;
 
-       public PeerCommunicationTask() {
+       public PeerSubscriptionTask() {
        }
 
-       public PeerCommunicationTask handle(MLPPeer peer, MLPPeerSubscription subscription) {
+       public PeerSubscriptionTask handle(MLPPeer peer, MLPPeerSubscription subscription) {
                this.mlpPeer = peer;
                this.mlpSubscription = subscription;
                return this;
@@ -77,38 +78,27 @@ public class PeerCommunicationTask implements Runnable {
        public void run() {
 
                if (this.mlpPeer == null || this.mlpSubscription == null) {
-                       logger.info(EELFLoggerDelegate.debugLogger, "Peer task has no peer subscription info");
+                       log.info(EELFLoggerDelegate.debugLogger, "Peer task has no peer subscription info");
                        return;
                }
 
                try {
-                       logger.info(EELFLoggerDelegate.debugLogger, "Peer task: " + mlpPeer);
-
-                       logger.info(EELFLoggerDelegate.debugLogger,
-                                       "Peer task: invoking getSolutions from Remote instance " + mlpPeer.getApiUrl());
+                       log.info(EELFLoggerDelegate.debugLogger, "Peer task for " + mlpPeer.getName() + ", " + mlpPeer.getApiUrl() + ", " + mlpSubscription.getSelector());
                        FederationClient fedClient = clients.getFederationClient(this.mlpPeer.getApiUrl());
-
-                       // Map<String, Object> queryParameters = new HashMap<String, Object>();
-                       // queryParameters.put("modelTypeCode", mlpSubscription.getSelector()); //
-                       // Subscriptions
-                       logger.info(EELFLoggerDelegate.debugLogger, "Peer Task: filter " + mlpSubscription.getSelector());
-
-                       JsonResponse<List<MLPSolution>> jsonResponse = fedClient
-                                       .getSolutions(Utils.jsonStringToMap(mlpSubscription.getSelector()));
-                       if (jsonResponse != null && jsonResponse.getResponseBody() != null) {
-                               List<MLPSolution> mlpSolutions = jsonResponse.getResponseBody();
-                               logger.debug(EELFLoggerDelegate.debugLogger,
-                                               "Peer task: Number of Solutions fetch from Remote Instance: " + mlpSolutions.size());
+                       JsonResponse<List<MLPSolution>> response =
+                               fedClient.getSolutions(Utils.jsonStringToMap(mlpSubscription.getSelector()));
+                       log.debug(EELFLoggerDelegate.debugLogger,
+                                               "Peer task got response " + response + " for " + mlpPeer.getName() + ", " + mlpPeer.getApiUrl() + ", " + mlpSubscription.getSelector());
+                       if (response != null && response.getContent() != null) {
+                               List<MLPSolution> mlpSolutions = response.getContent();
                                if (mlpSolutions.size() > 0) {
                                        this.eventPublisher.publishEvent(
                                                        new PeerSubscriptionEvent(this, this.mlpPeer, this.mlpSubscription, mlpSolutions));
                                }
                        }
-               } catch (Exception x) {
-                       logger.info(EELFLoggerDelegate.errorLogger, "Peer task for " + this.mlpPeer + " failed", x);
                }
-               // System.out.println(mlpPeer.getName() + " : Runnable Task with " + message + "
-               // on thread " + Thread.currentThread().getName() + ", id:"+
-               // Thread.currentThread().getId());
+               catch (Exception x) {
+                       log.error(EELFLoggerDelegate.errorLogger, "Peer task failed for " + mlpPeer.getName() + ", " + mlpPeer.getApiUrl() + ", " + mlpSubscription.getSelector(), x);
+               }
        }
 }
@@ -22,8 +22,10 @@ package org.acumos.federation.gateway.task;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Date;
 import java.util.concurrent.ScheduledFuture;
 
+import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 
 import org.acumos.cds.domain.MLPPeer;
@@ -31,12 +33,12 @@ import org.acumos.cds.domain.MLPPeerSubscription;
 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
 import org.acumos.federation.gateway.service.PeerService;
 import org.acumos.federation.gateway.service.PeerSubscriptionService;
-import org.acumos.federation.gateway.task.PeerCommunicationTask;
+import org.acumos.federation.gateway.cds.PeerStatus;
 import org.acumos.federation.gateway.util.Utils;
+
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.env.Environment;
@@ -54,10 +56,9 @@ import com.google.common.collect.Table;
  */
 @Component
 @EnableScheduling
-@Configuration
-public class PeerCommunicationTaskScheduler implements ApplicationContextAware {
+public class PeerSubscriptionTaskScheduler {
 
-       private final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PeerCommunicationTaskScheduler.class);
+       private final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(getClass().getName());
 
        @Autowired
        private Environment env;
@@ -68,55 +69,43 @@ public class PeerCommunicationTaskScheduler implements ApplicationContextAware {
        @Autowired
        private PeerSubscriptionService peerSubscriptionService;
 
+       @Autowired
        private ApplicationContext appCtx;
 
-       private static Table<String, Long, PeerTaskHandler> peersSubsTask = HashBasedTable.create();
+       private Table<String, Long, PeerTaskHandler> peersSubsTask = HashBasedTable.create();
+       private ThreadPoolTaskScheduler threadPoolTaskScheduler = null;
 
-       public void setApplicationContext(ApplicationContext theCtx) { // throws BeansException {
-               this.appCtx = theCtx;
-       }
 
-       // what was this for?
-       // @Bean(destroyMethod = "shutdown")
-       // public Executor taskExecutor() {
-       // return Executors.newScheduledThreadPool(10);//Hardcode for now
-       // }
+       @PostConstruct
+       public void initScheduler() {
 
-       @Bean
-       public ThreadPoolTaskScheduler taskScheduler() {
                String name = env.getProperty("federation.instance.name") + "-" + env.getProperty("federation.instance")
                                + "-taskscheduler";
-               ThreadPoolTaskScheduler threadPoolTaskScheduler = null;
-               try {
-                       threadPoolTaskScheduler = (ThreadPoolTaskScheduler) this.appCtx.getBean(name);
-               } catch (BeansException bix) {
-                       // instantiation should fail the first time because we create teh bean below
-               }
 
-               if (threadPoolTaskScheduler == null) {
-                       logger.debug(EELFLoggerDelegate.debugLogger, "creating task scheduler");
-                       threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
-                       threadPoolTaskScheduler.setPoolSize(20);// Make it configurable later
-                       threadPoolTaskScheduler.setBeanName(name);
-                       threadPoolTaskScheduler.initialize();
+               if (this.threadPoolTaskScheduler == null) {
+                       log.debug(EELFLoggerDelegate.debugLogger, "creating task scheduler");
+                       this.threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
+                       this.threadPoolTaskScheduler.setPoolSize(20);// Make it configurable later
+                       this.threadPoolTaskScheduler.setBeanName(name);
+                       this.threadPoolTaskScheduler.initialize();
                }
-               return threadPoolTaskScheduler;
        }
 
        @PreDestroy
        public void cleanUpTasks() {
-               logger.debug(EELFLoggerDelegate.debugLogger, "cleanUpTasks");
+               log.debug(EELFLoggerDelegate.debugLogger, "cleanUpTasks");
                try {
-                       logger.debug(EELFLoggerDelegate.debugLogger, "cleanUpTasks: " + this.peersSubsTask.size() + " tasks");
-                       taskScheduler().shutdown();
+                       log.debug(EELFLoggerDelegate.debugLogger, "cleanUpTasks: " + this.peersSubsTask.size() + " tasks");
+                       this.threadPoolTaskScheduler.shutdown();
 
-               } catch (Exception e) {
-                       logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while cleanUpTasks: ", e);
+               }
+               catch (Exception e) {
+                       log.error(EELFLoggerDelegate.errorLogger, "Exception occurred while cleanUpTasks: ", e);
                }
        }
 
        protected boolean same(MLPPeerSubscription theFirstSub, MLPPeerSubscription theSecondSub) {
-               logger.debug(EELFLoggerDelegate.debugLogger,
+               log.debug(EELFLoggerDelegate.debugLogger,
                                "comparing subs : [" + theFirstSub.getSubId() + "," + theFirstSub.getCreated() + ","
                                                + theFirstSub.getModified() + "] vs. [" + theSecondSub.getSubId() + ","
                                                + theSecondSub.getCreated() + "," + theSecondSub.getModified() + "]");
@@ -127,24 +116,33 @@ public class PeerCommunicationTaskScheduler implements ApplicationContextAware {
                                                                && theFirstSub.getModified().equals(theSecondSub.getModified())));
        }
 
-       @Scheduled(initialDelay = 1000, fixedRateString = "${peer.jobchecker.interval:400}000")
+       /**
+        * Schedule a one time execution of the subscription.
+        * The scheduler will not track the execution of suck a task.
+        */
+       public void runOnce(MLPPeer thePeer, MLPPeerSubscription theSub) {
+               new PeerTaskHandler().runTask(thePeer, theSub);
+       }
+
+       @Scheduled(initialDelay = 5000, fixedRateString = "${peer.jobchecker.interval:400}000")
        public void checkPeerJobs() {
 
+               log.debug(EELFLoggerDelegate.debugLogger, "checkPeerSubscriptionJobs");
                // Get the List of MLP Peers
                List<MLPPeer> mlpPeers = peerService.getPeers();
                if (Utils.isEmptyList(mlpPeers)) {
-                       logger.info(EELFLoggerDelegate.debugLogger, "checkPeer : no peers from " + peerService);
+                       log.info(EELFLoggerDelegate.debugLogger, "no peers from " + peerService);
                        return;
                }
 
                for (MLPPeer mlpPeer : mlpPeers) {
-                       logger.info(EELFLoggerDelegate.debugLogger, "checkPeer : " + mlpPeer);
+                       log.info(EELFLoggerDelegate.debugLogger, "checkPeer : " + mlpPeer);
 
                        // cancel peer tasks for inactive peers
-                       if (!mlpPeer.isActive()) {
+                       if (PeerStatus.Active != PeerStatus.forCode(mlpPeer.getStatusCode())) {
                                // cancel all peer sub tasks for this peer
-                               logger.debug(EELFLoggerDelegate.debugLogger,
-                                               "checkPeer : peer no longer active, removing active tasks");
+                               log.debug(EELFLoggerDelegate.debugLogger,
+                                               "checkPeer : peer " + mlpPeer + " no longer active, removing active tasks");
                                Map<Long, PeerTaskHandler> subsTask = this.peersSubsTask.row(mlpPeer.getPeerId());
                                if (subsTask != null) {
                                        for (Map.Entry<Long, PeerTaskHandler> subTaskEntry : subsTask.entrySet()) {
@@ -166,13 +164,13 @@ public class PeerCommunicationTaskScheduler implements ApplicationContextAware {
                        }
 
                        for (MLPPeerSubscription mlpSub : mlpSubs) {
-                               logger.info(EELFLoggerDelegate.debugLogger, "checkSub " + mlpSub);
+                               log.info(EELFLoggerDelegate.debugLogger, "checkSub " + mlpSub);
                                PeerTaskHandler peerSubTask = peersSubsTask.get(mlpPeer.getPeerId(), mlpSub.getSubId());
                                if (peerSubTask != null) {
                                        // was the subscription updated? if yes, cancel current task.
                                        MLPPeerSubscription mlpCurrentSub = peerSubTask.getSubscription();
                                        if (!same(mlpSub, mlpCurrentSub)) {
-                                               logger.debug(EELFLoggerDelegate.debugLogger,
+                                               log.debug(EELFLoggerDelegate.debugLogger,
                                                                "checkSub: subscription was updated, stopping current task");
                                                peerSubTask.stopTask();
                                                peerSubTask = null; // in order to trigger its reset below: no need to remove the entry as we
@@ -182,7 +180,7 @@ public class PeerCommunicationTaskScheduler implements ApplicationContextAware {
                                }
 
                                if (peerSubTask == null) {
-                                       logger.info(EELFLoggerDelegate.debugLogger, "Scheduled peer sub task for " + mlpPeer.getApiUrl());
+                                       log.info(EELFLoggerDelegate.debugLogger, "Scheduled peer sub task for " + mlpPeer.getApiUrl());
                                        this.peersSubsTask.put(mlpPeer.getPeerId(), mlpSub.getSubId(),