Support common-dataservice 2.2.x 15/4115/5
authorAndrew Gauld <agauld@att.com>
Wed, 27 Mar 2019 13:20:09 +0000 (13:20 +0000)
committerAndrew Gauld <agauld@att.com>
Tue, 16 Apr 2019 13:35:39 +0000 (13:35 +0000)
Also fix all Sonar vulnerability warnings and many Sonar code smells

Change-Id: Ia5d362ecd15c9056a2199b812b19dcc3ca3c2bfc
Issue-ID: ACUMOS-2732
Signed-off-by: Andrew Gauld <agauld@att.com>
101 files changed:
docs/config.rst
docs/developer-guide.rst
docs/release-notes.rst
docs/selectors.rst
gateway/pom.xml
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/sdc/ASDC.java
gateway/src/main/java/org/acumos/federation/gateway/cds/AccessType.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/Catalog.java
gateway/src/main/java/org/acumos/federation/gateway/cds/CodeNames.java
gateway/src/main/java/org/acumos/federation/gateway/cds/Mapper.java
gateway/src/main/java/org/acumos/federation/gateway/cds/PeerSubscription.java
gateway/src/main/java/org/acumos/federation/gateway/cds/Reference.java
gateway/src/main/java/org/acumos/federation/gateway/cds/RevCatDescription.java [moved from gateway/src/main/java/org/acumos/federation/gateway/cds/RevisionDescription.java with 78% similarity]
gateway/src/main/java/org/acumos/federation/gateway/cds/Solution.java
gateway/src/main/java/org/acumos/federation/gateway/cds/SolutionRevision.java
gateway/src/main/java/org/acumos/federation/gateway/cds/SolutionRevisionBuilder.java
gateway/src/main/java/org/acumos/federation/gateway/cds/SubscriptionScope.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/ValidationStatus.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/API.java
gateway/src/main/java/org/acumos/federation/gateway/common/FederationClient.java
gateway/src/main/java/org/acumos/federation/gateway/common/JsonResponse.java
gateway/src/main/java/org/acumos/federation/gateway/config/DockerConfiguration.java
gateway/src/main/java/org/acumos/federation/gateway/config/FederationConfiguration.java
gateway/src/main/java/org/acumos/federation/gateway/config/InterfaceConfiguration.java
gateway/src/main/java/org/acumos/federation/gateway/config/LocalConfiguration.java
gateway/src/main/java/org/acumos/federation/gateway/controller/AbstractController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/CatalogController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/ControllerContext.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerCatalogController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerPeersController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerPingController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerRegistrationController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerSubscriptionController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PeersController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/PingController.java
gateway/src/main/java/org/acumos/federation/gateway/controller/RegistrationController.java
gateway/src/main/java/org/acumos/federation/gateway/security/AuthenticationConfiguration.java
gateway/src/main/java/org/acumos/federation/gateway/security/FederationMethodSecurityConfiguration.java
gateway/src/main/java/org/acumos/federation/gateway/security/FederationMethodSecurityExpressionRoot.java
gateway/src/main/java/org/acumos/federation/gateway/security/Tools.java
gateway/src/main/java/org/acumos/federation/gateway/service/CatalogService.java
gateway/src/main/java/org/acumos/federation/gateway/service/CatalogServiceConfiguration.java
gateway/src/main/java/org/acumos/federation/gateway/service/ContentService.java
gateway/src/main/java/org/acumos/federation/gateway/service/LocalWatchService.java
gateway/src/main/java/org/acumos/federation/gateway/service/PeerService.java
gateway/src/main/java/org/acumos/federation/gateway/service/ServiceContext.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/CodeNamesServiceLocalImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/ContentServiceImpl.java
gateway/src/main/java/org/acumos/federation/gateway/service/impl/ContentServiceLocalImpl.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/ServiceImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/task/PeerSubscriptionTaskScheduler.java
gateway/src/main/java/org/acumos/federation/gateway/util/Action.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/Future.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/FutureHandler.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/Futures.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/JSONHttpMessageConverter.java
gateway/src/main/java/org/acumos/federation/gateway/util/ListBuilder.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/MapBuilder.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/AsdcTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/AuthorizationTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/CatalogServiceTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/CdsTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/ContentServiceTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/ControllerTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/LocalControllerTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/PeerGatewayTest.java
gateway/src/test/java/org/acumos/federation/gateway/test/TestAdapter.java
gateway/src/test/java/org/acumos/federation/gateway/test/TestTemplates.java [new file with mode: 0644]
gateway/src/test/java/org/acumos/federation/gateway/test/UtilsTest.java
gateway/src/test/resources/acumosa-catalog.json
gateway/src/test/resources/acumosb-catalog.json
gateway/src/test/resources/mockCDSAddCatalogSolutionResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSAllowedResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSCreateCatalogResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSCreateRevisionDescriptionResponse.json
gateway/src/test/resources/mockCDSCreateSolutionRevisionResponse.json
gateway/src/test/resources/mockCDSForbiddenResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSForbiddenSolutionRevisionResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSNoSuchThingResponse.json [moved from gateway/src/test/resources/mockCDSNoSuchSolutionResponse.json with 100% similarity]
gateway/src/test/resources/mockCDSPeerSubscriptionResponse.json
gateway/src/test/resources/mockCDSPeerSubscriptionsResponse.json
gateway/src/test/resources/mockCDSPortalCatalogsResponse.json
gateway/src/test/resources/mockCDSPortalGetCatalogResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSPortalNoSolutionsResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSPortalPeerAccessCatalogIdsResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSPortalSolutionCountResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockCDSSolutionRevisionDescriptionResponse.json
gateway/src/test/resources/mockCDSSolutionRevisionResponse.json
gateway/src/test/resources/mockCDSSolutionRevisionsResponse.json
gateway/src/test/resources/mockPeerGWCatalogsResponse.json [new file with mode: 0644]
gateway/src/test/resources/mockPeerSolutionResponse.json
gateway/src/test/resources/mockPeerSolutionRevisionResponse.json
gateway/src/test/resources/mockPeerSolutionRevisionsResponse.json
gateway/src/test/resources/task-test-catalog.json
gateway/src/test/resources/test-catalog.json

index 6dc0da4..ef6778c 100644 (file)
@@ -193,27 +193,10 @@ Gateway Configuration Properties
 
 The following configuration properties are enabled when federation.instance is "gateway":
 
-catalog.solutions.selector
+catalog.catalogs-selector
   Optional.  Default { "accessTypeCode": "PB" }
 
-  A JSON string giving override selector filters to be used when searching
-  for catalogs and solutions.  These filters are always in effect and cannot
-  be overridden.  Selectors are described in another section of this
-  documentation.
-
-catalog.solutions-selector-defaults
-  Optional.  Default { "modified": 1 }.
-
-  A JSON string giving default selector filters to be used when searching
-  for solutions.  These filters will be in effect unless overridden.
-
-catalog.solution-revisions-selector
-  Optional.  Default { "accessTypeCode": "PB" }
-
-  A JSON string giving override selector filters to be used when searching
-  for solution revisions.  These filters are always in effect and cannot
-  be overridden.  Selectors are described in another section of this
-  documentation.
+  A JSON string giving filters to be used when searching for catalogs.
 
 cdms.client.url
   Required.
index 4c78c1b..78c3a55 100644 (file)
@@ -65,8 +65,12 @@ REST Interface
 --------------
 
 The federation interface allows access via the federation gateway to information available in an Acumos system.
-The main category of information that is exposed via the gateway is solution information: solution/revision/artifact and artifact content.
-The federation gateway allows access from pre-registered peers via a REST interface running over HTTPS/SSL/TLS.
+The main exposed elements are catalogs, solutions, artifacts, and documents.
+The federation gateway allows pre-registered peers to retrieve a list of catalogs they are permitted to view.
+The peers can then list solutions and revisions of those solutions published in those catalogs.
+They can then retrieve metadata and content of artifacts referenced by those revisions.
+For each catalog a solution revision appears in, peers can retrieve a description and document metadata and content
+
 The gateway requires mutual authentication; i.e., the client will be required to present a certificate.
 The gateway identifies a client as a pre-registered peer based on the certificates' subjectName
 (which implies that the subjectName must be communicated to the Acumos system administrator when the peer is provisioned).
@@ -74,8 +78,8 @@ The gateway identifies a client as a pre-registered peer based on the certificat
 API
 ~~~
 
-All APIs encode the response in JSON.
-There is a top level envelope containing error information, and under the entry 'responseBody' it contains the actual content.
+All APIs except the artifact and document content APIs, encode the response in JSON.  The artifact and document content APIs return unencoded data.
+For other APIs, there is a top level envelope containing error information, and under the entry 'responseBody' it contains the actual content.
 All identifiers are UUIDs.
 The following endpoints are defined:
 
@@ -83,38 +87,38 @@ The following endpoints are defined:
 
   List all visible (e.g. public) catalogs.
 
-* /solutions
+* /solutions?catalogId={catalogId}
 
-  List all public solutions. Accepts a query parameter, 'selector', which contains a JSON object with selection criteria, base64 encoded. Acceptable selection criteria are the solution object attributes. The entries are ANDed (see :ref:`selecting`).
+  List all solutions published to the specified catalog.
 
 * /solutions/{solutionId}
 
-  Retrieve one solution details.
+  Retrieve the specified solution, and its revisions.
 
 * /solutions/{solutionId}/revisions
 
-  List all revisions for a given solution.
+  Retrieve the revisions of the specified solution.
 
-* /solutions/{solutionId}/revisions/{revisionId}
+* /solutions/{solutionId}/revisions/{revisionId}[?catalogId={catalogId}]
 
-  Retrieve one revision details
+  Retrieve details of the specified revision, including its artifacts.
+  If the optional catalogId query parameter is specified, the description
+  of the revision and any documents associated with it, from the specified
+  catalog, will also be included.
 
 * /solutions/{solutionId}/revisions/{revisionId}/artifacts
 
   List all artifacts attached to a particular revision
 
-* /artifacts/{artifactId}
-
-  Retrieve one artifact details
-
-* /artifacts/{artifactId}/download
+* /artifacts/{artifactId}/content
 
-  Download the artifact content.
+  Retrieve the content of the specified artifact
 
-Example of solutions selector: The following will select all CLassifiers::
+* /revision/{revisionId}/documents?catalogId={catalogId}
 
-    { "modelTypeCode":"CL" }
+  Retrieve documents associated with the specified revision in the specified
+  catalog.
 
-Multiple values for a solution attribute are allowed and ORed.  The following will select all CLassifiers and PRedictors::
+* /documents/{documentId}/content
 
-    { "modelTypeCode":["CL","PR"] }
+  Retrieve the content of the specified document
index 9994e51..bed87bd 100644 (file)
@@ -23,6 +23,32 @@ Federation Gateway Release Notes
 This server is available as a Docker image in a Docker registry at the Linux Foundation.
 The image name is "federation-gateway" and the tag is a version string as shown below. 
 
+Version 2.2.0, 2019-04-16
+-------------------------
+* Update to CDS 2.2.x with subscription by catalogs (`ACUMOS-2732 <https://jira.acumos.org/browse/ACUMOS-2732>`_)
+
+  This makes changes to the REST api for accessing Federation on both the
+  public and internal interfaces:
+
+  * When listing solutions, the optional selector query parameter is replaced
+    by a required catalogId query parameter
+
+  * When getting revision details an optional catalogId query parameter is
+    added, used to retrieve descriptions and documents, from that catalog, for
+    the revision.  If not specified, no descriptions or documents are returned.
+
+  * When getting artifact and document content, the form of the URI is changed
+    to eliminate the unused solution and revision IDs.
+
+  * When getting documents for a revision, the form of the URI is changed
+    to eliminate the unused solution ID and a required catalogID query parameter
+    is added.
+
+  Solution revisions in CDS no longer have access type codes, so the (optional)
+  catalog.default-access-type-code configuration parameter has been removed.
+
+* Eliminate vulnerabilities and many "code smells" identified by SONAR.
+
 Version 2.1.2, 2019-03-27
 -------------------------
 * Add JUnit test cases to reach 50% or better code coverage (`ACUMOS-2584 <https://jira.acumos.org/browse/ACUMOS-2584>`_)
index 3bcfd5b..ee31f32 100644 (file)
 
 .. _selecting:
 
-Selectors and Finding Solutions
+Selectors and Subscriptions
 -------------------------------
 
-The Acumos federation gateway supports retrieving solutions from a peer
-instance of Acumos.  Usually, though, what is desired is to retrieve a subset
-of the solutions, and this is done by specifying a "selector" as a query
-parameter on the HTTP GET from the peer federation gateway.  The value of the
-selector is the Base64 encoding of a JSON object, with keys specifying
-constraints on the set of solutions to be returned.  For example, to specify
-that the name of the solution must be "hello," the JSON object might look like::
+The Acumos federation gateway supports polling other Acumos instances for
+solutions using a subscription mechanism.  This subscription contains a
+selector specifying which catalogs should be imported.
 
-    {"name":"hello"}
+The form of the selector value can be:
 
-The Base64 encoding of this is::
+    { "catalogId": "some-catalog-id" }
 
-    eyJuYW1lIjoiaGVsbG8ifQ==
+or:
 
-And the URL for an HTTP GET with this selector might be::
+    { "catalogId": [ "first-catalog-id", "second-catalog-id", ... ] }
 
-    https://example.org/solutions?selector=eyJuYW1lIjoiaGVsbG8ifQ%3D%3D
-
-The keys supported in the selector object are:
-
-* active
-
-  Boolean, either true or false.  Defaults to true.  If true, only active
-  solutions will be returned.  If false, only inactive solutions will be
-  returned.
-
-* catalogId
-
-  String.  If specified, only solutions from the specified catalog will be
-  returned.
-
-* modelTypeCode
-
-  String or array of strings.  If specified, only solutions with one of the
-  specified modelTypeCodes will be returned.
-
-* modified
-
-  Integer.  Defaults to 1.  A timestamp specified as the number of seconds since
-  January 1, 1970, 00:00:00 GMT.  Only solutions modified at or after the
-  specified timestamp will be returned.
-
-* name
-
-  String.  If specified, only solutions with the specified name will be
-  returned.
-
-* solutionId
-
-  String.  If specified, only the specified solution will be returned.
-
-* toolkitTypeCode
-
-  String or array of strings.  If specified, only solutions with one of the
-  specified toolkitTypeCodes will be returned.
-
-* tags
-
-  String or array of strings.  If specified, only solutions that have at
-  least one of the specified tags will be returned.
-
-Note: String comparison uses an exact match.
-
-Note: Only solutions that meet all of the specified constraints will be returned.
-
-Note: A federation gateway can be configured with additional default values as
-well as overrides of user specified values.
-
-Note: To get "all" solutions, don't specify a selector on the HTTP request (or
-specify one without any of the above keys).  Default constraints will still
-be applied, so only active solutions modified after
-January 1st, 1970 at 00:00:00 GMT will be returned.
+where a catalog ID is the UUID of the catalog: something like
+70c19e97-b37d-4738-b363-2d352b2d0f05.
index 9f4835b..cc77c69 100644 (file)
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.acumos.federation</groupId>
        <artifactId>gateway</artifactId>
-       <version>2.1.2-SNAPSHOT</version>
+       <version>2.2.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>2.1.2.RELEASE</version>
+               <version>2.1.4.RELEASE</version>
                <!-- silence warning about parent relative path -->
                <relativePath />
        </parent>
@@ -69,7 +69,7 @@
                <dependency>
                        <groupId>org.acumos.common-dataservice</groupId>
                        <artifactId>cmn-data-svc-client</artifactId>
-                       <version>2.1.2</version>
+                       <version>2.2.1</version>
                </dependency>
                <dependency>
                        <groupId>org.json</groupId>
index 4bb6444..6c5a1cd 100644 (file)
@@ -2,15 +2,15 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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
 
 package org.acumos.federation.gateway.adapter;
 
-import java.io.Closeable;
+import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.time.Instant;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,11 +35,11 @@ import java.util.Set;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 
-import org.acumos.cds.AccessTypeCode;
 import org.acumos.cds.client.ICommonDataServiceRestClient;
+import org.acumos.cds.domain.MLPCatalog;
 import org.acumos.cds.domain.MLPPeer;
 import org.acumos.cds.domain.MLPPeerSubscription;
-import org.acumos.cds.domain.MLPRevisionDescription;
+import org.acumos.cds.domain.MLPRevCatDescription;
 import org.acumos.cds.domain.MLPSolution;
 import org.acumos.cds.domain.MLPSolutionRevision;
 import org.acumos.cds.domain.MLPTag;
@@ -47,15 +48,17 @@ import org.acumos.federation.gateway.cds.Document;
 import org.acumos.federation.gateway.cds.PeerSubscription;
 import org.acumos.federation.gateway.cds.Solution;
 import org.acumos.federation.gateway.cds.SolutionRevision;
-import org.acumos.federation.gateway.cds.SubscriptionScope;
 import org.acumos.federation.gateway.cds.TimestampedEntity;
+import org.acumos.federation.gateway.common.API;
 import org.acumos.federation.gateway.common.Clients;
 import org.acumos.federation.gateway.common.FederationClient;
+import org.acumos.federation.gateway.common.FederationClient.StreamingResource;
 import org.acumos.federation.gateway.common.FederationException;
 import org.acumos.federation.gateway.common.JsonResponse;
 import org.acumos.federation.gateway.config.GatewayCondition;
 import org.acumos.federation.gateway.event.PeerSubscriptionEvent;
 import org.acumos.federation.gateway.service.CatalogService;
+import org.acumos.federation.gateway.service.CatalogServiceConfiguration;
 import org.acumos.federation.gateway.service.ContentService;
 import org.acumos.federation.gateway.service.PeerSubscriptionService;
 import org.acumos.federation.gateway.service.ServiceContext;
@@ -63,18 +66,24 @@ import org.acumos.federation.gateway.service.ServiceException;
 import org.acumos.federation.gateway.util.Utils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.BeanInitializationException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Conditional;
 import org.springframework.context.annotation.Scope;
 import org.springframework.context.event.EventListener;
-import org.springframework.core.env.Environment;
-import org.springframework.core.io.Resource;
 import org.springframework.core.task.TaskExecutor;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.HttpStatusCodeException;
 
+import org.omg.CORBA.BooleanHolder;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.acumos.cds.domain.MLPArtifact;
+import org.acumos.cds.domain.MLPDocument;
+
 
 @Component("peergateway")
 @Scope("singleton")
@@ -82,21 +91,22 @@ import org.springframework.web.client.HttpStatusCodeException;
 public class PeerGateway {
 
        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+       @Value("${federation.operator}")
+       private String defaultUser;
        @Autowired
        @Qualifier("acumos")
        private TaskExecutor taskExecutor;
        @Autowired
-       private Environment env;
-       @Autowired
        private Clients clients;
        @Autowired
        private ContentService content;
        @Autowired
        private CatalogService catalog;
        @Autowired
+       private CatalogServiceConfiguration catalogConfig;
+       @Autowired
        private PeerSubscriptionService peerSubscriptionService;
 
-       private static final String federationDotOperator = "federation.operator";
 
        public PeerGateway() {
                log.trace("PeerGateway::new");
@@ -105,24 +115,14 @@ public class PeerGateway {
        @PostConstruct
        public void initGateway() {
                log.trace("initPeerGateway");
-
                /* make sure an operator was specified and that it is a declared user */
-               if (null == this.env.getProperty(federationDotOperator)) {
-                       throw new BeanInitializationException("Missing configuration key " + federationDotOperator);
-               } 
-               else {
-                       try {
-                               if (null == this.clients.getCDSClient().getUser(this.env.getProperty(federationDotOperator))) {
-                                       log.warn(federationDotOperator + 
-                                                       " does not point to an existing user");
-                               }
-                       }
-                       catch (/* HttpStatusCode */Exception dx) {
-                               log.warn("failed to verify value " + federationDotOperator, dx);
+               try {
+                       if (this.clients.getCDSClient().getUser(defaultUser) == null) {
+                               log.warn("The default federation operator {} is not a known user ID", defaultUser);
                        }
+               } catch (Exception dx) {
+                       log.warn("failed to verify default federation operator", dx);
                }
-
-               // Done
                log.debug("PeerGateway available");
        }
 
@@ -131,11 +131,9 @@ public class PeerGateway {
                log.debug("PeerGateway destroyed");
        }
 
-       protected String getUserId(MLPPeerSubscription theSubscription/*
-                                                                                                                                        * , MLPSolution theSolution
-                                                                                                                                        */) {
+       protected String getUserId(MLPPeerSubscription theSubscription) {
                String userId = theSubscription.getUserId();
-               return userId != null ? userId : this.env.getProperty(federationDotOperator);
+               return userId != null ? userId : defaultUser;
        }
 
        @EventListener
@@ -154,6 +152,7 @@ public class PeerGateway {
 
                private MLPPeer peer;
                private PeerSubscription sub;
+               private FederationClient peerClient;
 
                public PeerGatewayUpdateTask(MLPPeer thePeer, MLPPeerSubscription theSub) {
                        this.peer = thePeer;
@@ -161,7 +160,11 @@ public class PeerGateway {
                }
 
                public void run() {
-
+                       peerClient = clients.getFederationClient(this.peer.getApiUrl());
+                       if (peerClient == null) {
+                               log.error("Failed to get client for peer {}", this.peer);
+                               return;
+                       }
                        Map selector = null;
                        try {
                                selector = Utils.jsonStringToMap(this.sub.getSelector());
@@ -170,32 +173,64 @@ public class PeerGateway {
                                log.error("Failed to parse selector for subscription {}", this.sub);
                                return;
                        }
-                       Instant lastProcessed = this.sub.getProcessed();
-                       if (lastProcessed != null) {
-                               selector.put("modified", lastProcessed.getEpochSecond());
-                       }
-                       lastProcessed = Instant.now();
-                       
-                       FederationClient peerClient = clients.getFederationClient(this.peer.getApiUrl());
-                       if (peerClient == null) {
-                               log.error("Failed to get client for peer {}", this.peer);
+                       Instant lastProcessed = Instant.now();
+                       boolean isComplete = true;
+                       Object catids = selector.get(API.QueryParameters.CATALOG_ID);
+                       if (catids instanceof String) {
+                               isComplete &= scanCatalog((String)catids);
+                       } else if (catids instanceof String[]) {
+                               for (String catid: (String[]) catids) {
+                                       isComplete &= scanCatalog(catid);
+                               }
+                       } else {
+                               log.error("Selector for subscription {} needs catalog ID(s)", this.sub);
                                return;
                        }
+                       log.info("Processing of subscription {} completed succesfully: {}", this.sub, isComplete);
+                       //only commit the last processed date if we completed succesfully
+                       if (isComplete) {
+                               try {
+                                       this.sub.setProcessed(lastProcessed);
+                                       peerSubscriptionService.updatePeerSubscription(this.sub);
+                               }
+                               catch (ServiceException sx) {
+                                       log.error("Failed to update subscription information", sx);
+                               }
+                       }
+               }
+               private boolean scanCatalog(String theCatalogId) {
 
                        JsonResponse<List<MLPSolution>> peerSolutionsResponse = null;
                        try {
-                               peerSolutionsResponse = peerClient.getSolutions(selector);
+                               peerSolutionsResponse = peerClient.getSolutions(theCatalogId);
                        }
                        catch (FederationException fx) {
-                               log.info("Processing peer " + this.peer + " subscription " + this.sub.getSubId() + " error.", fx);
-                               return;
+                               log.error("Processing peer " + this.peer + " subscription " + this.sub.getSubId() + " error.", fx);
+                               return false;
                        }
-
                        List<MLPSolution> peerSolutions = peerSolutionsResponse.getContent();
-                       log.info("Processing peer {} subscription {}, {} yielded solutions {}", this.peer, this.sub.getSubId(), selector, peerSolutions);
+                       Set<String> localSolutions = new HashSet<>();
+                       try {
+                               MLPCatalog localCatalog = catalog.getCatalogs().stream().filter(x -> x.getCatalogId().equals(theCatalogId)).findAny().orElse(null);
+                               if (localCatalog == null) {
+                                       log.info("Subscription local catalog id {} missing: trying to create it", theCatalogId);
+                                       MLPCatalog peerCatalog = peerClient.getCatalogs().getContent().stream().filter(x -> x.getCatalogId().equals(theCatalogId)).findAny().orElse(null);
+                                       localCatalog = clients.getCDSClient().createCatalog(peerCatalog);
+                               }
+                               for (MLPSolution solution: catalog.getSolutions(theCatalogId)) {
+                                       localSolutions.add(solution.getSolutionId());
+                               }
+                       } catch (FederationException fe) {
+                               log.error("Failed to retrieve peer catalog " + theCatalogId, fe);
+                               return false;
+                       } catch (ServiceException se) {
+                               log.error("Failed to list solutions in local catalog " + theCatalogId, se);
+                               return false;
+                       }
+                       log.info("Processing peer {} subscription {}, {} yielded solutions {}", this.peer, this.sub.getSubId(), theCatalogId, peerSolutions);
                        if (peerSolutions == null) {
                                log.warn("No solutions available for peer {} subscription {} in {}", this.peer, this.sub.getSubId(), peerSolutionsResponse);
-                               peerSolutions = Collections.EMPTY_LIST;
+                               peerSolutions = Collections.emptyList();
                                //and let it proceed so we end up marking it as processed
                        }
 
@@ -206,33 +241,22 @@ public class PeerGateway {
                                log.info("Processing peer solution {}", peerSolution);
 
                                try {
-                                       isComplete &= mapSolution(peerSolution, peerClient, ctx);
+                                       isComplete &= mapSolution(theCatalogId, peerSolution, !localSolutions.contains(peerSolution.getSolutionId()), ctx);
                                }
                                catch (Throwable t) {
                                        log.error("Mapping of acumos solution failed for " + peerSolution, t);
                                }
                        }
-                                       
-                       log.info("Processing of subscription {} completed succesfully: {}", this.sub, isComplete);
-                       //only commit the last processed date if we completed succesfully
-                       if (isComplete) {
-                               try {
-                                       this.sub.setProcessed(lastProcessed);
-                                       peerSubscriptionService.updatePeerSubscription(this.sub);
-                               }
-                               catch (ServiceException sx) {
-                                       log.error("Failed to update subscription information", sx);
-                               }
-                       }
+                       return isComplete;
                }
 
                //this should go away once the move to service interface based operations is complete
                //as ugly as they come
-               private ICommonDataServiceRestClient getCDSClient(ServiceContext theContext) {
+               private ICommonDataServiceRestClient getCDSClient() {
                        return PeerGateway.this.clients.getCDSClient();
                }
 
-               private Artifact copyArtifact(Artifact peerArtifact) {
+               public Artifact copyArtifact(Artifact peerArtifact) {
                        return Artifact.buildFrom(peerArtifact)
                                                                .withUser(getUserId(this.sub))
                                                                .withCreated(TimestampedEntity.ORIGIN)
@@ -241,41 +265,14 @@ public class PeerGateway {
                }
 
                /* we create a new one as nothing is preserved. assumes matching ids. */
-               private Artifact copyArtifact(Artifact peerArtifact, Artifact localArtifact) {
+               public Artifact copyArtifact(Artifact peerArtifact, Artifact localArtifact) {
                        return Artifact.buildFrom(peerArtifact)
                                                                .withId(localArtifact.getArtifactId())
                                                                .withUser(getUserId(this.sub))
                                                                .build();
                }
 
-               private void putArtifact(String theSolutionId, String theRevisionId, Artifact theArtifact,
-                               ServiceContext theContext) throws ServiceException {
-
-                       assert(getCDSClient(theContext) != null);
-
-                       try {
-                               if (theArtifact.getCreated() == Instant.MIN) {
-                                       getCDSClient(theContext).createArtifact(theArtifact);
-                                       getCDSClient(theContext).addSolutionRevisionArtifact(theSolutionId, theRevisionId, theArtifact.getArtifactId());
-                                       log.info("Local artifact created: {}", theArtifact);
-                               }
-                               else {
-                                       getCDSClient(theContext).updateArtifact(theArtifact);
-                                       log.info("Local artifact updated: {}", theArtifact);
-                               }
-       
-                       }
-                       catch (HttpStatusCodeException restx) {
-                               log.error("Artifact CDS call failed. CDS message is " + restx.getResponseBodyAsString(), restx);
-                               throw new ServiceException("Artifact CDS call failed.", restx);
-                       }
-                       catch (Exception x) {
-                               log.error("Artifact unexpected failure", x);
-                               throw new ServiceException("Artifact CDS call failed.", x);
-                       }
-               }
-
-               private Document copyDocument(Document peerDocument) {
+               public Document copyDocument(Document peerDocument) {
                        return Document.buildFrom(peerDocument)
                                                                .withUser(getUserId(this.sub))
                                                                .withCreated(TimestampedEntity.ORIGIN)
@@ -283,58 +280,34 @@ public class PeerGateway {
                                                                .build();
                }
 
-               private Document copyDocument(Document peerDocument, Document localDocument) {
+               public Document copyDocument(Document peerDocument, Document localDocument) {
                        return Document.buildFrom(peerDocument)
                                                                .withId(localDocument.getDocumentId())
                                                                .withUser(getUserId(this.sub))
                                                                .build();
                }
 
-               private void putDocument(String theSolutionId, String theRevisionId, Document theDocument,
-                               ServiceContext theContext) throws ServiceException {
-
-                       try {
-                               if (theDocument.getCreated() == Instant.MIN) {
-                                       getCDSClient(theContext).createDocument(theDocument);
-                                       getCDSClient(theContext).addSolutionRevisionDocument(theRevisionId, AccessTypeCode.PB.name(), theDocument.getDocumentId());
-                                       log.info("Local document created: {}", theDocument);
-                               }
-                               else {
-                                       getCDSClient(theContext).updateDocument(theDocument);
-                                       log.info("Local document updated: {}", theDocument);
-                               }
-                       }
-                       catch (HttpStatusCodeException restx) {
-                               log.error("Document CDS call failed. CDS message is " + restx.getResponseBodyAsString(), restx);
-                               throw new ServiceException("Document CDS call failed.", restx);
-                       }
-                       catch (Exception x) {
-                               log.error("Document handling unexpected failure", x);
-                               throw new ServiceException("Document handling unexpected failure", x);
-                       }
-               }
-       
-               private MLPRevisionDescription copyRevisionDescription(MLPRevisionDescription peerDescription) {
-                       MLPRevisionDescription localDescription = new MLPRevisionDescription(peerDescription);
+               private MLPRevCatDescription copyRevCatDescription(MLPRevCatDescription peerDescription) {
+                       MLPRevCatDescription localDescription = new MLPRevCatDescription(peerDescription);
                        localDescription.setCreated(TimestampedEntity.ORIGIN);
                        localDescription.setModified(TimestampedEntity.ORIGIN);
                        return localDescription;
                }
 
-               private MLPRevisionDescription copyRevisionDescription(MLPRevisionDescription peerDescription, MLPRevisionDescription localDescription) {
+               private MLPRevCatDescription copyRevCatDescription(MLPRevCatDescription peerDescription, MLPRevCatDescription localDescription) {
                        localDescription.setDescription(peerDescription.getDescription());
                        return localDescription;
                }
 
-               private void putRevisionDescription(MLPRevisionDescription theDescription,ServiceContext theContext) throws ServiceException {
-                       
+               private void putRevCatDescription(MLPRevCatDescription theDescription) throws ServiceException {
+
                        try {
                                if (theDescription.getCreated() == Instant.MIN) {
-                                       getCDSClient(theContext).createRevisionDescription(theDescription);
+                                       getCDSClient().createRevCatDescription(theDescription);
                                        log.info("Local description created: {}", theDescription);
                                }
                                else {
-                                       getCDSClient(theContext).updateRevisionDescription(theDescription);
+                                       getCDSClient().updateRevCatDescription(theDescription);
                                }
                        }
                        catch (HttpStatusCodeException restx) {
@@ -347,30 +320,6 @@ public class PeerGateway {
                        }
                }
 
-               private boolean hasChanged(Artifact thePeerArtifact, Artifact theLocalArtifact) {
-                       if (thePeerArtifact.getVersion() != null && theLocalArtifact.getVersion() != null) { 
-                               return !thePeerArtifact.getVersion().equals(theLocalArtifact.getVersion());
-                       }
-
-                       if (thePeerArtifact.getSize() != null && theLocalArtifact.getSize() != null) { 
-                               return !thePeerArtifact.getSize().equals(theLocalArtifact.getSize());
-                       }
-
-                       return true;
-               }       
-
-               private boolean hasChanged(Document thePeerDoc, Document theLocalDoc) {
-                       if (thePeerDoc.getVersion() != null && theLocalDoc.getVersion() != null) { 
-                               return !thePeerDoc.getVersion().equals(theLocalDoc.getVersion());
-                       }
-
-                       if (thePeerDoc.getSize() != null && theLocalDoc.getSize() != null) { 
-                               return !thePeerDoc.getSize().equals(theLocalDoc.getSize());
-                       }
-
-                       return true;
-               }
-
                private Solution copySolution(Solution thePeerSolution) {
                        return Solution.buildFrom(thePeerSolution)
                                                                .withCreated(TimestampedEntity.ORIGIN)
@@ -381,10 +330,10 @@ public class PeerGateway {
                                                                .resetStats()
                                                                .build();
                }
-       
-               private Solution copySolution(Solution thePeerSolution, Solution theLocalSolution) {    
-                       String newUserId = getUserId(this.sub),
-                                                newSourceId = this.peer.getPeerId();
+
+               private Solution copySolution(Solution thePeerSolution, Solution theLocalSolution) {
+                       String newUserId = getUserId(this.sub);
+                       String newSourceId = this.peer.getPeerId();
 
                        //some basic warnings
                        if (!theLocalSolution.getUserId().equals(newUserId)) {
@@ -411,7 +360,7 @@ public class PeerGateway {
                        //tags, keep only the delta
                        Set<MLPTag> tags = thePeerSolution.getTags();
                        tags.removeAll(theLocalSolution.getTags());
-                       theLocalSolution.setTags(tags);                 
+                       theLocalSolution.setTags(tags);
 
                        return theLocalSolution;
                }
@@ -429,31 +378,34 @@ public class PeerGateway {
                /**
                 * Here comes the core process of updating a local solution's related
                 * information with what is available from a peer.
-                * 
+                *
+                * @param theCatalogId
+                *            the catalog containing the solution for fetching
+                *            revision descriptions and documents
                 * @param theSolution
                 *            the local solution who's related information (revisions and
                 *            artifacts) we are trying to sync
-                * @param thePeerClient
-                *            client
+                * @param addToCatalog
+                *            true if solution is not yet in local catalog
                 * @param theContext
                 *            the context in which we perform the catalog operations
                 * @return true if mapping was succesful, false otherwise
                 * @throws Exception
                 *             any error related to CDS and peer interaction
                 */
-               protected boolean mapSolution(MLPSolution theSolution, FederationClient thePeerClient, ServiceContext theContext) throws Exception {
+               protected boolean mapSolution(String theCatalogId, MLPSolution theSolution, boolean addToCatalog, ServiceContext theContext) throws Exception {
 
-                       boolean isComplete = true,
-                                                       isSolutionNew = false,
-                                                       hasSolutionChanged = false;
+                       boolean isComplete = true;
+                       boolean isSolutionNew = false;
+                       boolean hasSolutionChanged = false;
 
-                       Solution localSolution = null,
-                                                        peerSolution = null;
+                       Solution localSolution = null;
+                       Solution peerSolution = null;
 
                        //retrieve the full representation from the peer
                        JsonResponse<MLPSolution> peerSolutionResponse = null;
                        try {
-                               peerSolutionResponse = thePeerClient.getSolution(theSolution.getSolutionId());
+                               peerSolutionResponse = peerClient.getSolution(theSolution.getSolutionId());
                        }
                        catch (FederationException fx) {
                                log.warn("Failed to retrieve peer solution details for " + theSolution, fx);
@@ -469,45 +421,47 @@ public class PeerGateway {
                        localSolution = catalog.getSolution(peerSolution.getSolutionId());
                        if (localSolution == null) {
                                localSolution = catalog.putSolution(copySolution(peerSolution), theContext);
-                       isSolutionNew = true;
+                               isSolutionNew = true;
                        }
                        else {
                                hasSolutionChanged = hasChanged(peerSolution, localSolution);
                        }
-                       
-                       List<MLPSolutionRevision> peerRevisions = (List)peerSolution.getRevisions();
+
+                       if (addToCatalog) {
+                               clients.getCDSClient().addSolutionToCatalog(localSolution.getSolutionId(), theCatalogId);
+                       }
+                       List<MLPSolutionRevision> peerRevisions = peerSolution.getRevisions();
                        Collections.sort(peerRevisions, (arev, brev) -> arev.getModified().compareTo(brev.getModified()));
 
                        // 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) {
-                               log.warn("No peer revisions were retrieved");
+                       if (peerRevisions == null || peerRevisions.isEmpty()) {
+                               log.warn("No solution revisions were retrieved from the peer");
                                return true;
                        }
 
                        // check if we have locally the latest revision available on the peer
-                       List<MLPSolutionRevision> catalogRevisions = (List)localSolution.getRevisions();
-                       final List<MLPSolutionRevision> localRevisions = catalogRevisions == null ? Collections.EMPTY_LIST : catalogRevisions;
+                       List<MLPSolutionRevision> catalogRevisions = localSolution.getRevisions();
+                       final List<MLPSolutionRevision> localRevisions = catalogRevisions == null ? Collections.emptyList() : catalogRevisions;
 
                        // map peer revisions to local ones; new peer revisions have a null mapping
                        Map<MLPSolutionRevision, MLPSolutionRevision> peerToLocalRevisions =
-                                       new LinkedHashMap<MLPSolutionRevision, MLPSolutionRevision>();
+                                       new LinkedHashMap<>();
                        peerRevisions.forEach(peerRevision -> peerToLocalRevisions.put(peerRevision,
                                        localRevisions.stream()
                                                        .filter(localRevision -> localRevision.getRevisionId().equals(peerRevision.getRevisionId()))
                                                        .findFirst().orElse(null)));
 
                        for (Map.Entry<MLPSolutionRevision, MLPSolutionRevision> revisionEntry : peerToLocalRevisions.entrySet()) {
-                               MLPSolutionRevision peerRevision = revisionEntry.getKey(), localRevision = revisionEntry.getValue();
-
-                               boolean isRevisionNew = false,
-                                                               hasRevisionChanged = false;
+                               MLPSolutionRevision peerRevision = revisionEntry.getKey();
+                               MLPSolutionRevision localRevision = revisionEntry.getValue();
+                               boolean isRevisionNew = false;
 
                                //revision related information (artifacts/documents/description/..) is now embedded in the revision details
                                //federation api call so one call is all is needed
                                JsonResponse<MLPSolutionRevision> peerRevisionResponse = null;
                                try {
-                                       peerRevisionResponse = thePeerClient.getSolutionRevision(peerSolution.getSolutionId(), peerRevision.getRevisionId());
+                                       peerRevisionResponse = peerClient.getSolutionRevision(peerSolution.getSolutionId(), peerRevision.getRevisionId(), theCatalogId);
                                }
                                catch (FederationException fx) {
                                        isComplete = false; //try the next revision but mark the overall processing as incomplete
@@ -522,14 +476,13 @@ public class PeerGateway {
 
                                if (localRevision == null) {
                                        try {
-                                               localRevision = catalog.putSolutionRevision(
-                                                                                                                                                       SolutionRevision.buildFrom(peerRevision)
-                                                                                                                                                               .withCreated(TimestampedEntity.ORIGIN)
-                                                                                                                                                               .withModified(TimestampedEntity.ORIGIN)
-                                                                                                                                                               .withUser(getUserId(this.sub))
-                                                                                                                                                               .withSource(this.peer.getPeerId())
-                                                                                                                                                               .withAccessTypeCode(this.sub.getAccessType())
-                                                                                                                                                               .build(), theContext);
+                                               localRevision = catalog.putRevision(
+                                                   SolutionRevision.buildFrom(peerRevision)
+                                                       .withCreated(TimestampedEntity.ORIGIN)
+                                                       .withModified(TimestampedEntity.ORIGIN)
+                                                       .withUser(getUserId(this.sub))
+                                                       .withSource(this.peer.getPeerId())
+                                                                                                                                       .build(), theContext);
                                        }
                                        catch (ServiceException sx) {
                                                log.error("Failed to put revision " + theSolution.getSolutionId() + "/" + peerRevision.getRevisionId() + " into catalog", sx);
@@ -539,186 +492,32 @@ public class PeerGateway {
                                        isRevisionNew = true;
                                }
 
-                               List<Artifact> peerArtifacts = (List)((SolutionRevision)peerRevision).getArtifacts();
-                               List<Document> peerDocuments = (List)((SolutionRevision)peerRevision).getDocuments();
-
-                               List<Artifact> catalogArtifacts = (List)((SolutionRevision)localRevision).getArtifacts();
-                               List<Document> catalogDocuments = (List)((SolutionRevision)localRevision).getDocuments();
-
-                               final List<Artifact> localArtifacts = catalogArtifacts;
-                               // map the artifacts
-                               // TODO: track deleted artifacts
-                               Map<Artifact, Artifact> peerToLocalArtifacts = new HashMap<Artifact, Artifact>();
-                               peerArtifacts.forEach(peerArtifact -> peerToLocalArtifacts.put(peerArtifact, localArtifacts.stream()
-                                               .filter(localArtifact -> localArtifact.getArtifactId().equals(peerArtifact.getArtifactId()))
-                                               .findFirst().orElse(null)));
+                               BooleanHolder hasRevChanged = new BooleanHolder(false);
+                               isComplete &= artifactsHandler.handle(theCatalogId, peerRevision, localRevision, this, hasRevChanged);
+                               isComplete &= documentsHandler.handle(theCatalogId, peerRevision, localRevision, this, hasRevChanged);
+                               boolean hasRevisionChanged = hasRevChanged.value;
 
-                               for (Map.Entry<Artifact, Artifact> artifactEntry : peerToLocalArtifacts.entrySet()) {
-                                       Artifact peerArtifact = artifactEntry.getKey(),
-                                                                        localArtifact = artifactEntry.getValue();
-                                       boolean doCatalog = false;
-                                       
-                                       log.info("Processing peer artifact {} against local artifact {}", peerArtifact, localArtifact);
-
-                                       if (localArtifact == null) {
-                                               localArtifact = copyArtifact(peerArtifact);
-                                               doCatalog = true;
-                                       }
-                                       else {
-                                               if (hasChanged(peerArtifact, localArtifact)) {
-                                                       // update local artifact
-                                                       localArtifact = copyArtifact(peerArtifact, localArtifact);
-                                                       doCatalog = true;
-                                               }
-                                       }
-
-                                       boolean doContent = doCatalog &&
-                                                                                                                       (peerArtifact.getUri() != null) &&
-                                                                                                                       (SubscriptionScope.Full == SubscriptionScope.forCode(this.sub.getScopeType()));
-                                       if (doContent) {
-                                               log.info("Processing content for artifact {}", peerArtifact); 
-                                               // 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
-                                               // data is the right approach (as it does not rely on the E5 definition).
-                                               Resource artifactContent = null;
-                                               try {
-                                                       artifactContent = thePeerClient.getArtifactContent(
-                                                               peerSolution.getSolutionId(), peerRevision.getRevisionId(), peerArtifact.getArtifactId());
-                                                       log.info("Received {} bytes of artifact content", artifactContent.contentLength()); 
-                                               }
-                                               catch (FederationException x) {
-                                                       log.error("Failed to retrieve acumos artifact content", x);
-                                                       doCatalog = this.sub.getSubscriptionOptions().alwaysUpdateCatalog();
-                                                       isComplete = false;
-                                               }
-
-                                               if (artifactContent != null) {
-                                                       try {
-                                                               content.putArtifactContent(
-                                                                       localSolution.getSolutionId(), localRevision.getRevisionId(), localArtifact, artifactContent);
-                                                               doCatalog = true;
-                                                       }
-                                                       catch (ServiceException sx) {
-                                                               log.error("Failed to store artifact content to local repo", sx);
-                                                               doCatalog = this.sub.getSubscriptionOptions().alwaysUpdateCatalog();
-                                                               isComplete = false;
-                                                       }
-                                                       finally {
-                                                               if (artifactContent instanceof Closeable) {
-                                                                       ((Closeable)artifactContent).close();
-                                                               }
-                                                       }
-                                               }
-                                       }
-
-                                       if (doCatalog) {
-                                               try {
-                                                       putArtifact(localSolution.getSolutionId(), localRevision.getRevisionId(), localArtifact, theContext);
-                                               }
-                                               catch (ServiceException sx) {
-                                                       log.error("Artifact processing failed.", sx);
-                                                       isComplete = false;
-                                               }
-                                               hasRevisionChanged = true;
-                                       }
-                               } //end map artifacts loop
-
-
-                               final List<Document> localDocuments = catalogDocuments;
-                               // map the documents
-                               // TODO: track deleted documents
-                               Map<Document, Document> peerToLocalDocuments = new HashMap<Document, Document>();
-                               peerDocuments.forEach(peerDocument -> peerToLocalDocuments.put(peerDocument, localDocuments.stream()
-                                               .filter(localDocument -> localDocument.getDocumentId().equals(peerDocument.getDocumentId()))
-                                               .findFirst().orElse(null)));
-
-                               for (Map.Entry<Document, Document> documentEntry : peerToLocalDocuments.entrySet()) {
-                                       Document peerDocument = documentEntry.getKey(),
-                                                                        localDocument = documentEntry.getValue();
-                                       boolean doCatalog = false;
-
-                                       log.info("Processing peer document {} against local version {}", peerDocument, localDocument);
-                                       if (localDocument == null) {
-                                               localDocument = copyDocument(peerDocument);
-                                               doCatalog = true;
-                                       }
-                                       else {
-                                               //version strings are not standard so comparing them is not necessarly safe
-                                               if (hasChanged(peerDocument, localDocument)) {
-                                                       // update local doc
-                                                       localDocument = copyDocument(peerDocument, localDocument);
-                                                       doCatalog = true;
-                                               }
-                                       }
-
-                                       boolean doContent = doCatalog &&
-                                                                                                                       (peerDocument.getUri() != null) &&
-                                                                                                                       (SubscriptionScope.Full == SubscriptionScope.forCode(this.sub.getScopeType()));
-                                       if (doContent) {
-                                               log.info("Processing content for document {}", peerDocument); 
-                                               // TODO: we are trying to access the document by its identifier which
-                                               // is fine in the common case but the uri specified in the document
-                                               // data is a more flexible approach.
-                                               Resource documentContent = null;
-                                               try {
-                                                       documentContent = thePeerClient.getDocumentContent(
-                                                               peerSolution.getSolutionId(), peerRevision.getRevisionId(), peerDocument.getDocumentId());
-                                                       log.info("Received {} bytes of document content", documentContent.contentLength()); 
-                                               }
-                                               catch (FederationException x) {
-                                                       log.error("Failed to retrieve acumos document content", x);
-                                                       doCatalog = this.sub.getSubscriptionOptions().alwaysUpdateCatalog();
-                                                       isComplete = false;
-                                               }
-
-                                               if (documentContent != null) {
-                                                       try {
-                                                               content.putDocumentContent(
-                                                                       localSolution.getSolutionId(), localRevision.getRevisionId(), localDocument, documentContent);
-                                                               doCatalog = true;
-                                                       }
-                                                       catch (ServiceException sx) {
-                                                               log.error("Failed to store document content to local repo", sx);
-                                                               doCatalog = this.sub.getSubscriptionOptions().alwaysUpdateCatalog();
-                                                               isComplete = false;
-                                                       }
-                                               }
-                                       }
-
-                                       if (doCatalog) {
-                                               try {
-                                                       putDocument(localSolution.getSolutionId(), localRevision.getRevisionId(), localDocument, theContext);
-                                               }
-                                               catch (ServiceException sx) {
-                                                       log.error("Document processing failed", sx);
-                                                       isComplete = false;
-                                               }
-                                               hasRevisionChanged = true;
-                                       }
-       
-                               } // end map documents loop
-                               
-                               MLPRevisionDescription localDescription = ((SolutionRevision)localRevision).getRevisionDescription();
-                               MLPRevisionDescription peerDescription = ((SolutionRevision)peerRevision).getRevisionDescription();
+                               MLPRevCatDescription localDescription = ((SolutionRevision)localRevision).getRevCatDescription();
+                               MLPRevCatDescription peerDescription = ((SolutionRevision)peerRevision).getRevCatDescription();
 
                                if (peerDescription != null) {
                                        boolean doCatalog = false;
 
                                        if (localDescription == null) {
-                                               localDescription = copyRevisionDescription(peerDescription);
+                                               localDescription = copyRevCatDescription(peerDescription);
                                                doCatalog = true;
                                        }
                                        else {
                                                //is this a good enough test ?? it implies time sync ..
                                                if (peerDescription.getModified().isAfter(localDescription.getModified())) {
-                                                       localDescription = copyRevisionDescription(peerDescription, localDescription);
+                                                       localDescription = copyRevCatDescription(peerDescription, localDescription);
                                                        doCatalog = true;
                                                }
                                        }
 
                                        if (doCatalog) {
                                                try {
-                                                       putRevisionDescription(localDescription, theContext);
+                                                       putRevCatDescription(localDescription);
                                                }
                                                catch (ServiceException sx) {
                                                        log.error("Description processing failed",      sx);
@@ -731,14 +530,14 @@ public class PeerGateway {
                                if (!isRevisionNew && hasRevisionChanged) {
                                        try {
                                                //we do not actually update any properties, just give CDS a chance to update the timestamps as to mark it as updated.
-                                               catalog.putSolutionRevision(SolutionRevision.buildFrom(localRevision).build(),
+                                               catalog.putRevision(SolutionRevision.buildFrom(localRevision).build(),
                                                                                                                                                                theContext);
                                        }
                                        catch (ServiceException sx) {
                                                log.error("Failed to update local revision",    sx);
                                                isComplete = false;
                                        }
-                               }       
+                               }
 
                                hasSolutionChanged |= (isRevisionNew || hasRevisionChanged);
                        } //end revisions processing
@@ -755,5 +554,196 @@ public class PeerGateway {
 
                        return isComplete;
                } // mapSolution
+
+               public boolean alwaysUpdateCatalog() {
+                       return sub.getSubscriptionOptions().alwaysUpdateCatalog();
+               }
+
+               public boolean copyDocumentContent(String solutionId, Document document) {
+                       try (StreamingResource data = peerClient.getDocumentContent(document.getDocumentId())) {
+                               content.putDocumentContent(solutionId, document, data);
+                               log.info("Received {} bytes of document content", data.contentLength());
+                               return true;
+                       } catch (FederationException fedex) {
+                               log.error("Failed to retrieve acumos document content", fedex);
+                       } catch (ServiceException srvex) {
+                               log.error("Failed to store document content to local repo", srvex);
+                       } catch (IOException ioex) {
+                               log.error("Exception receiving document content ", ioex);
+                       }
+                       return false;
+               }
+
+               public boolean copyArtifactContent(String solutionId, Artifact artifact) {
+                       try (StreamingResource data = peerClient.getArtifactContent(artifact.getArtifactId())) {
+                               content.putArtifactContent(solutionId, artifact, data);
+                               log.info("Received {} bytes of artifact content", data.contentLength());
+                               return true;
+                       } catch (FederationException fedex) {
+                               log.error("Failed to retrieve acumos artifact content", fedex);
+                       } catch (ServiceException srvex) {
+                               log.error("Failed to store artifact content to local repo", srvex);
+                       } catch (IOException ioex) {
+                               log.error("Exception receiving artifact content ", ioex);
+                       }
+                       return false;
+               }
+       }
+
+       /*
+        * The process for federating Artifacts and Documents is the same,
+        * with just different method names and, in a few cases method
+        * arguments.  These interfaces and the ItemsHandler class are about
+        * factoring out that duplicated code.
+        */
+
+       @FunctionalInterface
+       private interface TriFunction<T, U, V, R> {
+               R apply(T t, U u, V v);
+       }
+
+       @FunctionalInterface
+       private interface TriPredicate<T, U, V> {
+               boolean test(T t, U u, V v);
+       }
+
+       @FunctionalInterface
+       private interface QuadConsumer<T, U, V, W> {
+               void accept(T t, U u, V v, W w);
+       }
+
+       private static class ItemsHandler<T>    {
+               // get list of items to process
+               private Function<SolutionRevision, List<T>> getList;
+               // get ID of an item
+               private Function<T, String> getId;
+               // get item from local data store
+               private BiFunction<ICommonDataServiceRestClient, String, T> localGet;
+               // link item to revision/catalog
+               private QuadConsumer<ICommonDataServiceRestClient, MLPSolutionRevision, String, String> link;
+               // copy item from peer
+               private BiFunction<PeerGatewayUpdateTask, T, T> copy;
+               // check if peer item updates local item
+               private BiPredicate<T, T> changed;
+               // merge peer and local items
+               private TriFunction<PeerGatewayUpdateTask, T, T, T> merge;
+               // transfer content
+               private TriPredicate<PeerGatewayUpdateTask, String, T> copybody;
+               // create item
+               private BiConsumer<ICommonDataServiceRestClient, T> create;
+               // update item
+               private BiConsumer<ICommonDataServiceRestClient, T> update;
+
+               public ItemsHandler(
+                   Function<SolutionRevision, List<T>> getList,
+                   Function<T, String> getId,
+                   BiFunction<ICommonDataServiceRestClient, String, T> localGet,
+                   QuadConsumer<ICommonDataServiceRestClient, MLPSolutionRevision, String, String> link,
+                   BiFunction<PeerGatewayUpdateTask, T, T> copy,
+                   BiPredicate<T, T> changed,
+                   TriFunction<PeerGatewayUpdateTask, T, T, T> merge,
+                   TriPredicate<PeerGatewayUpdateTask, String, T> copybody,
+                   BiConsumer<ICommonDataServiceRestClient, T> create,
+                   BiConsumer<ICommonDataServiceRestClient, T> update) {
+                       this.getList = getList;
+                       this.getId = getId;
+                       this.localGet = localGet;
+                       this.link = link;
+                       this.copy = copy;
+                       this.changed = changed;
+                       this.merge = merge;
+                       this.copybody = copybody;
+                       this.create = create;
+                       this.update = update;
+               }
+
+               public boolean handle(String catalogId, MLPSolutionRevision peer, MLPSolutionRevision local, PeerGatewayUpdateTask task, BooleanHolder updated) {
+                       ICommonDataServiceRestClient cdsClient = task.getCDSClient();
+                       HashMap<String, T> localItems = new HashMap();
+                       for (T item: getList.apply((SolutionRevision)local)) {
+                               localItems.put(getId.apply(item), item);
+                       }
+                       boolean success = true;
+                       for (T peerItem: getList.apply((SolutionRevision)peer)) {
+                               String itemId = getId.apply(peerItem);
+                               T localItem = localItems.get(itemId);
+                               log.info("Processing peer item {} against local item {}", peerItem, localItem);
+                               if (localItem == null) {
+                                       localItem = localGet.apply(cdsClient, itemId);
+                                       if (localItem != null) {
+                                               link.accept(cdsClient, local, catalogId, itemId);
+                                       }
+                               }
+                               boolean isNew = (localItem == null);
+                               if (isNew) {
+                                       localItem = copy.apply(task, peerItem);
+                               } else if (changed.test(peerItem, localItem)) {
+                                       localItem = merge.apply(task, peerItem, localItem);
+                               } else {
+                                       continue;
+                               }
+                               if (!copybody.test(task, local.getSolutionId(), localItem)) {
+                                       success = false;
+                                       if (!task.alwaysUpdateCatalog()) {
+                                               continue;
+                                       }
+                               }
+                               if (isNew) {
+                                       create.accept(cdsClient, localItem);
+                                       link.accept(cdsClient, local, catalogId, itemId);
+                               } else {
+                                       update.accept(cdsClient, localItem);
+                               }
+                               updated.value = true;
+                       }
+                       return(success);
+               }
+       }
+
+       private static ItemsHandler<MLPDocument> documentsHandler = new ItemsHandler<MLPDocument>(
+           rev -> rev.getDocuments(),
+           doc -> doc.getDocumentId(),
+           (client, id) -> client.getDocument(id),
+           (client, rev, catid, itemid) -> client.addRevisionCatalogDocument(rev.getRevisionId(), catid, itemid),
+           (task, doc) -> task.copyDocument((Document)doc),
+           (peerdoc, localdoc) -> PeerGateway.hasChanged((Document)peerdoc, (Document)localdoc),
+           (task, peerdoc, localdoc) -> task.copyDocument((Document)peerdoc, (Document)localdoc),
+           (task, solid, doc) -> task.copyDocumentContent(solid, (Document)doc),
+           (client, doc) -> client.createDocument(doc),
+           (client, doc) -> client.updateDocument(doc));
+       private static ItemsHandler<MLPArtifact> artifactsHandler = new ItemsHandler<MLPArtifact>(
+           rev -> rev.getArtifacts(),
+           art -> art.getArtifactId(),
+           (client, id) -> client.getArtifact(id),
+           (client, rev, catid, itemid) -> client.addSolutionRevisionArtifact(rev.getSolutionId(), rev.getRevisionId(), itemid),
+           (task, art) -> task.copyArtifact((Artifact)art),
+           (peerart, localart) -> PeerGateway.hasChanged((Artifact)peerart, (Artifact)localart),
+           (task, peerart, localart) -> task.copyArtifact((Artifact)peerart, (Artifact)localart),
+           (task, solid, art) -> task.copyArtifactContent(solid, (Artifact)art),
+           (client, art) -> client.createArtifact(art),
+           (client, art) -> client.updateArtifact(art));
+
+       public static boolean hasChanged(Document thePeerDoc, Document theLocalDoc) {
+               if (thePeerDoc.getVersion() != null && theLocalDoc.getVersion() != null) {
+                       return !thePeerDoc.getVersion().equals(theLocalDoc.getVersion());
+               }
+
+               if (thePeerDoc.getSize() != null && theLocalDoc.getSize() != null) {
+                       return !thePeerDoc.getSize().equals(theLocalDoc.getSize());
+               }
+
+               return true;
+       }
+
+       public static boolean hasChanged(Artifact thePeerArtifact, Artifact theLocalArtifact) {
+               if (thePeerArtifact.getVersion() != null && theLocalArtifact.getVersion() != null) {
+                       return !thePeerArtifact.getVersion().equals(theLocalArtifact.getVersion());
+               }
+
+               if (thePeerArtifact.getSize() != null && theLocalArtifact.getSize() != null) {
+                       return !thePeerArtifact.getSize().equals(theLocalArtifact.getSize());
+               }
+
+               return true;
        }
 }
index 4dfde97..a9f0344 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -126,7 +126,7 @@ public class ONAP {
 
        @EventListener
        public void handlePeerSubscriptionUpdate(PeerSubscriptionEvent theEvent) {
-               log.info("received peer subscription update event " + theEvent);
+               log.info("received peer subscription update event {}", theEvent);
                taskExecutor.execute(new ONAPPushTask(theEvent.getPeer(), theEvent.getSubscription()));
        }
 
@@ -147,8 +147,10 @@ public class ONAP {
                        // sdc assettype, category and subcategory
 
                        Map selector = null;
+                       String catalogId = null;
                        try {
                                selector = Utils.jsonStringToMap(this.sub.getSelector());
+                               catalogId = (String)selector.get("catalogId");
                        }
                        catch(Exception x) {
                                log.error("Failed to parse selector for subscription {}", this.sub);
@@ -168,7 +170,7 @@ public class ONAP {
 
                        List<MLPSolution> acumosSolutions = null;
                        try {
-                               acumosSolutions = (List)acumosClient.getSolutions(selector).getContent();
+                               acumosSolutions = (List<MLPSolution>)acumosClient.getSolutions(catalogId).getContent();
                        }
                        catch(Exception x) {
                                log.error("Processing peer " + this.peer + " subscription " + this.sub.getSubId() + ": getSolutions failed.", x);
@@ -178,7 +180,7 @@ public class ONAP {
 
                        JSONArray sdcAssets = null;
                        try {
-                               sdcAssets = asdc.getAssets(AssetType.resource, JSONArray.class, "Generic", "Abstract").waitForResult();
+                               sdcAssets = asdc.getAssets(AssetType.resource, JSONArray.class, "Generic", "Abstract");
                        }
                        catch (Exception x) {
                                log.error("Failed to list ONAP SDC assets: " + x.getCause(), x);
@@ -195,7 +197,7 @@ public class ONAP {
 
                                List<MLPSolutionRevision> acumosRevisions = null;
                                try {
-                                       acumosRevisions = (List<MLPSolutionRevision>) acumosClient
+                                       acumosRevisions = acumosClient
                                                        .getSolutionRevisions(acumosSolution.getSolutionId()).getContent();
                                }
                                catch (Exception x) {
@@ -212,14 +214,9 @@ public class ONAP {
                                                sdcAsset = createSdcAsset(acumosSolution, acumosRevisions.get(acumosRevisions.size()-1));
                                        }
                                        else {
-                                               // ONAP.this.asdc.checkoutResource(UUID.fromString(sdcAsset.getString("artifactUUID")),
-                                               // ONAP.this.asdcOperator, "updated solution import");
                                                sdcAsset = updateSdcAsset(sdcAsset, acumosSolution, acumosRevisions);
                                        }
                                        updateAssetArtifacts(sdcAsset, acumosSolution, acumosRevisions);
-                                       // ONAP.this.asdc.checkinResource(UUID.fromString(sdcAsset.getString("artifactUUID")),
-                                       // ONAP.this.asdcOperator, "solution imported " + " the acumos revision number
-                                       // ");
                                }
                                catch (Exception x) {
                                        log.error("Mapping of acumos solution failed for: " + acumosSolution + ": " + x);
@@ -239,7 +236,7 @@ public class ONAP {
                }
 
                public JSONObject createSdcAsset(MLPSolution theSolution, MLPSolutionRevision theRevision) throws Exception {
-                       log.info("Creating ONAP SDC VF for solution " + theSolution);
+                       log.info("Creating ONAP SDC VF for solution {}", theSolution);
 
                        try {
                                return ONAP.this.asdc.createVF()
@@ -252,8 +249,8 @@ public class ONAP {
                                                .withVendorRelease(theRevision.getVersion()) //is this meaningful ? given that it cannot be updated ..
                                                .withTags("acumos", theSolution.getSolutionId()) // can I fit an UUID as tag ??
                                                .withOperator(ONAP.this.asdcOperator/* theSolution.getOwnerId() */) // probably won't work, SDC
-                                                                                                                                                                                       // expects an att uuid
-                                               .execute().waitForResult();
+                                               // expects a user uuid
+                                               .get();
                        }
                        catch (Exception x) {
                                log.error("Failed to create ONAP SDC VF", x);
@@ -273,7 +270,7 @@ public class ONAP {
                 * @return SDC Asset info
                 */
                public JSONObject updateSdcAsset(JSONObject theAssetInfo, MLPSolution theSolution, List<MLPSolutionRevision> theRevisions) {
-                       log.info("Updating ONAP SDC VF " + theAssetInfo.optString("uuid") + " for Acumos solution " + theSolution);
+                       log.info("Updating ONAP SDC VF {} for Acumos solution {}", theAssetInfo.optString("uuid"), theSolution);
                        return theAssetInfo;
                }
 
@@ -281,8 +278,7 @@ public class ONAP {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                throws Exception {
                        try {
                                theAssetInfo = ONAP.this.asdc
-                                               .getAsset(AssetType.resource, UUID.fromString(theAssetInfo.getString("uuid")), JSONObject.class)
-                                               .waitForResult();
+                                               .getAsset(AssetType.resource, UUID.fromString(theAssetInfo.getString("uuid")), JSONObject.class);
                        }
                        catch (Exception x) {
                                log.error("Failed to retrieve ONAP SDC asset metadata for " + theAssetInfo.getString("uuid") + " : " + x);
@@ -300,7 +296,7 @@ public class ONAP {
 
                        List<MLPArtifact> acumosArtifacts = null;
                        try {
-                               acumosArtifacts = (List<MLPArtifact>) clients.getFederationClient(this.peer.getApiUrl())
+                               acumosArtifacts = clients.getFederationClient(this.peer.getApiUrl())
                                        .getArtifacts(theSolution.getSolutionId(), mappedAcumosRevision.getRevisionId())
                                                .getContent();
                        }
@@ -310,7 +306,7 @@ public class ONAP {
                        }
 
                        if (acumosArtifacts == null)
-                               acumosArtifacts = new LinkedList<MLPArtifact>();
+                               acumosArtifacts = new LinkedList<>();
 
                        //add an artifact to be mapped for revision tracking purposes
                        {
@@ -330,12 +326,11 @@ public class ONAP {
                        //!! we support a 1-to-n mapping of artifacts from Acumos to SDC
 
                        // acumos artifacts that do not exist locally need to be added
-                       List<MLPArtifact> newArtifacts = new LinkedList<MLPArtifact>();
-                       Map<MLPArtifact, JSONArray> updatedArtifacts = new HashMap<MLPArtifact, JSONArray>();
-                       // List<JSONObject> oldArtifacts = new LinkedList<JSONObject>();
+                       List<MLPArtifact> newArtifacts = new LinkedList<>();
+                       Map<MLPArtifact, JSONArray> updatedArtifacts = new HashMap<>();
 
-                       log.info("Acumos artifacts: " + acumosArtifacts);
-                       log.info("SDC artifacts: " + sdcArtifacts);
+                       log.info("Acumos artifacts: {}", acumosArtifacts);
+                       log.info("SDC artifacts: {}", sdcArtifacts);
 
                        for (MLPArtifact acumosArtifact : acumosArtifacts) {
                                JSONArray sdcMappedArtifacts = new JSONArray();
@@ -359,13 +354,13 @@ public class ONAP {
                                }
                        }
 
-                       log.info("New artifacts: " + newArtifacts);
+                       log.info("New artifacts: {}", newArtifacts);
                        for (MLPArtifact acumosArtifact : newArtifacts) {
                                try {
                                        for (ASDC.ArtifactUploadAction uploadAction:
                                                                mapNewArtifact(theAssetInfo, theSolution.getSolutionId(), mappedAcumosRevision.getRevisionId(),
                                                                                                                         acumosArtifact)) {
-                                               uploadAction.execute().waitForResult();
+                                               uploadAction.get();
                                        }
                                }
                                catch (Exception x) {
@@ -373,14 +368,14 @@ public class ONAP {
                                }
                        }
 
-                       log.warn("Updated SDC artifacts: " + updatedArtifacts.keySet());
+                       log.warn("Updated SDC artifacts: {}", updatedArtifacts.keySet());
                        for (Map.Entry<MLPArtifact, JSONArray> updateEntry : updatedArtifacts.entrySet()) {
                                MLPArtifact acumosArtifact = updateEntry.getKey();
                                try {
                                        for (ASDC.ArtifactUpdateAction updateAction: 
                                                                mapArtifact(theAssetInfo, theSolution.getSolutionId(), mappedAcumosRevision.getRevisionId(),
                                                                                                                updateEntry.getKey(), updateEntry.getValue())) {
-                                               updateAction.execute().waitForResult();
+                                               updateAction.get();
                                        }
                                }
                                catch (Exception x) {
@@ -391,7 +386,7 @@ public class ONAP {
                        // sdc artifacts that do not have a acumos counterpart should be deleted (if
                        // they are labeled as having
                        // originated in acumos).
-                       List<JSONObject> deletedArtifacts = new LinkedList<JSONObject>();
+                       List<JSONObject> deletedArtifacts = new LinkedList<>();
                        for (int i = 0; i < sdcArtifacts.length(); i++) {
                                JSONObject sdcArtifact = sdcArtifacts.getJSONObject(i);
                                boolean found = false;
@@ -405,12 +400,12 @@ public class ONAP {
                                        deletedArtifacts.add(sdcArtifact);
                                }
                        }
-                       log.warn("Deleted SDC artifacts: " + deletedArtifacts);
+                       log.warn("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();
+                                                       .get();
                                }
                                catch (Exception x) {
                                        log.error("Failed to delete ONAP SDC VF Artifact", x);
@@ -432,7 +427,7 @@ public class ONAP {
                                }
                                catch (Exception x) {
                                        log.error("Failed to retrieve Acumoms artifact content from " + theAcumosArtifact.getUri(), x);
-                                       return Collections.EMPTY_LIST;
+                                       return Collections.emptyList();
                                }
 
                                JSONObject models = null;
@@ -441,14 +436,14 @@ public class ONAP {
                                }
                                catch (JSONException jsonx) {
                                        log.error("Failed to parse toscalab output", jsonx);
-                                       return Collections.EMPTY_LIST;
+                                       return Collections.emptyList();
                                }
                                catch (Exception x) {
                                        log.error("Failed to process DCAE component specification from " + theAcumosArtifact, x);
-                                       return Collections.EMPTY_LIST;
+                                       return Collections.emptyList();
                                }
 
-                               List<ASDC.ArtifactUploadAction> actions = new LinkedList<ASDC.ArtifactUploadAction>();
+                               List<ASDC.ArtifactUploadAction> actions = new LinkedList<>();
                                for (String model: models.keySet()) {
                                        actions.add(
                                                asdc.createAssetArtifact(AssetType.resource, UUID.fromString(theSDCAsset.getString("uuid")))
@@ -479,7 +474,7 @@ public class ONAP {
                        } 
                        else {
                                //everything else gets ignored at this point
-                               return Collections.EMPTY_LIST;
+                               return Collections.emptyList();
                        }
                }
                
@@ -494,7 +489,7 @@ public class ONAP {
                                }
                                catch (Exception x) {
                                        log.error("Failed to retrieve Acumoms artifact content from " + theAcumosArtifact.getUri(), x);
-                                       return Collections.EMPTY_LIST;
+                                       return Collections.emptyList();
                                }
 
                                JSONObject models = null;
@@ -503,14 +498,14 @@ public class ONAP {
                                }
                                catch (JSONException jsonx) {
                                        log.error("Failed to parse toscalab output", jsonx);
-                                       return Collections.EMPTY_LIST;
+                                       return Collections.emptyList();
                                }
                                catch (Exception x) {
                                        log.error("Failed to process DCAE component specification from " + theAcumosArtifact, x);
-                                       return Collections.EMPTY_LIST;
+                                       return Collections.emptyList();
                                }
 
-                               List<ASDC.ArtifactUpdateAction> actions = new LinkedList<ASDC.ArtifactUpdateAction>();
+                               List<ASDC.ArtifactUpdateAction> actions = new LinkedList<>();
                                for (int i = 0; i < theSDCArtifacts.length(); i++) {
                                        JSONObject sdcArtifact = theSDCArtifacts.getJSONObject(i);
                                        actions.add(
@@ -534,7 +529,7 @@ public class ONAP {
                        } 
                        else {
                                log.error("Found sdc artifacts for mlp artifact we do not process {}: {} ", theAcumosArtifact, theSDCArtifacts);
-                               return Collections.EMPTY_LIST;
+                               return Collections.emptyList();
                        }
                }
 
@@ -589,14 +584,11 @@ public class ONAP {
                                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                                StreamUtils.copy(
                                        clients.getFederationClient(this.peer.getApiUrl())
-                                               .getArtifactContent(theAcumosSolutionId, theAcumosRevisionId, theAcumosArtifact.getArtifactId())
+                                               .getArtifactContent(theAcumosArtifact.getArtifactId())
                                                        .getInputStream(),
                                        bos);
                                return bos.toByteArray();
                        }
-                       //else {
-                       //      return IOUtils.toByteArray(new URI(theAcumosArtifact.getUri()));
-                       //}
                }
        }
 
@@ -608,7 +600,7 @@ public class ONAP {
 
                JSONArray sdcAssets = null;
                try {
-                       sdcAssets = asdc.getAssets(AssetType.resource, JSONArray.class, "Generic", "Abstract").waitForResult();
+                       sdcAssets = asdc.getAssets(AssetType.resource, JSONArray.class, "Generic", "Abstract");
                } catch (Throwable x) {
                        log.info("Cleanup failed to list ONAP SDC assets: " + x.getCause(), x);
                }
@@ -622,7 +614,7 @@ public class ONAP {
                        if (state != null && "NOT_CERTIFIED_CHECKEOUT".equals(state)) {
                                try {
                                        asdc.cycleAsset(AssetType.resource, UUID.fromString(sdcAsset.getString("uuid")),
-                                                       LifecycleState.undocheckout, ONAP.this.asdcOperator, null).waitForResult();
+                                                       LifecycleState.undocheckout, ONAP.this.asdcOperator, null);
                                }
                                catch (Exception x) {
                                        log.error("Cleanup ONAP SDC asset: " + sdcAsset.optString("uuid"), x);
index b6a6261..4331d0e 100644 (file)
@@ -26,7 +26,6 @@ import java.io.UncheckedIOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Collections;
-import java.util.List;
 import java.util.UUID;
 import java.util.function.UnaryOperator;
 import java.util.function.Supplier;
@@ -35,14 +34,10 @@ import java.util.logging.Logger;
 
 import javax.annotation.PostConstruct;
 
-import org.acumos.federation.gateway.util.Action;
-import org.acumos.federation.gateway.util.Future;
-import org.acumos.federation.gateway.util.Futures;
 import org.acumos.federation.gateway.util.JSONHttpMessageConverter;
-//import org.springframework.util.DigestUtils;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.RegExUtils;
 import org.json.JSONArray;
 import org.json.JSONObject;
 import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -54,17 +49,13 @@ import org.springframework.http.HttpRequest;
 import org.springframework.http.MediaType;
 import org.springframework.http.RequestEntity;
 import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.AsyncClientHttpRequestExecution;
-import org.springframework.http.client.AsyncClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
 import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.util.Base64Utils;
-import org.springframework.util.concurrent.ListenableFuture;
-import org.springframework.util.concurrent.ListenableFutureCallback;
-import org.springframework.web.client.AsyncRestTemplate;
-import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
 import org.springframework.web.client.RestClientException;
 
 @Component("asdc")
@@ -72,42 +63,37 @@ import org.springframework.web.client.RestClientException;
 @ConfigurationProperties(prefix = "asdc")
 public class ASDC {
 
-       public static enum AssetType {
+       public enum AssetType {
                resource, service, product
        }
 
-       public static enum ArtifactType {
+       public enum ArtifactType {
                DCAE_TOSCA, DCAE_JSON, DCAE_POLICY, DCAE_DOC, DCAE_EVENT, DCAE_INVENTORY_TOSCA, DCAE_INVENTORY_JSON, DCAE_INVENTORY_POLICY, DCAE_INVENTORY_DOC, DCAE_INVENTORY_BLUEPRINT, DCAE_INVENTORY_EVENT, HEAT, HEAT_VOL, HEAT_NET, HEAT_NESTED, HEAT_ARTIFACT, HEAT_ENV, OTHER
        }
 
-       public static enum ArtifactGroupType {
+       public enum ArtifactGroupType {
                DEPLOYMENT, INFORMATIONAL
        }
 
-       public static enum LifecycleState {
+       public enum LifecycleState {
                Checkin, Checkout, Certify, undocheckout
        }
 
-       // @Retention(RetentionPolicy.RUNTIME)
-       // @Target(ElementType.METHOD)
-       // public @interface Mandatory {
-       // }
-
        private Logger log = Logger.getLogger(ASDC.class.getName());
 
        private URI rootUri;
-       private String rootPath = "/asdc/"; // "/sdc1/feproxy/"; //"/sdc/v1/catalog/";
-       private String user, passwd;
+       private String rootPath = "/asdc/";
+       private String user;
+       private String passwd;
        private String instanceId;
+       private Supplier<RestTemplate> rtfactory = RestTemplate::new;
 
-       private Supplier<AsyncRestTemplate> artfactory = () -> new AsyncRestTemplate();
-
-       public void setARTFactory(Supplier<AsyncRestTemplate> factory) {
-               artfactory = factory;
+       public void setRTFactory(Supplier<RestTemplate> factory) {
+               rtfactory = factory;
        }
 
-       public Supplier<AsyncRestTemplate> getARTFactory() {
-               return artfactory;
+       public Supplier<RestTemplate> getRTFactory() {
+               return rtfactory;
        }
 
        public void setUri(URI theUri) {
@@ -176,57 +162,57 @@ public class ASDC {
        public void initASDC() {
        }
 
-       public <T> Future<T> getResources(Class<T> theType) {
+       public <T> T getResources(Class<T> theType) {
                return getAssets(AssetType.resource, theType);
        }
 
-       public Future<JSONArray> getResources() {
+       public JSONArray getResources() {
                return getAssets(AssetType.resource, JSONArray.class);
        }
 
-       public <T> Future<T> getResources(Class<T> theType, String theCategory, String theSubCategory) {
+       public <T> T getResources(Class<T> theType, String theCategory, String theSubCategory) {
                return getAssets(AssetType.resource, theType, theCategory, theSubCategory);
        }
 
-       public Future<JSONArray> getResources(String theCategory, String theSubCategory) {
+       public JSONArray getResources(String theCategory, String theSubCategory) {
                return getAssets(AssetType.resource, JSONArray.class, theCategory, theSubCategory);
        }
 
-       public <T> Future<T> getServices(Class<T> theType) {
+       public <T> T getServices(Class<T> theType) {
                return getAssets(AssetType.service, theType);
        }
 
-       public Future<JSONArray> getServices() {
+       public JSONArray getServices() {
                return getAssets(AssetType.service, JSONArray.class);
        }
 
-       public <T> Future<T> getServices(Class<T> theType, String theCategory, String theSubCategory) {
+       public <T> T getServices(Class<T> theType, String theCategory, String theSubCategory) {
                return getAssets(AssetType.service, theType, theCategory, theSubCategory);
        }
 
-       public Future<JSONArray> getServices(String theCategory, String theSubCategory) {
+       public JSONArray getServices(String theCategory, String theSubCategory) {
                return getAssets(AssetType.service, JSONArray.class, theCategory, theSubCategory);
        }
 
-       public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType) {
+       public <T> T getAssets(AssetType theAssetType, Class<T> theType) {
                return fetch(refAssets(theAssetType), theType);
        }
 
-       public <T> Action<T> getAssetsAction(AssetType theAssetType, Class<T> theType) {
+       public <T> Supplier<T> getAssetsAction(AssetType theAssetType, Class<T> theType) {
                return (() -> fetch(refAssets(theAssetType), theType));
        }
 
-       public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType, String theCategory,
+       public <T> T getAssets(AssetType theAssetType, Class<T> theType, String theCategory,
                        String theSubCategory) {
                return getAssets(theAssetType, theType, theCategory, theSubCategory, null);
        }
 
-       public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType, String theCategory, String theSubCategory,
+       public <T> T getAssets(AssetType theAssetType, Class<T> theType, String theCategory, String theSubCategory,
                        String theResourceType) {
                return fetch(refAssets(theAssetType) + filter(theCategory, theSubCategory, theResourceType), theType);
        }
 
-       public <T> Action<T> getAssetsAction(AssetType theAssetType, Class<T> theType, String theCategory,
+       public <T> Supplier<T> getAssetsAction(AssetType theAssetType, Class<T> theType, String theCategory,
                        String theSubCategory, String theResourceType) {
                return (() -> fetch(refAssets(theAssetType) + filter(theCategory, theSubCategory, theResourceType), theType));
        }
@@ -254,67 +240,67 @@ public class ASDC {
                return this.rootPath + theAssetType + "s/" + theId;
        }
 
-       public <T> Future<T> getResource(UUID theId, Class<T> theType) {
+       public <T> T getResource(UUID theId, Class<T> theType) {
                return getAsset(AssetType.resource, theId, theType);
        }
 
-       public Future<JSONObject> getResource(UUID theId) {
+       public JSONObject getResource(UUID theId) {
                return getAsset(AssetType.resource, theId, JSONObject.class);
        }
 
-       public <T> Future<T> getService(UUID theId, Class<T> theType) {
+       public <T> T getService(UUID theId, Class<T> theType) {
                return getAsset(AssetType.service, theId, theType);
        }
 
-       public Future<JSONObject> getService(UUID theId) {
+       public JSONObject getService(UUID theId) {
                return getAsset(AssetType.service, theId, JSONObject.class);
        }
 
-       public <T> Future<T> getAsset(AssetType theAssetType, UUID theId, Class<T> theType) {
+       public <T> T getAsset(AssetType theAssetType, UUID theId, Class<T> theType) {
                return fetch(refAsset(theAssetType, theId) + "/metadata", theType);
        }
 
-       public <T> Action<T> getAssetAction(AssetType theAssetType, UUID theId, Class<T> theType) {
+       public <T> Supplier<T> getAssetAction(AssetType theAssetType, UUID theId, Class<T> theType) {
                return (() -> fetch(refAsset(theAssetType, theId) + "/metadata", theType));
        }
 
-       public Future<byte[]> getResourceArchive(UUID theId) {
+       public byte[] getResourceArchive(UUID theId) {
                return getAssetArchive(AssetType.resource, theId);
        }
 
-       public Future<byte[]> getServiceArchive(UUID theId) {
+       public byte[] getServiceArchive(UUID theId) {
                return getAssetArchive(AssetType.service, theId);
        }
 
-       public Future<byte[]> getAssetArchive(AssetType theAssetType, UUID theId) {
+       public byte[] getAssetArchive(AssetType theAssetType, UUID theId) {
                return fetch(refAsset(theAssetType, theId) + "/toscaModel", byte[].class);
        }
 
-       public Action<byte[]> getAssetArchiveAction(AssetType theAssetType, UUID theId) {
+       public Supplier<byte[]> getAssetArchiveAction(AssetType theAssetType, UUID theId) {
                return (() -> fetch(refAsset(theAssetType, theId) + "/toscaModel", byte[].class));
        }
 
-       public Future<JSONObject> checkinResource(UUID theId, String theUser, String theMessage) {
+       public JSONObject checkinResource(UUID theId, String theUser, String theMessage) {
                return cycleAsset(AssetType.resource, theId, LifecycleState.Checkin, theUser, theMessage);
        }
 
-       public Future<JSONObject> checkinService(UUID theId, String theUser, String theMessage) {
+       public JSONObject checkinService(UUID theId, String theUser, String theMessage) {
                return cycleAsset(AssetType.service, theId, LifecycleState.Checkin, theUser, theMessage);
        }
 
-       public Future<JSONObject> checkoutResource(UUID theId, String theUser, String theMessage) {
+       public JSONObject checkoutResource(UUID theId, String theUser, String theMessage) {
                return cycleAsset(AssetType.resource, theId, LifecycleState.Checkout, theUser, theMessage);
        }
 
-       public Future<JSONObject> checkoutService(UUID theId, String theUser, String theMessage) {
+       public JSONObject checkoutService(UUID theId, String theUser, String theMessage) {
                return cycleAsset(AssetType.service, theId, LifecycleState.Checkout, theUser, theMessage);
        }
 
-       public Future<JSONObject> certifyResource(UUID theId, String theUser, String theMessage) {
+       public JSONObject certifyResource(UUID theId, String theUser, String theMessage) {
                return cycleAsset(AssetType.resource, theId, LifecycleState.Certify, theUser, theMessage);
        }
 
-       public Future<JSONObject> certifyService(UUID theId, String theUser, String theMessage) {
+       public JSONObject certifyService(UUID theId, String theUser, String theMessage) {
                return cycleAsset(AssetType.service, theId, LifecycleState.Certify, theUser, theMessage);
        }
 
@@ -322,10 +308,10 @@ public class ASDC {
         * Normally theMessage is mandatory (and we'd use put instead of putOpt) but ..
         * not so for undocheckout ..
         */
-       public Future<JSONObject> cycleAsset(AssetType theAssetType, UUID theId, LifecycleState theState, String theUser,
+       public JSONObject cycleAsset(AssetType theAssetType, UUID theId, LifecycleState theState, String theUser,
                        String theMessage) {
                return post(refAsset(theAssetType, theId) + "/lifecycleState/" + theState,
-                               (headers) -> prepareHeaders(headers).header("USER_ID", theUser),
+                               headers -> prepareHeaders(headers).header("USER_ID", theUser),
                                new JSONObject().putOpt("userRemarks", theMessage));
        }
 
@@ -339,40 +325,40 @@ public class ASDC {
                return refAsset(theAssetType, theAssetId) + "/artifacts" + (theArtifactId == null ? "" : ("/" + theArtifactId));
        }
 
-       public <T> Future<T> getResourceArtifact(UUID theAssetId, UUID theArtifactId, Class<T> theType) {
+       public <T> T getResourceArtifact(UUID theAssetId, UUID theArtifactId, Class<T> theType) {
                return getAssetArtifact(AssetType.resource, theAssetId, theArtifactId, theType);
        }
 
-       public <T> Future<T> getServiceArtifact(UUID theAssetId, UUID theArtifactId, Class<T> theType) {
+       public <T> T getServiceArtifact(UUID theAssetId, UUID theArtifactId, Class<T> theType) {
                return getAssetArtifact(AssetType.service, theAssetId, theArtifactId, theType);
        }
 
-       public <T> Future<T> getResourceInstanceArtifact(UUID theAssetId, UUID theArtifactId, String theInstance,
+       public <T> T getResourceInstanceArtifact(UUID theAssetId, UUID theArtifactId, String theInstance,
                        Class<T> theType) {
                return getAssetInstanceArtifact(AssetType.resource, theAssetId, theInstance, theArtifactId, theType);
        }
 
-       public <T> Future<T> getServiceInstanceArtifact(UUID theAssetId, UUID theArtifactId, String theInstance,
+       public <T> T getServiceInstanceArtifact(UUID theAssetId, UUID theArtifactId, String theInstance,
                        Class<T> theType) {
                return getAssetInstanceArtifact(AssetType.service, theAssetId, theInstance, theArtifactId, theType);
        }
 
-       public <T> Future<T> getAssetArtifact(AssetType theAssetType, UUID theAssetId, UUID theArtifactId,
+       public <T> T getAssetArtifact(AssetType theAssetType, UUID theAssetId, UUID theArtifactId,
                        Class<T> theType) {
                return fetch(refAssetArtifact(theAssetType, theAssetId, theArtifactId), theType);
        }
 
-       public <T> Action<T> getAssetArtifactAction(AssetType theAssetType, UUID theAssetId, UUID theArtifactId,
+       public <T> Supplier<T> getAssetArtifactAction(AssetType theAssetType, UUID theAssetId, UUID theArtifactId,
                        Class<T> theType) {
                return (() -> fetch(refAssetArtifact(theAssetType, theAssetId, theArtifactId), theType));
        }
 
-       public <T> Future<T> getAssetInstanceArtifact(AssetType theAssetType, UUID theAssetId, String theInstance,
+       public <T> T getAssetInstanceArtifact(AssetType theAssetType, UUID theAssetId, String theInstance,
                        UUID theArtifactId, Class<T> theType) {
                return fetch(refAssetInstanceArtifact(theAssetType, theAssetId, theInstance, theArtifactId), theType);
        }
 
-       public <T> Action<T> getAssetInstanceArtifactAction(AssetType theAssetType, UUID theAssetId, String theInstance,
+       public <T> Supplier<T> getAssetInstanceArtifactAction(AssetType theAssetType, UUID theAssetId, String theInstance,
                        UUID theArtifactId, Class<T> theType) {
                return (() -> fetch(refAssetInstanceArtifact(theAssetType, theAssetId, theInstance, theArtifactId), theType));
        }
@@ -456,7 +442,7 @@ public class ASDC {
                return new ArtifactDeleteAction(theArtifactId).ofAssetInstance(theAssetType, theAssetId, theInstance);
        }
 
-       public abstract class ASDCAction<A extends ASDCAction<A, T>, T> implements Action<T> {
+       public abstract class ASDCAction<A extends ASDCAction<A, T>, T> implements Supplier<T> {
 
                protected JSONObject info; // info passed to asdc as request body
                protected String operatorId; // uid of the user performing the action: only required in the updatr
@@ -538,7 +524,7 @@ public class ASDC {
                }
 
                protected String normalizeInstanceName(String theName) {
-                       return StringUtils.removePattern(theName, "[ \\.\\-]+").toLowerCase();
+                       return RegExUtils.removePattern(theName, "[ \\.\\-]+").toLowerCase();
                }
 
                protected String[] mandatoryInfoEntries() {
@@ -605,9 +591,9 @@ public class ASDC {
                        return ASDC.this.uploadMandatoryEntries;
                }
 
-               public Future<JSONObject> execute() {
+               public JSONObject get() {
                        checkMandatory();
-                       return ASDC.this.post(ref(null), (headers) -> prepareHeaders(headers).header("USER_ID", this.operatorId),
+                       return ASDC.this.post(ref(null), headers -> prepareHeaders(headers).header("USER_ID", this.operatorId),
                                        this.info);
                }
        }
@@ -666,12 +652,12 @@ public class ASDC {
                        this.info.remove("artifactDescription");
                }
 
-               public Future<JSONObject> execute() {
+               public JSONObject get() {
                        UUID artifactUUID = UUID.fromString(this.info.getString("artifactUUID"));
                        checkMandatory();
                        cleanupInfoEntries();
                        return ASDC.this.post(ref(artifactUUID),
-                                       (headers) -> prepareHeaders(headers).header("USER_ID", this.operatorId), this.info);
+                                       headers -> prepareHeaders(headers).header("USER_ID", this.operatorId), this.info);
                }
        }
 
@@ -688,10 +674,10 @@ public class ASDC {
                        return this;
                }
 
-               public Future<JSONObject> execute() {
+               public JSONObject get() {
                        checkMandatory();
                        return ASDC.this.delete(ref(this.artifactId),
-                                       (headers) -> prepareHeaders(headers).header("USER_ID", this.operatorId));
+                                       headers -> prepareHeaders(headers).header("USER_ID", this.operatorId));
                }
        }
 
@@ -749,13 +735,13 @@ public class ASDC {
                        return with("contactId", theContact);
                }
 
-               public Future<JSONObject> execute() {
+               public JSONObject get() {
 
                        this.info.putOnce("contactId", this.operatorId);
                        this.info.append("tags", info.optString("name"));
                        checkMandatory();
                        return ASDC.this.post(refAssets(AssetType.resource),
-                                       (headers) -> prepareHeaders(headers).header("USER_ID", this.operatorId), this.info);
+                                       headers -> prepareHeaders(headers).header("USER_ID", this.operatorId), this.info);
                }
 
        }
@@ -821,13 +807,13 @@ public class ASDC {
                        return with("contactId", theContact);
                }
 
-               public Future<JSONObject> execute() {
+               public JSONObject get() {
 
                        this.info.putOnce("contactId", this.operatorId);
                        this.info.append("tags", info.optString("name"));
                        checkMandatory();
                        return ASDC.this.post(refAssets(AssetType.resource),
-                                       (headers) -> prepareHeaders(headers).header("USER_ID", this.operatorId), this.info);
+                                       headers -> prepareHeaders(headers).header("USER_ID", this.operatorId), this.info);
                }
 
        }
@@ -870,16 +856,16 @@ public class ASDC {
                                .header("X-ECOMP-InstanceID", this.instanceId);
        }
 
-       public <T> Future<T> fetch(String theRef, Class<T> theContentType) {
+       public <T> T fetch(String theRef, Class<T> theContentType) {
                return exchange(theRef, HttpMethod.GET, new HttpEntity(prepareHeaders()), theContentType);
        }
 
-       public Future<JSONObject> post(String theRef, JSONObject thePost) {
+       public JSONObject post(String theRef, JSONObject thePost) {
                return exchange(theRef, HttpMethod.POST, new HttpEntity<JSONObject>(thePost, prepareHeaders()),
                                JSONObject.class);
        }
 
-       public Future<JSONObject> post(String theRef, UnaryOperator<RequestEntity.HeadersBuilder> theHeadersBuilder,
+       public JSONObject post(String theRef, UnaryOperator<RequestEntity.HeadersBuilder> theHeadersBuilder,
                        JSONObject thePost) {
                RequestEntity.BodyBuilder builder = RequestEntity.post(refUri(theRef));
                theHeadersBuilder.apply(builder);
@@ -887,7 +873,7 @@ public class ASDC {
                return exchange(theRef, HttpMethod.POST, builder.body(thePost), JSONObject.class);
        }
 
-       public Future<JSONObject> delete(String theRef, UnaryOperator<RequestEntity.HeadersBuilder> theHeadersBuilder) {
+       public JSONObject delete(String theRef, UnaryOperator<RequestEntity.HeadersBuilder> theHeadersBuilder) {
 
                RequestEntity.HeadersBuilder builder = RequestEntity.delete(refUri(theRef));
                theHeadersBuilder.apply(builder);
@@ -895,88 +881,31 @@ public class ASDC {
                return exchange(theRef, HttpMethod.DELETE, builder.build(), JSONObject.class);
        }
 
-       public <T> Future<T> exchange(String theRef, HttpMethod theMethod, HttpEntity theRequest,
-                       Class<T> theResponseType) {
-
-               AsyncRestTemplate restTemplate = artfactory.get();
-
-               List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
-               converters.add(0, new JSONHttpMessageConverter());
-               restTemplate.setMessageConverters(converters);
+       private <T> T exchange(String theRef, HttpMethod theMethod, HttpEntity theRequest, Class<T> theResponseType) {
 
+               RestTemplate restTemplate = rtfactory.get();
+               restTemplate.getMessageConverters().add(0, new JSONHttpMessageConverter());
                restTemplate.setInterceptors(Collections.singletonList(new ContentMD5Interceptor()));
-               /*
-                * restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { public
-                * boolean hasError(ClientHttpResponse theResponse) throws IOException { if (404
-                * == theResponse.getRawStatusCode()) { System.out.println("Found a 404 !");
-                * return false; } return super.hasError(theResponse); }
-                * 
-                * protected byte[] getResponseBody(ClientHttpResponse theResponse) { if (404 ==
-                * theResponse.getRawStatusCode()) { return "[]".getBytes(); } return
-                * super.getResponseBody(theResponse); } });
-                */
-               // ResponseEntity<T> response = null;
-               ASDCFuture<T> result = new ASDCFuture<T>();
                String uri = this.rootUri + theRef;
                try {
-                       restTemplate.exchange(uri, theMethod, theRequest, theResponseType).addCallback(result.callback);
+                       ResponseEntity<T> response = restTemplate.exchange(uri, theMethod, theRequest, theResponseType);
+                       return response.getBody();
                } catch (RestClientException rcx) {
                        log.log(Level.WARNING, "Failed to fetch " + uri, rcx);
-                       return Futures.failedFuture(rcx);
-               } catch (Exception x) {
-                       log.log(Level.WARNING, "Failed to fetch " + uri, x);
-                       return Futures.failedFuture(x);
-               }
-
-               return result;
-       }
-
-       public class ASDCFuture<T> extends Futures.BasicFuture<T> {
-
-               private boolean http404toEmpty = false;
-
-               ASDCFuture() {
+                       throw rcx;
                }
-
-               public ASDCFuture setHttp404ToEmpty(boolean doEmpty) {
-                       this.http404toEmpty = doEmpty;
-                       return this;
-               }
-
-               ListenableFutureCallback<ResponseEntity<T>> callback = new ListenableFutureCallback<ResponseEntity<T>>() {
-
-                       public void onSuccess(ResponseEntity<T> theResult) {
-                               ASDCFuture.this.result(theResult.getBody());
-                       }
-
-                       public void onFailure(Throwable theError) {
-                               if (theError instanceof HttpClientErrorException) {
-                                       // if (theError.getRawStatusCode() == 404 && this.http404toEmpty)
-                                       // ASDCFuture.this.result(); //th eresult is of type T ...
-                                       // else
-                                       ASDCFuture.this.cause(new ASDCException((HttpClientErrorException) theError));
-                               } else {
-                                       ASDCFuture.this.cause(theError);
-                               }
-                       }
-               };
-
        }
 
-       public class ContentMD5Interceptor implements AsyncClientHttpRequestInterceptor {
+       private class ContentMD5Interceptor implements ClientHttpRequestInterceptor {
 
                @Override
-               public ListenableFuture<ClientHttpResponse> intercept(HttpRequest theRequest, byte[] theBody,
-                               AsyncClientHttpRequestExecution theExecution) throws IOException {
+               public ClientHttpResponse intercept(HttpRequest theRequest, byte[] theBody,
+                               ClientHttpRequestExecution theExecution) throws IOException {
                        if (HttpMethod.POST == theRequest.getMethod()) {
                                HttpHeaders headers = theRequest.getHeaders();
-                               headers.add("Content-MD5", Base64Utils.encodeToString(
-                                               // DigestUtils.md5Digest(theBody)));
-                                               DigestUtils.md5Hex(theBody).getBytes()));
-
+                               headers.add("Content-MD5", Base64Utils.encodeToString(DigestUtils.md5Hex(theBody).getBytes()));
                        }
-                       return theExecution.executeAsync(theRequest, theBody);
+                       return theExecution.execute(theRequest, theBody);
                }
        }
-
 }
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/cds/AccessType.java b/gateway/src/main/java/org/acumos/federation/gateway/cds/AccessType.java
deleted file mode 100644 (file)
index acc1932..0000000
+++ /dev/null
@@ -1,59 +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.cds;
-
-import java.util.EnumSet;
-
-/**
- * Supplements the CDS representation of a solution revision access type information.
- */
-public enum AccessType {
-
-       Organization("OR"), //
-       Public("PB"), //
-       Private("PR"), //
-       Restricted("RS")//
-       ;
-
-       private String                                                  code;
-       //private MLPAccessTypeCode     mlp;
-
-       private AccessType(String theCode) {
-               this.code = theCode;
-       }
-
-       public String code() {
-               return this.code;
-       }
-
-       //public MLPAccessType mlp() {
-       //      return this.mlp;
-       //}
-
-       public static AccessType forCode(final String theCode) {
-               return EnumSet.allOf(AccessType.class)
-                                               .stream()
-                                               .filter(status -> status.code().equals(theCode))
-                                               .findFirst()
-                                               .orElse(null);
-       }
-}
-
-
index 809aa43..d2cfe0f 100644 (file)
@@ -25,6 +25,7 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -48,15 +49,11 @@ public abstract class CodeNames<T extends CodeName> {
 
        private static CodeNamesService codes = null;
 
-       protected static Map<CodeNameType, List<MLPCodeNamePair>> codeNamePairs = new HashMap<>();
-       protected static Map<Class, List<CodeName>> codeNames = new HashMap<>();
+       protected static Map<CodeNameType, List<MLPCodeNamePair>> codeNamePairs = new EnumMap(CodeNameType.class);
+       protected static HashMap<Class, List<CodeName>> codeNames = new HashMap<>();
 
        @Autowired
        public void setCodeNamesService(CodeNamesService theService) {
-               if (codes != null && codes != theService) {
-                       log.warn("Mismatched auto (RE-)wiring. Has " + codes + ". Got " + theService);
-               }
-               // TODO: last value wins?   if (codes == null)
                codes = theService;
        }       
 
@@ -97,7 +94,7 @@ public abstract class CodeNames<T extends CodeName> {
                synchronized (codeNames) {
                        List<CodeName> codes = codeNames.get(theType);
                        if (codes == null) {
-                               codes = new LinkedList<CodeName>();
+                               codes = new LinkedList<>();
                                codeNames.put(theType, codes);
                        }
                        //cannot call the CodeName.getCode in here as it will trigger an attempt to load the codes
@@ -159,7 +156,7 @@ public abstract class CodeNames<T extends CodeName> {
                                                         this.pair.getName().equals(other.getName()); //we should also test the type ..
                        }
                        if (theMethod.getName().equals("toString")) {
-                               return this.pair.getCode().toString();
+                               return this.pair.getCode();
                        }
                        throw new IllegalArgumentException("Unexpected CodeName call: " + theMethod);
                }
index b6b6128..bc9db8e 100644 (file)
@@ -26,7 +26,7 @@ import org.acumos.cds.domain.MLPArtifact;
 import org.acumos.cds.domain.MLPCatalog;
 import org.acumos.cds.domain.MLPDocument;
 import org.acumos.cds.domain.MLPPeerSubscription;
-import org.acumos.cds.domain.MLPRevisionDescription;
+import org.acumos.cds.domain.MLPRevCatDescription;
 import org.acumos.cds.domain.MLPSolution;
 import org.acumos.cds.domain.MLPSolutionRevision;
 
@@ -70,7 +70,7 @@ public class Mapper {
                    .add(MLPCatalog.class, Catalog.class)
                    .add(MLPDocument.class, Document.class)
                    .add(MLPPeerSubscription.class, PeerSubscription.class)
-                   .add(MLPRevisionDescription.class, RevisionDescription.class)
+                   .add(MLPRevCatDescription.class, RevCatDescription.class)
                    .add(MLPSolution.class, Solution.class)
                    .add(MLPSolutionRevision.class, SolutionRevision.class)
                    .build();
index 0d54526..b2717a6 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -107,29 +107,27 @@ public class PeerSubscription extends MLPPeerSubscription {
        public static boolean isModified(MLPPeerSubscription theCurrentSub, MLPPeerSubscription theNewSub) {
                boolean res = true;
 
-               String taskSelector = theCurrentSub.getSelector(),
-                                        peerSelector = theNewSub.getSelector();
+               String taskSelector = theCurrentSub.getSelector();
+               String peerSelector = theNewSub.getSelector();
                res &= ((taskSelector != null && peerSelector == null) ||
                                                (taskSelector == null && peerSelector != null) ||
                                          (taskSelector != null && peerSelector != null && !taskSelector.equals(peerSelector)));
 
-               String taskOptions = theCurrentSub.getOptions(),
-                                        peerOptions = theNewSub.getOptions();
+               String taskOptions = theCurrentSub.getOptions();
+               String peerOptions = theNewSub.getOptions();
                res &= ((taskOptions != null && peerOptions == null) ||
                                                (taskOptions == null && peerOptions != null) ||
                                          (taskOptions != null && peerOptions != null && !taskOptions.equals(peerOptions)));
 
-               Long taskRefresh = theCurrentSub.getRefreshInterval(),
-                                peerRefresh = theNewSub.getRefreshInterval();
+               Long taskRefresh = theCurrentSub.getRefreshInterval();
+               Long peerRefresh = theNewSub.getRefreshInterval();
                res &= ((taskRefresh != null && peerRefresh == null) ||
                                                (taskRefresh == null && peerRefresh != null) ||
                                          (taskRefresh != null && peerRefresh != null && !taskRefresh.equals(peerRefresh)));
 
                //cannot be null
-               res &= !theCurrentSub.getScopeType().equals(theNewSub.getScopeType());
                res &= !theCurrentSub.getUserId().equals(theNewSub.getUserId());
                res &= !theCurrentSub.getPeerId().equals(theNewSub.getPeerId());
-               res &= !theCurrentSub.getAccessType().equals(theNewSub.getAccessType());
 
                return res;
        }
index ea818fe..64013df 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -63,9 +63,9 @@ public interface Reference {
        @JsonIgnore
        public default String getCanonicalFilename() {
                
-               String filename = getUriFilename(),
-                                        basename = FilenameUtils.getBaseName(filename),
-                                        extension = FilenameUtils.getExtension(filename);
+               String filename = getUriFilename();
+               String basename = FilenameUtils.getBaseName(filename);
+               String extension = FilenameUtils.getExtension(filename);
 
                log.debug("filename: {}, basename: {}, extension: {}", filename, basename, extension);
 
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
 package org.acumos.federation.gateway.cds;
 
 
-import org.acumos.cds.domain.MLPRevisionDescription;
+import org.acumos.cds.domain.MLPRevCatDescription;
 
 /**
  */
-public class RevisionDescription extends MLPRevisionDescription
-                                                                                                                                       implements TimestampedEntity {
+public class RevCatDescription extends MLPRevCatDescription implements TimestampedEntity {
 
 }
-
-
index 790c969..e5ce0db 100644 (file)
@@ -50,7 +50,7 @@ public class Solution extends MLPSolution {
                public static final String catalogId = "catalogId";
        };
 
-       private List<? extends MLPSolutionRevision>             revisions;
+       private List<MLPSolutionRevision>               revisions;
        private byte[] picture;
 
        public Solution() {
@@ -60,11 +60,11 @@ public class Solution extends MLPSolution {
                super(theCDSSolution);
        }
 
-       public void setRevisions(List<? extends MLPSolutionRevision> theRevisions) {
+       public void setRevisions(List<MLPSolutionRevision> theRevisions) {
                this.revisions = theRevisions;
        }
 
-       public List<? extends MLPSolutionRevision>      getRevisions() {
+       public List<MLPSolutionRevision>        getRevisions() {
                return this.revisions;
        }
 
index 8e2ea36..5d46906 100644 (file)
@@ -2,15 +2,15 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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
@@ -24,7 +24,7 @@ import java.util.List;
 
 import org.acumos.cds.domain.MLPArtifact;
 import org.acumos.cds.domain.MLPDocument;
-import org.acumos.cds.domain.MLPRevisionDescription;
+import org.acumos.cds.domain.MLPRevCatDescription;
 import org.acumos.cds.domain.MLPSolutionRevision;
 
 /**
@@ -33,13 +33,9 @@ import org.acumos.cds.domain.MLPSolutionRevision;
  */
 public class SolutionRevision extends MLPSolutionRevision {
 
-       public static interface Fields {
-               public static final String accessTypeCode = "accessTypeCode";
-       };
-
-       private List<? extends MLPArtifact>             artifacts = Collections.EMPTY_LIST;
-       private List<? extends MLPDocument>             documents = Collections.EMPTY_LIST;
-       private MLPRevisionDescription                          description;
+       private List<MLPArtifact>               artifacts = Collections.emptyList();
+       private List<MLPDocument>               documents = Collections.emptyList();
+       private MLPRevCatDescription                            description;
 
        public SolutionRevision() {
        }
@@ -48,27 +44,27 @@ public class SolutionRevision extends MLPSolutionRevision {
                super(theCDSRevision);
        }
 
-       public void setArtifacts(List<? extends MLPArtifact> theArtifacts) {
+       public void setArtifacts(List<MLPArtifact> theArtifacts) {
                this.artifacts = theArtifacts;
        }
 
-       public List<? extends MLPArtifact>      getArtifacts() {
+       public List<MLPArtifact>        getArtifacts() {
                return this.artifacts;
        }
 
-       public void setDocuments(List<? extends MLPDocument> theDocuments) {
+       public void setDocuments(List<MLPDocument> theDocuments) {
                this.documents = theDocuments;
        }
 
-       public List<? extends MLPDocument>      getDocuments() {
+       public List<MLPDocument>        getDocuments() {
                return this.documents;
        }
 
-       public void setRevisionDescription(MLPRevisionDescription theDescription) {
-               this.description = theDescription;      
+       public void setRevCatDescription(MLPRevCatDescription theDescription) {
+               this.description = theDescription;
        }
 
-       public MLPRevisionDescription getRevisionDescription() {
+       public MLPRevCatDescription getRevCatDescription() {
                return this.description;
        }
 
@@ -81,5 +77,3 @@ public class SolutionRevision extends MLPSolutionRevision {
        }
 
 }
-
-
index 5cd86df..857f961 100644 (file)
@@ -2,15 +2,15 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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
@@ -21,8 +21,6 @@ package org.acumos.federation.gateway.cds;
 
 import java.time.Instant;
 
-/**
- */
 public class SolutionRevisionBuilder {
 
        private SolutionRevision revision;
@@ -33,7 +31,7 @@ public class SolutionRevisionBuilder {
 
        public SolutionRevision build() {
                return this.revision;
-       } 
+       }
 
        public SolutionRevisionBuilder withCreated(Instant theInstant) {
                this.revision.setCreated(theInstant);
@@ -64,17 +62,12 @@ public class SolutionRevisionBuilder {
                this.revision.setVerifiedLicense(theCode);
                return this;
        }
-       
+
        public SolutionRevisionBuilder withVerifiedVulnerability(String theCode) {
                this.revision.setVerifiedVulnerability(theCode);
                return this;
        }
 
-       public SolutionRevisionBuilder withAccessTypeCode(String theCode) {
-               this.revision.setAccessTypeCode(theCode);
-               return this;
-       }
-
        public SolutionRevisionBuilder withOrigin(String theOrigin) {
                this.revision.setOrigin(theOrigin);
                return this;
@@ -84,7 +77,7 @@ public class SolutionRevisionBuilder {
                this.revision.setUserId(theUserId);
                return this;
        }
-       
+
        public SolutionRevisionBuilder withSource(String theSourceId) {
                this.revision.setSourceId(theSourceId);
                return this;
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
deleted file mode 100644 (file)
index caaa745..0000000
+++ /dev/null
@@ -1,58 +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.cds;
-
-import java.util.EnumSet;
-
-/**
- * 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
deleted file mode 100644 (file)
index 8811b84..0000000
+++ /dev/null
@@ -1,58 +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.cds;
-
-import java.util.EnumSet;
-
-/**
- * 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 adac473..8a9fe97 100644 (file)
@@ -34,17 +34,15 @@ import org.springframework.web.util.UriComponentsBuilder;
  */
 public enum API {
 
-       SOLUTIONS(Paths.SOLUTIONS, Queries.SOLUTIONS),
+       CATALOGS(Paths.CATALOGS),
+       SOLUTIONS(Paths.SOLUTIONS, Queries.CATALOG_ID),
        SOLUTION_DETAIL(Paths.SOLUTION_DETAILS),
        SOLUTION_REVISIONS(Paths.SOLUTION_REVISIONS),
-       SOLUTION_REVISION_DETAILS(Paths.SOLUTION_REVISION_DETAILS),
+       SOLUTION_REVISION_DETAILS(Paths.SOLUTION_REVISION_DETAILS, Queries.CATALOG_ID),
        SOLUTION_REVISION_ARTIFACTS(Paths.SOLUTION_REVISION_ARTIFACTS),
-       ARTIFACT_DETAILS(Paths.ARTIFACT_DETAILS),
        ARTIFACT_CONTENT(Paths.ARTIFACT_CONTENT),
-       SOLUTION_REVISION_DOCUMENTS(Paths.SOLUTION_REVISION_DOCUMENTS),
-       DOCUMENT_DETAILS(Paths.DOCUMENT_DETAILS),
+       SOLUTION_REVISION_DOCUMENTS(Paths.SOLUTION_REVISION_DOCUMENTS, Queries.CATALOG_ID),
        DOCUMENT_CONTENT(Paths.DOCUMENT_CONTENT),
-       CATALOGS(Paths.CATALOGS),
        PEERS(Paths.PEERS),
        SUBSCRIPTION(Paths.SUBSCRIPTION),
        PING(Paths.PING),
@@ -157,23 +155,18 @@ public enum API {
 
        public static interface Paths {
 
+               public static final String CATALOGS = "/catalogs";
                public static final String SOLUTIONS = "/solutions";
                public static final String SOLUTION_DETAILS = "/solutions/{solutionId}";
-
                public static final String SOLUTION_REVISIONS = "/solutions/{solutionId}/revisions";
                public static final String SOLUTION_REVISION_DETAILS = "/solutions/{solutionId}/revisions/{revisionId}";
-
                public static final String SOLUTION_REVISION_ARTIFACTS = "/solutions/{solutionId}/revisions/{revisionId}/artifacts";
-               public static final String ARTIFACT_DETAILS = "/solutions/{solutionId}/revisions/{revisionId}/artifacts/{artifactId}";
-               public static final String ARTIFACT_CONTENT = "/solutions/{solutionId}/revisions/{revisionId}/artifacts/{artifactId}/content";
-
-               public static final String SOLUTION_REVISION_DOCUMENTS = "/solutions/{solutionId}/revisions/{revisionId}/documents";
-               public static final String DOCUMENT_DETAILS = "/solutions/{solutionId}/revisions/{revisionId}/documents/{documentId}";
-               public static final String DOCUMENT_CONTENT = "/solutions/{solutionId}/revisions/{revisionId}/documents/{documentId}/content";
+               public static final String ARTIFACT_CONTENT = "/artifacts/{artifactId}/content";
+               public static final String SOLUTION_REVISION_DOCUMENTS = "/revisions/{revisionId}/documents";
+               public static final String DOCUMENT_CONTENT = "/documents/{documentId}/content";
 
                public static final String SUBSCRIPTION = "/subscription/{subscriptionId}";
 
-               public static final String CATALOGS = "/catalogs";
                public static final String PEERS = "/peers";
                public static final String PING = "/ping";
 
@@ -181,13 +174,21 @@ public enum API {
                public static final String PEER_UNREGISTER = "/peer/unregister";
        }
 
+       public static interface PathParameters {
+               public static final String PEER_ID = "peerId";
+               public static final String CATALOG_ID = "catalogId";
+               public static final String SOLUTION_ID = "solutionId";
+               public static final String REVISION_ID = "revisionId";
+               public static final String ARTIFACT_ID = "artifactId";
+               public static final String DOCUMENT_ID = "documentId";
+       }
        public static interface QueryParameters {
 
-               public static final String SOLUTIONS_SELECTOR = "selector";
+               public static final String CATALOG_ID = "catalogId";
        }
 
        public static interface Queries {
 
-               public static final List<String> SOLUTIONS = Collections.unmodifiableList(Arrays.asList(new String[] { QueryParameters.SOLUTIONS_SELECTOR }));
+               public static final List<String> CATALOG_ID = Collections.unmodifiableList(Arrays.asList(new String[] { QueryParameters.CATALOG_ID }));
        }
 }
index 1c205d5..b2409af 100644 (file)
@@ -27,7 +27,6 @@ import java.lang.invoke.MethodHandles;
 import java.net.URI;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.function.Supplier;
 
 import org.acumos.cds.domain.MLPArtifact;
@@ -36,7 +35,6 @@ import org.acumos.cds.domain.MLPDocument;
 import org.acumos.cds.domain.MLPPeer;
 import org.acumos.cds.domain.MLPSolution;
 import org.acumos.cds.domain.MLPSolutionRevision;
-import org.acumos.federation.gateway.util.Utils;
 import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.http.client.HttpClient;
 import org.slf4j.Logger;
@@ -52,7 +50,6 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.http.client.ClientHttpRequest;
 import org.springframework.http.client.ClientHttpResponse;
 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
-import org.springframework.util.Base64Utils;
 import org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.HttpStatusCodeException;
 
@@ -115,28 +112,16 @@ public class FederationClient extends AbstractClient {
        }
        /**
         * 
-        * @param theSelection
-        *            key-value pairs; ignored if null or empty. Gives special treatment
-        *            to Date-type values.
+        * @param theCatalogId
+        *             Catalog ID
         * @return List of MLPSolutions from Remote Acumos
         * @throws FederationException
         *             If remote acumos is not available
         */
-       public JsonResponse<List<MLPSolution>> getSolutions(Map<String, Object> theSelection)
-                       throws FederationException {
-
-               String selectorParam = null;
-               try {
-                       log.info("getSolutions selector {}", Utils.mapToJsonString(theSelection));
-                       selectorParam = theSelection == null ? null
-                                       : Base64Utils.encodeToString(Utils.mapToJsonString(theSelection).getBytes("UTF-8"));
-                       log.info("getSolutions encoded selector {}", selectorParam);
-               }
-               catch (Exception x) {
-                       throw new IllegalArgumentException("Cannot process the selection argument", x);
-               }
+       public JsonResponse<List<MLPSolution>> getSolutions(String theCatalogId) throws FederationException {
 
-               URI uri = API.SOLUTIONS.buildUri(this.baseUrl, selectorParam == null ? Collections.EMPTY_MAP : Collections.singletonMap(API.QueryParameters.SOLUTIONS_SELECTOR, selectorParam));
+               log.info("getSolutions Catalog ID {}", theCatalogId);
+               URI uri = API.SOLUTIONS.buildUri(this.baseUrl, Collections.singletonMap(API.QueryParameters.CATALOG_ID, theCatalogId));
                return handle(uri, new ParameterizedTypeReference<JsonResponse<List<MLPSolution>>>() {});
        }
 
@@ -174,15 +159,15 @@ public class FederationClient extends AbstractClient {
         *            Solution ID
         * @param theRevisionId
         *            Revision ID
+        * @param theCatalogId
+        *            Optional Catalog ID
         * @return Detailed artifact information from Remote Acumos. The returned value can be safely cast to ..gateway.cds.SolutionRevision.
         * @throws FederationException
         *             if remote acumos is not available
         */
-       public JsonResponse<MLPSolutionRevision> getSolutionRevision(String theSolutionId, String theRevisionId)
-                       throws FederationException {
-
+       public JsonResponse<MLPSolutionRevision> getSolutionRevision(String theSolutionId, String theRevisionId, String theCatalogId) throws FederationException {
                return handle(
-                    API.SOLUTION_REVISION_DETAILS.buildUri(this.baseUrl, theSolutionId, theRevisionId),
+                    API.SOLUTION_REVISION_DETAILS.buildUri(this.baseUrl, theSolutionId, theRevisionId, theCatalogId),
                     new ParameterizedTypeReference<JsonResponse<MLPSolutionRevision>>() {});
        }
 
@@ -203,48 +188,40 @@ public class FederationClient extends AbstractClient {
        }
 
        /**
-        * @param theSolutionId
-        *            Solution ID
-        * @param theRevisionId
-        *            Revision ID
         * @param theArtifactId
         *            Artifact ID
         * @return Resource
         * @throws FederationException On failure
         */
-       public Resource getArtifactContent(String theSolutionId, String theRevisionId, String theArtifactId) throws FederationException {
-               return download2(API.ARTIFACT_CONTENT.buildUri(this.baseUrl, theSolutionId, theRevisionId, theArtifactId));
+       public StreamingResource getArtifactContent(String theArtifactId) throws FederationException {
+               return download(API.ARTIFACT_CONTENT.buildUri(this.baseUrl, theArtifactId));
        }
 
        /**
         * 
-        * @param theSolutionId
-        *            Solution ID
         * @param theRevisionId
         *            Revision ID
+        * @param theCatalogId
+        *            Catalog ID
         * @return List of MLPDocuments from Remote Acumos
         * @throws FederationException
         *             if remote acumos is not available
         */
-       public JsonResponse<List<MLPDocument>> getDocuments(String theSolutionId, String theRevisionId) throws FederationException {
+       public JsonResponse<List<MLPDocument>> getDocuments(String theRevisionId, String theCatalogId) throws FederationException {
                return handle(
-                   API.SOLUTION_REVISION_DOCUMENTS.buildUri(this.baseUrl, theSolutionId, theRevisionId),
+                   API.SOLUTION_REVISION_DOCUMENTS.buildUri(this.baseUrl, theRevisionId, theCatalogId),
                    new ParameterizedTypeReference<JsonResponse<List<MLPDocument>>>() {});
        }
 
        /**
-        * @param theSolutionId
-        *            Solution ID
-        * @param theRevisionId
-        *            Revision ID
         * @param theDocumentId
         *            Document ID
         * @return Resource
         * @throws FederationException
         *             On failure
         */
-       public Resource getDocumentContent(String theSolutionId, String theRevisionId, String theDocumentId) throws FederationException {
-               return download2(API.DOCUMENT_CONTENT.buildUri(this.baseUrl, theSolutionId, theRevisionId, theDocumentId));
+       public StreamingResource getDocumentContent(String theDocumentId) throws FederationException {
+               return download(API.DOCUMENT_CONTENT.buildUri(this.baseUrl, theDocumentId));
        }
 
        /**
@@ -292,11 +269,6 @@ public class FederationClient extends AbstractClient {
                return handle(uri, () -> restTemplate.exchange(uri, HttpMethod.GET, null, type));
        }
 
-       protected Resource download(URI theUri) throws FederationException {
-               RequestEntity<Void> request = RequestEntity.get(theUri).accept(MediaType.ALL).build();
-               return handle(theUri, () -> restTemplate.exchange(request, Resource.class));
-       }
-
        /**
         * Download content of a URI.
         * E.g. the body of an artifact or document.
@@ -305,7 +277,7 @@ public class FederationClient extends AbstractClient {
         * @return Resource
         * @throws FederationException on failure
         */
-       protected StreamingResource download2(URI theUri) throws FederationException {
+       private StreamingResource download(URI theUri) throws FederationException {
                log.info("Query for download {}", theUri);
                ClientHttpResponse response = null;
                try {
@@ -337,7 +309,7 @@ public class FederationClient extends AbstractClient {
                }
 
                @Override
-               public InputStream getInputStream() throws IOException, IllegalStateException {
+               public InputStream getInputStream() throws IOException {
                        log.trace("Download input stream access at {}",ExceptionUtils.getStackTrace(new RuntimeException("Input stream access")) );
                        return super.getInputStream();
                }
index 36b4a43..7d187b6 100644 (file)
@@ -112,7 +112,7 @@ public class JsonResponse<T> implements Serializable {
        }
 
        public static <T> JsonResponseBuilder<T> buildResponse() {
-               return new JsonResponseBuilder<T>();
+               return new JsonResponseBuilder<>();
        }
 
        public static class JsonErrorResponseBuilder<T> {
@@ -140,7 +140,7 @@ public class JsonResponse<T> implements Serializable {
        }
        
        public static <T> JsonErrorResponseBuilder<T> buildErrorResponse() {
-               return new JsonErrorResponseBuilder<T>();
+               return new JsonErrorResponseBuilder<>();
        }
 
 }
index 7bc076f..9b4db68 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -99,19 +99,14 @@ public class DockerConfiguration {
 
        public void setDockerTlsVerify(Boolean doVerify) {
                this.builder.withDockerTlsVerify(doVerify);
-  }
-
-       /*
-       public void withCustomSslConfig(SSLConfig customSslConfig) {
        }
-       */
 
        public DockerClientConfig buildConfig() {
                return this.builder.build();
        }
 
        public DockerClient     getDockerClient() {
-    return DockerClientBuilder.getInstance(buildConfig())
+               return DockerClientBuilder.getInstance(buildConfig())
                        .withDockerCmdExecFactory(DockerClientBuilder.getDefaultDockerCmdExecFactory())
                        .build();
        }
index 0c0d908..85d497c 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -29,7 +29,6 @@ import org.acumos.federation.gateway.controller.RegistrationController;
 import org.apache.http.client.HttpClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-//import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -88,13 +87,13 @@ public class FederationConfiguration {
   @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        //@ConfigurationProperties(prefix = "server", ignoreInvalidFields = true)
        public HttpClient federationClient() {
-               log.debug(this + "::federationClient from " + this.interfaceConfig);
+               log.debug("{}::federationClient from {}", this, this.interfaceConfig);
                return this.interfaceConfig.buildClient();
        }
 
        @Bean
        public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> federationServer() {
-               log.debug(this + "::federationServer from " + this.interfaceConfig);
+               log.debug("{}::federationServer from {}", this, this.interfaceConfig);
                return new WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>() {
                        @Override
                        public void customize(ConfigurableServletWebServerFactory theServer) {
index fff55ea..8e4e30e 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -52,8 +52,6 @@ import org.apache.http.conn.socket.ConnectionSocketFactory;
 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
 import org.apache.http.conn.ssl.SSLContextBuilder;
-//import org.apache.http.ssl.SSLContexts;
-//import org.apache.http.ssl.SSLContextBuilder;
 import org.apache.http.conn.ssl.SSLContexts;
 import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.client.HttpClientBuilder;
@@ -81,21 +79,12 @@ public class InterfaceConfiguration {
        private Server  server; 
 
        public InterfaceConfiguration() {
-               log.trace(this + "::new");
+               log.trace("{}::new", this);
        }
 
-/*
-       public int getPoolSize() {
-               return this.poolSize;
-       }
-
-       public void setPoolSize(int thePoolSize) {
-               this.poolSize = thePoolSize;
-       }
-*/
        @PostConstruct
        public void initInterface() {
-               log.trace(this + "::init");
+               log.trace("{}::init", this);
        }       
 
        public String getAddress() {
@@ -281,8 +270,8 @@ public class InterfaceConfiguration {
                @Autowired
                private ResourceLoader resourceLoader;
 
-               private KeyStore        keyStore,
-                                                                                       trustStore;
+               private KeyStore        keyStore;
+               private KeyStore        trustStore;
 
                private String keyStoreLocation;
                private String keyStoreType = "JKS";
@@ -425,7 +414,7 @@ public class InterfaceConfiguration {
                        try {
                                store = KeyStore.getInstance(theType);
                                store.load(storeSource, thePasswd.toCharArray());
-                               log.trace("Loaded key store: " + theLocation);
+                               log.trace("Loaded key store: {}", theLocation);
                        }
                        catch (Exception x) {
                                throw new IllegalStateException("Error loading key material: " + x, x);
@@ -509,24 +498,19 @@ public class InterfaceConfiguration {
        public HttpClient buildClient() {
 
                SSLContext sslContext = null;
-               log.trace("Build HttpClient with " + this);
+               log.trace("Build HttpClient with {}", this);
 
                if (this.ssl == null) {
                        log.trace("No ssl config was provided");
                }
                else {
-                       KeyStore keyStore = this.ssl.loadKeyStore(),
-                                                        trustStore = this.ssl.loadTrustStore();
+                       KeyStore keyStore = this.ssl.loadKeyStore();
+                       KeyStore trustStore = this.ssl.loadTrustStore();
 
                        SSLContextBuilder contextBuilder = SSLContexts.custom();
                        try {
                                if (keyStore != null) {
-                                       contextBuilder.loadKeyMaterial(keyStore,
-                                                       this.ssl.keyStorePasswd.toCharArray()/*
-                                                                                                                                        * , (aliases, socket) -> {
-                                                                                                                                        * 
-                                                                                                                                        * return this.ssl.keyAlias; }
-                                                                                                                                        */);
+                                       contextBuilder.loadKeyMaterial(keyStore, this.ssl.keyStorePasswd.toCharArray());
                                }
 
                                if (trustStore != null) {
@@ -554,14 +538,6 @@ public class InterfaceConfiguration {
                        registryBuilder.register("https", sslSocketFactory);
                }
                Registry<ConnectionSocketFactory> registry = registryBuilder.build();
-
-               /*
-                * PoolingHttpClientConnectionManager connectionManager = new
-                * PoolingHttpClientConnectionManager(registry);
-                * connectionManager.setMaxTotal(this.poolSize);
-                * connectionManager.setDefaultMaxPerRoute(this.poolSize);
-                */
-
                CredentialsProvider credsProvider = null;
                if (hasClient()) {
                        credsProvider = new BasicCredentialsProvider();
@@ -574,7 +550,6 @@ public class InterfaceConfiguration {
 
                HttpClientBuilder clientBuilder = HttpClients.custom();
 
-               // clientBuilder.setConnectionManager(connectionManager);
                clientBuilder.setConnectionManager(new BasicHttpClientConnectionManager(registry));
 
                if (sslSocketFactory != null)
index 1727286..4015807 100644 (file)
@@ -90,7 +90,7 @@ public class LocalConfiguration {
        @Bean
   @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        public HttpClient localClient() {
-               log.debug(this + "::localClient from " + this.interfaceConfig);
+               log.debug("{}::localClient from {}", this, this.interfaceConfig);
                return interfaceConfig.buildClient();
        }
 
@@ -101,7 +101,7 @@ public class LocalConfiguration {
         */
        @Bean
        public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> localServer() {
-               log.debug(this + "::localServer from " + this.interfaceConfig);
+               log.debug("{}::localServer from {}", this, this.interfaceConfig);
                return new WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>() {
                        @Override
                        public void customize(ConfigurableServletWebServerFactory theServer) {
index e0adc9e..305bb22 100644 (file)
@@ -61,10 +61,12 @@ public abstract class AbstractController {
 
        /**
         * Handle common aspects of forwarding a local request to a peer Acumos.
+        * @param <T> the type of the expected response, from the peer
         * @param opname the name of the operation to perform
         * @param response the HTTP response for setting error codes
         * @param peerId the ID of the remote peer to call
         * @param fcn the operation to invoke on the remote peer
+        * @return response from peer
         */
        protected <T> JsonResponse<T> callPeer(String opname, HttpServletResponse response, String peerId, ThrowingFunction<FederationClient, JsonResponse<T>> fcn) {
                try {
index 4fba274..e4aca35 100644 (file)
@@ -24,7 +24,6 @@ import java.lang.invoke.MethodHandles;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.Callable;
 
 import javax.servlet.http.HttpServletRequest;
@@ -43,14 +42,12 @@ import org.acumos.federation.gateway.common.API;
 import org.acumos.federation.gateway.common.JsonResponse;
 import org.acumos.federation.gateway.service.CatalogService;
 import org.acumos.federation.gateway.service.ContentService;
-import org.acumos.federation.gateway.util.Utils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.Resource;
 import org.springframework.security.access.prepost.PreAuthorize;
 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;
@@ -76,17 +73,21 @@ public class CatalogController extends AbstractController {
        private ContentService contentService;
 
        /**
+        * List all catalogs the user is permitted to see.
+        *
         * @param theHttpRequest Request
         * @param theHttpResponse
         *            HttpServletResponse
         * @return List of Catalogs in JSON format.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).CATALOG_ACCESS)")
+       @PreAuthorize("isActive() && hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).CATALOG_ACCESS)")
        @ApiOperation(value = "Invoked by Peer Acumos to get a list of visible Catalogs from the local Acumos Instance .", response = MLPCatalog.class, responseContainer = "List")
-       @RequestMapping(value = { API.Paths.CATALOGS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @RequestMapping(value = API.Paths.CATALOGS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
-       public JsonResponse<List<MLPCatalog>> getCatalogs(HttpServletRequest theHttpRequest, HttpServletResponse theHttpResponse) {
+       public JsonResponse<List<MLPCatalog>> getCatalogs(
+           HttpServletRequest theHttpRequest,
+           HttpServletResponse theHttpResponse) {
                JsonResponse<List<MLPCatalog>> response = null;
                List<MLPCatalog> catalogs = null;
                log.debug(API.Paths.CATALOGS);
@@ -110,88 +111,98 @@ public class CatalogController extends AbstractController {
        }
 
        /**
+        * List all solutions in the specified catalog.
+        *
         * @param theHttpRequest Request
         * @param theHttpResponse
         *            HttpServletResponse
-        * @param theSelector
-        *            Solutions selector
+        * @param theCatalogId
+        *            The catalog
         * @return List of Published ML Solutions in JSON format.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).CATALOG_ACCESS)")
+       @PreAuthorize("isActive() && hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).CATALOG_ACCESS)")
        @ApiOperation(value = "Invoked by Peer Acumos to get a list of Published Solutions from the Catalog of the local Acumos Instance .", response = MLPSolution.class, responseContainer = "List")
-       @RequestMapping(value = { API.Paths.SOLUTIONS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @RequestMapping(value = API.Paths.SOLUTIONS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
        public JsonResponse<List<MLPSolution>> getSolutions(
-                       HttpServletRequest theHttpRequest,
-                       HttpServletResponse theHttpResponse,
-                       @RequestParam(value = API.QueryParameters.SOLUTIONS_SELECTOR, required = false) String theSelector) {
+           HttpServletRequest theHttpRequest,
+           HttpServletResponse theHttpResponse,
+           @RequestParam(value=API.QueryParameters.CATALOG_ID, required = true) String theCatalogId) {
                JsonResponse<List<MLPSolution>> response = null;
                List<MLPSolution> solutions = null;
                log.debug(API.Paths.SOLUTIONS);
                try {
-                       log.debug("getSolutions: selector " + theSelector);
-                       Map<String, ?> selector = null;
-                       if (theSelector != null)
-                               selector = Utils.jsonStringToMap(new String(Base64Utils.decodeFromString(theSelector), "UTF-8"));
-
-                       solutions = catalogService.getSolutions(selector, new ControllerContext());
+                       if (catalogService.isCatalogAllowed(theCatalogId, new ControllerContext())) {
+                               solutions = catalogService.getSolutions(theCatalogId, new ControllerContext());
+                       }
                        if (solutions != null) {
                                for (MLPSolution solution: solutions) {
                                        encodeSolution(solution, theHttpRequest);
                                }
                        }
-
                        response = JsonResponse.<List<MLPSolution>> buildResponse()
-                                                                                                               .withMessage("available public solution for given filter")
-                                                                                                               .withContent(solutions)
-                                                                                                               .build();
+                           .withMessage("available public solution for given filter")
+                           .withContent(solutions)
+                           .build();
                        theHttpResponse.setStatus(HttpServletResponse.SC_OK);
                        log.debug("getSolutions: provided {} solutions", solutions == null ? 0 : solutions.size());
                }
                catch (/*Exception*/Throwable x) {
                        response = JsonResponse.<List<MLPSolution>> buildErrorResponse()
-                                                                                                                .withError(x)
-                                                                                                                .build();
+                           .withError(x)
+                           .build();
                        theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        log.error("Exception occurred while fetching solutions", x);
                }
                return response;
        }
 
+       /**
+        * Retrieve details of the specified solution.
+        *
+        * @param theHttpRequest Request
+        * @param theHttpResponse
+        *            HttpServletResponse
+        * @param theSolutionId
+        *            The solution
+        * @return Published MLSolution in JSON format.
+        */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority('CATALOG_ACCESS')")
+       @PreAuthorize("isActive() && hasAuthority('CATALOG_ACCESS')")
        @ApiOperation(value = "Invoked by Peer Acumos to get a list detailed solution information from the Catalog of the local Acumos Instance .", response = MLPSolution.class)
-       @RequestMapping(value = { API.Paths.SOLUTION_DETAILS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @RequestMapping(value = API.Paths.SOLUTION_DETAILS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
        public JsonResponse<MLPSolution> getSolutionDetails(
                        HttpServletRequest theHttpRequest,
                        HttpServletResponse theHttpResponse,
-                       @PathVariable(value = "solutionId") String theSolutionId) {
+                       @PathVariable(API.PathParameters.SOLUTION_ID) String theSolutionId) {
                JsonResponse<MLPSolution> response = null;
                MLPSolution solution = null;
-               log.debug(API.Paths.SOLUTION_DETAILS + ": " + theSolutionId);
+               log.debug("{}: {}", API.Paths.SOLUTION_DETAILS, theSolutionId);
                try {
-                       solution = catalogService.getSolution(theSolutionId, new ControllerContext());
+                       if (catalogService.isSolutionAllowed(theSolutionId, new ControllerContext())) {
+                               solution = catalogService.getSolution(theSolutionId, new ControllerContext());
+                       }
                        if (null == solution) {
                                response = JsonResponse.<MLPSolution> buildResponse()
-                                                                                                                       .withMessage("No solution with id " + theSolutionId + " is available.")
-                                                                                                                       .build();
+                                   .withMessage("No solution with id " + theSolutionId + " is available.")
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        }
                        else {
                                encodeSolution(solution, theHttpRequest);
                                response = JsonResponse.<MLPSolution> buildResponse()
-                                                                                                                       .withMessage("solution details")
-                                                                                                                       .withContent(solution)
-                                                                                                                       .build();
+                                   .withMessage("solution details")
+                                   .withContent(solution)
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_OK);
                        }
                }
                catch (Exception x) {
                        response = JsonResponse.<MLPSolution> buildErrorResponse()
-                                                                                                                .withError(x)
-                                                                                                                .build();
+                           .withError(x)
+                           .build();
                        theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        log.error("An error occurred while fetching solution " + theSolutionId, x);
                }
@@ -199,44 +210,49 @@ public class CatalogController extends AbstractController {
        }
 
        /**
-        * @param theSolutionId
-        *            Solution ID
+        * List the revisions of the specified solution.
+        *
         * @param theHttpResponse
         *            HttpServletResponse
+        * @param theSolutionId
+        *            Solution ID
         * @return List of Published ML Solutions in JSON format.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority('CATALOG_ACCESS')")
+       @PreAuthorize("isActive() && hasAuthority('CATALOG_ACCESS')")
        @ApiOperation(value = "Invoked by Peer Acumos to get a list of Solution Revision from the Catalog of the local Acumos Instance .", response = MLPSolutionRevision.class, responseContainer = "List")
-       @RequestMapping(value = { API.Paths.SOLUTION_REVISIONS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @RequestMapping(value = API.Paths.SOLUTION_REVISIONS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
-       public JsonResponse<List<MLPSolutionRevision>> getSolutionRevisions(HttpServletResponse theHttpResponse,
-                       @PathVariable("solutionId") String theSolutionId) {
+       public JsonResponse<List<MLPSolutionRevision>> getSolutionRevisions(
+           HttpServletResponse theHttpResponse,
+           @PathVariable(API.PathParameters.SOLUTION_ID) String theSolutionId) {
                JsonResponse<List<MLPSolutionRevision>> response = null;
                List<MLPSolutionRevision> solutionRevisions = null;
                log.debug(API.Paths.SOLUTION_REVISIONS);
                try {
-                       solutionRevisions = catalogService.getSolutionRevisions(theSolutionId, new ControllerContext());
+                       if (catalogService.isSolutionAllowed(theSolutionId, new ControllerContext())) {
+                               solutionRevisions = catalogService.getRevisions(theSolutionId, new ControllerContext());
+                       }
                        if (null == solutionRevisions) {
                                response = JsonResponse.<List<MLPSolutionRevision>> buildResponse()
-                                                                                                                       .withMessage("No solution with id " + theSolutionId + " is available.")
-                                                                                                                       .build();
+                                   .withMessage("No solution with id " + theSolutionId + " is available.")
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        }
                        else {
                                response = JsonResponse.<List<MLPSolutionRevision>> buildResponse()
-                                                                                                                       .withMessage("solution revisions")
-                                                                                                                       .withContent(solutionRevisions)
-                                                                                                                       .build();
+                                   .withMessage("solution revisions")
+                                   .withContent(solutionRevisions)
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_OK);
                                log.debug("getSolutionsRevisions for solution {} provided {} revisions",
-                                               theSolutionId, solutionRevisions.size());
+                                   theSolutionId, solutionRevisions.size());
                        }
                }
                catch (Exception x) {
                        response = JsonResponse.<List<MLPSolutionRevision>> buildErrorResponse()
-                                                                                                                .withError(x)
-                                                                                                                .build();
+                           .withError(x)
+                           .build();
                        theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        log.error("An error occured while fetching solution " + theSolutionId + " revisions", x);
                }
@@ -244,59 +260,70 @@ public class CatalogController extends AbstractController {
        }
 
        /**
-        * 
+        * Get details of the specified revision, including the list of artifacts.
+        * If the catalogID is specified, also return the list of documents and the description.
         * @param theHttpRequest Request
+        * @param theHttpResponse
+        *            HttpServletResponse
         * @param theSolutionId
         *            Solution ID
         * @param theRevisionId
         *            Revision ID
-        * @param theHttpResponse
-        *            HttpServletResponse
-        * @return List of Published ML Solutions in JSON format.
+        * @param theCatalogId
+        *            Catalog ID
+        * @return List of MLSolutionRevisions in JSON format.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority('CATALOG_ACCESS')")
+       @PreAuthorize("isActive() && hasAuthority('CATALOG_ACCESS')")
        @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)
+       @RequestMapping(value = API.Paths.SOLUTION_REVISION_DETAILS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
        public JsonResponse<MLPSolutionRevision> getSolutionRevisionDetails(
-                       HttpServletRequest theHttpRequest, HttpServletResponse theHttpResponse,
-                       @PathVariable("solutionId") String theSolutionId, @PathVariable("revisionId") String theRevisionId) {
+           HttpServletRequest theHttpRequest,
+           HttpServletResponse theHttpResponse,
+           @PathVariable(API.PathParameters.SOLUTION_ID) String theSolutionId,
+           @PathVariable(API.PathParameters.REVISION_ID) String theRevisionId,
+           @RequestParam(value=API.QueryParameters.CATALOG_ID, required = false) String theCatalogId) {
                ControllerContext context = new ControllerContext();
                JsonResponse<MLPSolutionRevision> response = null;
                SolutionRevision solutionRevision = null;
-               log.debug(API.Paths.SOLUTION_REVISION_DETAILS + "(" + theSolutionId + "," + theRevisionId + ")");
+               log.debug("{}({},{})", API.Paths.SOLUTION_REVISION_DETAILS, theSolutionId, theRevisionId);
                try {
-                       solutionRevision = catalogService.getSolutionRevision(theSolutionId, theRevisionId, context);
+                       if (theCatalogId != null && !catalogService.isCatalogAllowed(theCatalogId, context)) {
+                               theCatalogId = null;
+                       }
+                       solutionRevision = catalogService.getRevision(theCatalogId, theSolutionId, theRevisionId, context);
+                       if (solutionRevision != null && !catalogService.isSolutionAllowed(solutionRevision.getSolutionId(), context)) {
+                               solutionRevision = null;
+                       }
                        if (null == solutionRevision) {
                                response = JsonResponse.<MLPSolutionRevision> buildResponse()
-                                                                                                                               .withMessage("No solution revision " + theSolutionId + "/" + theRevisionId + " is available.")
-                                                                                                                               .build();
+                                   .withMessage("No solution revision " + theSolutionId + "/" + theRevisionId + " is available.")
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        }
                        else {
                                for (MLPArtifact artifact : solutionRevision.getArtifacts()) {
                                        if (!context.getPeer().getPeerInfo().isLocal()) {
-                                               encodeArtifact(theSolutionId, theRevisionId, (Artifact)artifact, theHttpRequest);
+                                               encodeArtifact((Artifact)artifact, theHttpRequest);
                                        }
                                }
                                for (MLPDocument document : solutionRevision.getDocuments()) {
                                        if (!context.getPeer().getPeerInfo().isLocal()) {
-                                               encodeDocument(theSolutionId, theRevisionId, (Document)document, theHttpRequest);
+                                               encodeDocument((Document)document, theHttpRequest);
                                        }
                                }
-       
                                response = JsonResponse.<MLPSolutionRevision> buildResponse()
-                                                                                                                               .withMessage("solution revision details")
-                                                                                                                               .withContent(solutionRevision)
-                                                                                                                               .build();
+                                   .withMessage("solution revision details")
+                                   .withContent(solutionRevision)
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_OK);
                        }
                }
                catch (Exception x) {
                        response = JsonResponse.<MLPSolutionRevision> buildErrorResponse()
-                                                                                                                .withError(x)
-                                                                                                                .build();
+                       .withError(x)
+                       .build();
                        theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        log.error("An error occured while fetching solution " + theSolutionId + " revision " + theRevisionId + " details", x);
                }
@@ -304,6 +331,8 @@ public class CatalogController extends AbstractController {
        }
 
        /**
+        * List the artifacts of the specified revision.
+        *
         * @param theHttpRequest
         *            HttpServletRequest
         * @param theHttpResponse
@@ -315,44 +344,47 @@ public class CatalogController extends AbstractController {
         * @return List of solution revision artifacts in JSON format.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority('CATALOG_ACCESS')")
+       @PreAuthorize("isActive() && hasAuthority('CATALOG_ACCESS')")
        @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)
+       @RequestMapping(value = API.Paths.SOLUTION_REVISION_ARTIFACTS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
        public JsonResponse<List<MLPArtifact>> getSolutionRevisionArtifacts(
-                       HttpServletRequest theHttpRequest, HttpServletResponse theHttpResponse,
-                       @PathVariable("solutionId") String theSolutionId,       @PathVariable("revisionId") String theRevisionId) {
+           HttpServletRequest theHttpRequest,
+           HttpServletResponse theHttpResponse,
+           @PathVariable(API.PathParameters.SOLUTION_ID) String theSolutionId,
+           @PathVariable(API.PathParameters.REVISION_ID) String theRevisionId) {
                JsonResponse<List<MLPArtifact>> response = null;
                List<MLPArtifact> solutionRevisionArtifacts = null;
                ControllerContext context = new ControllerContext();
-               log.debug(API.Paths.SOLUTION_REVISION_ARTIFACTS + "(" + theSolutionId + "," + theRevisionId + ")");
+               log.debug("{}({}, {})", API.Paths.SOLUTION_REVISION_ARTIFACTS, theSolutionId, theRevisionId);
                try {
-                       solutionRevisionArtifacts = catalogService.getSolutionRevisionArtifacts(theSolutionId, theRevisionId, context);
+                       if (catalogService.isRevisionAllowed(theRevisionId, context)) {
+                               solutionRevisionArtifacts = catalogService.getArtifacts(theSolutionId, theRevisionId, context);
+                       }
                        if (null == solutionRevisionArtifacts) {
                                response = JsonResponse.<List<MLPArtifact>> buildResponse()
-                                                                                                                               .withMessage("No solution revision " + theSolutionId + "/" + theRevisionId + " is available.")
-                                                                                                                               .build();
+                                   .withMessage("No solution revision " + theSolutionId + "/" + theRevisionId + " is available.")
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        }
                        else {
                                for (MLPArtifact artifact : solutionRevisionArtifacts) {
                                        if (!context.getPeer().getPeerInfo().isLocal()) {
-                                               encodeArtifact(theSolutionId, theRevisionId, (Artifact)artifact, theHttpRequest);
+                                               encodeArtifact((Artifact)artifact, theHttpRequest);
                                        }
                                }
                                response = JsonResponse.<List<MLPArtifact>> buildResponse()
-                                                                                                               .withMessage("solution revision artifacts")
-                                                                                                               .withContent(solutionRevisionArtifacts)
-                                                                                                               .build();
+                                   .withMessage("solution revision artifacts")
+                                   .withContent(solutionRevisionArtifacts)
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                               log.debug("getSolutionRevisionArtifacts provided {} artifacts",
-                                                       solutionRevisionArtifacts.size());
+                               log.debug("getSolutionRevisionArtifacts provided {} artifacts", solutionRevisionArtifacts.size());
                        }
                } 
                catch (Exception x) {
                        response = JsonResponse.<List<MLPArtifact>> buildErrorResponse()
-                                                                                                                .withError(x)
-                                                                                                                .build();
+                           .withError(x)
+                           .build();
                        theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                        log.error("An error occured while fetching solution " + theSolutionId + " revision " + theRevisionId + " artifacts", x);
                }
@@ -360,95 +392,100 @@ public class CatalogController extends AbstractController {
        }
 
        /**
+        * List the documents in the specified catalog for the revision.
+        *
         * @param theHttpRequest
         *            HttpServletRequest
         * @param theHttpResponse
         *            HttpServletResponse
-        * @param theSolutionId
-        *            Solution ID
         * @param theRevisionId
         *            Revision ID
+        * @param theCatalogId
+        *            Catalog ID
         * @return List of solution revision documents in JSON format.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority('CATALOG_ACCESS')")
+       @PreAuthorize("isActive() && hasAuthority('CATALOG_ACCESS')")
        @ApiOperation(value = "Invoked by Peer Acumos to get a list of solution revision public documents from the local Acumos Instance .", response = MLPArtifact.class, responseContainer = "List")
-       @RequestMapping(value = { API.Paths.SOLUTION_REVISION_DOCUMENTS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @RequestMapping(value = API.Paths.SOLUTION_REVISION_DOCUMENTS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
        public JsonResponse<List<MLPDocument>> getSolutionRevisionDocuments(
-                       HttpServletRequest theHttpRequest, HttpServletResponse theHttpResponse,
-                       @PathVariable("solutionId") String theSolutionId,       @PathVariable("revisionId") String theRevisionId) {
+           HttpServletRequest theHttpRequest,
+           HttpServletResponse theHttpResponse,
+           @PathVariable(API.PathParameters.REVISION_ID) String theRevisionId,
+           @RequestParam(value=API.QueryParameters.CATALOG_ID, required = true) String theCatalogId) {
                JsonResponse<List<MLPDocument>> response = null;
                List<MLPDocument> solutionRevisionDocuments = null;
                ControllerContext context = new ControllerContext();
-               log.debug(API.Paths.SOLUTION_REVISION_DOCUMENTS + "(" + theSolutionId + "," + theRevisionId + ")");
+               log.debug("{}({})", API.Paths.SOLUTION_REVISION_DOCUMENTS, theRevisionId);
                try {
-                       solutionRevisionDocuments = catalogService.getSolutionRevisionDocuments(theSolutionId, theRevisionId, context);
+                       if (catalogService.isCatalogAllowed(theCatalogId, context)) {
+                               solutionRevisionDocuments = catalogService.getDocuments(theCatalogId, theRevisionId, context);
+                       }
                        if (null == solutionRevisionDocuments) {
                                response = JsonResponse.<List<MLPDocument>> buildResponse()
-                                                                                                                               .withMessage("No solution revision " + theSolutionId + "/" + theRevisionId + " is available.")
-                                                                                                                               .build();
+                                   .withMessage("No documents for " + theRevisionId + " are available.")
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        }
                        else {
                                for (MLPDocument document : solutionRevisionDocuments) {
                                        if (!context.getPeer().getPeerInfo().isLocal()) {
-                                               encodeDocument(theSolutionId, theRevisionId, (Document)document, theHttpRequest);
+                                               encodeDocument((Document)document, theHttpRequest);
                                        }
                                }
                                response = JsonResponse.<List<MLPDocument>> buildResponse()
-                                                                                                               .withMessage("solution revision documents")
-                                                                                                               .withContent(solutionRevisionDocuments)
-                                                                                                               .build();
+                                   .withMessage("solution revision documents")
+                                   .withContent(solutionRevisionDocuments)
+                                   .build();
                                theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-                               log.debug("getSolutionRevisionDocuments provided {} documents",
-                                                       solutionRevisionDocuments.size());
+                               log.debug("getSolutionRevisionDocuments provided {} documents", solutionRevisionDocuments.size());
                        }
                } 
                catch (Exception x) {
                        response = JsonResponse.<List<MLPDocument>> buildErrorResponse()
-                                                                                                                .withError(x)
-                                                                                                                .build();
+                           .withError(x)
+                           .build();
                        theHttpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-                       log.error("An error occured while fetching solution " + theSolutionId + " revision " + theRevisionId + " documents", x);
+                       log.error("An error occured while fetching revision " + theRevisionId + " documents", x);
                }
                return response;
        }
 
 
        /**
+        * Get the content of the specified artifact.
+        *
         * @param theHttpRequest
         *            HttpServletRequest
         * @param theHttpResponse
         *            HttpServletResponse
-        * @param theSolutionId
-        *            Solution ID
-        * @param theRevisionId
-        *            Revision ID
         * @param theArtifactId
         *            Artifact ID
         * @return Archive file of the Artifact for the Solution.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority('CATALOG_ACCESS')")
+       @PreAuthorize("isActive() && hasAuthority('CATALOG_ACCESS')")
        @ApiOperation(value = "API to download artifact content", response = Resource.class, code = 200)
-       @RequestMapping(value = { API.Paths.ARTIFACT_CONTENT }, method = RequestMethod.GET, produces = APPLICATION_OCTET_STREAM)
+       @RequestMapping(value = API.Paths.ARTIFACT_CONTENT, method = RequestMethod.GET, produces = APPLICATION_OCTET_STREAM)
        @ResponseBody
-       public Callable<Resource> getArtifactContent(HttpServletRequest theHttpRequest,
-                       HttpServletResponse theHttpResponse, @PathVariable("solutionId") String theSolutionId,
-                       @PathVariable("revisionId") String theRevisionId, @PathVariable("artifactId") String theArtifactId) {
+       public Callable<Resource> getArtifactContent(
+           HttpServletRequest theHttpRequest,
+           HttpServletResponse theHttpResponse,
+           @PathVariable(API.PathParameters.ARTIFACT_ID) String theArtifactId) {
                        
                theHttpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
                theHttpResponse.setHeader("Pragma", "no-cache");
                theHttpResponse.setHeader("Expires", "0");
                theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-
                final ControllerContext ctx = new ControllerContext();
+               if (!catalogService.isArtifactAllowed(theArtifactId, ctx)) {
+                       return () -> null;
+               }
                return new Callable<Resource>() {
                        public Resource call() throws Exception {
                                try {   
-                                       return contentService.getArtifactContent(
-                                               theSolutionId, theRevisionId, catalogService.getSolutionRevisionArtifact(theArtifactId, ctx), ctx);
+                                       return contentService.getArtifactContent(catalogService.getArtifact(theArtifactId, ctx), ctx);
                                } 
                                catch (Exception x) {
                                        log.error("An error occurred while retrieving artifact content " + theArtifactId, x);
@@ -459,38 +496,37 @@ public class CatalogController extends AbstractController {
        }
 
        /**
+        * Get the body of the specified document.
+        *
         * @param theHttpRequest
         *            HttpServletRequest
         * @param theHttpResponse
         *            HttpServletResponse
-        * @param theSolutionId
-        *            Solution ID
-        * @param theRevisionId
-        *            Revision ID
         * @param theDocumentId
         *            Document ID
         * @return Archive file of the Artifact for the Solution.
         */
        @CrossOrigin
-       @PreAuthorize("isActive && hasAuthority('CATALOG_ACCESS')")
+       @PreAuthorize("isActive() && hasAuthority('CATALOG_ACCESS')")
        @ApiOperation(value = "API to download a documents' content", response = Resource.class, code = 200)
-       @RequestMapping(value = { API.Paths.DOCUMENT_CONTENT }, method = RequestMethod.GET, produces = APPLICATION_OCTET_STREAM)
+       @RequestMapping(value = API.Paths.DOCUMENT_CONTENT, method = RequestMethod.GET, produces = APPLICATION_OCTET_STREAM)
        @ResponseBody
-       public Callable<Resource> getDocumentContent(HttpServletRequest theHttpRequest,
-                       HttpServletResponse theHttpResponse, @PathVariable("solutionId") String theSolutionId,
-                       @PathVariable("revisionId") String theRevisionId, @PathVariable("documentId") String theDocumentId) {
-                       
+       public Callable<Resource> getDocumentContent(
+           HttpServletRequest theHttpRequest,
+           HttpServletResponse theHttpResponse,
+           @PathVariable(API.PathParameters.DOCUMENT_ID) String theDocumentId) {
                theHttpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
                theHttpResponse.setHeader("Pragma", "no-cache");
                theHttpResponse.setHeader("Expires", "0");
                theHttpResponse.setStatus(HttpServletResponse.SC_OK);
-
                final ControllerContext ctx = new ControllerContext();
+               if (!catalogService.isDocumentAllowed(theDocumentId, ctx)) {
+                       return () -> null;
+               }
                return new Callable<Resource>() {
                        public Resource call() throws Exception {
                                try {   
-                                       return contentService.getDocumentContent(
-                                                                       theSolutionId, theRevisionId, catalogService.getSolutionRevisionDocument(theDocumentId, ctx), ctx);
+                                       return contentService.getDocumentContent(catalogService.getDocument(theDocumentId, ctx), ctx);
                                } 
                                catch (Exception x) {
                                        log.error("An error occurred while retrieving artifact content " + theDocumentId, x);
@@ -500,40 +536,29 @@ public class CatalogController extends AbstractController {
                };
        }
 
-       /** */
        private void encodeSolution(MLPSolution theSolution, HttpServletRequest theRequest) throws URISyntaxException {
                //encode the 'origin'
                if (null == theSolution.getOrigin()) {
                        URI requestUri = new URI(theRequest.getRequestURL().toString());
-                       URI solutionUri = API.SOLUTION_DETAIL
-                                                                                               .buildUri(
-                                                                                                       new URI(requestUri.getScheme(), null, requestUri.getHost(),
-                                                                                                                                       requestUri.getPort(), null, null, null).toString(),
-                                                                                                       theSolution.getSolutionId());
+                       URI solutionUri = API.SOLUTION_DETAIL.buildUri(
+                           new URI(requestUri.getScheme(), null, requestUri.getHost(), requestUri.getPort(), null, null, null).toString(),
+                           theSolution.getSolutionId());
                        theSolution.setOrigin(solutionUri.toString());  
                }
        }
        
-       /** */
-       private void encodeArtifact(String theSolutionId, String theRevisionId, Artifact theArtifact, HttpServletRequest theRequest)
-                                                                                                                                                                                                                                                                                                               throws URISyntaxException {
+       private void encodeArtifact(Artifact theArtifact, HttpServletRequest theRequest) throws URISyntaxException {
                String artifactUri = theArtifact.getUri();
-
                //remember the artifact filename before redirecting
                theArtifact.setFilename(theArtifact.getCanonicalFilename());
-
                //redirect              
-               {
-                       URI requestUri = new URI(theRequest.getRequestURL().toString());
-                       URI redirectUri = API.ARTIFACT_CONTENT
-                                                                                               .buildUri(
-                                                                                                       new URI(requestUri.getScheme(), null, requestUri.getHost(),
-                                                                                                                                       requestUri.getPort(), null, null, null).toString(),
-                                                                                                       theSolutionId, theRevisionId, theArtifact.getArtifactId());
-                       log.debug("encodeArtifact: redirected artifact uri " + redirectUri);
-                       theArtifact.setUri(redirectUri.toString());
-               }
-               
+               URI requestUri = new URI(theRequest.getRequestURL().toString());
+               URI redirectUri = API.ARTIFACT_CONTENT
+                   .buildUri(
+                       new URI(requestUri.getScheme(), null, requestUri.getHost(), requestUri.getPort(), null, null, null).toString(),
+                       theArtifact.getArtifactId());
+               log.debug("encodeArtifact: redirected artifact uri {}", redirectUri);
+               theArtifact.setUri(redirectUri.toString());
                if (ArtifactTypes.DockerImage.getCode().equals(theArtifact.getArtifactTypeCode())) {
                        if (artifactUri != null) {
                                //ugly but avoids parsing the manifest on the receiving side
@@ -543,25 +568,16 @@ public class CatalogController extends AbstractController {
                }
        }
        
-       /** */
-       private void encodeDocument(String theSolutionId, String theRevisionId, Document theDocument, HttpServletRequest theRequest)
-                                                                                                                                                                                                                                                                                                                       throws URISyntaxException {
-               String artifactUri = theDocument.getUri();
-
+       private void encodeDocument(Document theDocument, HttpServletRequest theRequest) throws URISyntaxException {
                //remember the document filename before redirecting
                theDocument.setFilename(theDocument.getCanonicalFilename());
-
                //redirect              
-               {
-                       URI requestUri = new URI(theRequest.getRequestURL().toString());
-                       URI redirectUri = API.DOCUMENT_CONTENT
-                                                                                               .buildUri(
-                                                                                                       new URI(requestUri.getScheme(), null, requestUri.getHost(),
-                                                                                                                                       requestUri.getPort(), null, null, null).toString(),
-                                                                                                       theSolutionId, theRevisionId, theDocument.getDocumentId());
-                       log.debug("encodeDocument: redirected document uri " + redirectUri);
-                       theDocument.setUri(redirectUri.toString());
-               }
+               URI requestUri = new URI(theRequest.getRequestURL().toString());
+               URI redirectUri = API.DOCUMENT_CONTENT
+                   .buildUri(
+                       new URI(requestUri.getScheme(), null, requestUri.getHost(), requestUri.getPort(), null, null, null).toString(),
+                                                                                                       theDocument.getDocumentId());
+               log.debug("encodeDocument: redirected document uri {}", redirectUri);
+               theDocument.setUri(redirectUri.toString());
        }
-
 }
index ee98933..b705982 100644 (file)
@@ -36,7 +36,7 @@ public class ControllerContext implements ServiceContext {
        private ThreadLocal<Map<String, Object>> attributes =
                new ThreadLocal<Map<String, Object>>() {
                        public Map<String, Object> initialValue() {
-                               return new HashMap<String, Object>();
+                               return new HashMap<>();
                        }
                };                                                                                                                                                              
 
index de3a17f..f2c12f8 100644 (file)
@@ -26,16 +26,13 @@ import java.util.List;
 import javax.servlet.http.HttpServletResponse;
 
 import org.acumos.cds.domain.MLPCatalog;
-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.JsonResponse;
-import org.acumos.federation.gateway.util.Utils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.access.prepost.PreAuthorize;
 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;
@@ -53,11 +50,10 @@ import io.swagger.annotations.ApiOperation;
 @Controller
 @RequestMapping(API.Roots.LOCAL)
 public class PeerCatalogController extends AbstractController {
-
        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
        /**
-        * Provides access 
+        * List peer's visible catalogs
         * @param theHttpResponse
         *            HttpServletResponse
         * @param thePeerId Peer ID
@@ -66,47 +62,58 @@ public class PeerCatalogController extends AbstractController {
        @CrossOrigin
        @PreAuthorize("hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).PEER_ACCESS)")
        @ApiOperation(value = "Invoked by local Acumos to get a list of catalogs available from a peer Acumos instance .", response = MLPCatalog.class, responseContainer = "List")
-       @RequestMapping(value = { API.Paths.CATALOGS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
+       @RequestMapping(value = API.Paths.CATALOGS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
        public JsonResponse<List<MLPCatalog>> getCatalogs(
            HttpServletResponse theHttpResponse,
-           @PathVariable("peerId") String thePeerId) {
-               log.debug(API.Roots.LOCAL + "" + API.Paths.CATALOGS);
+           @PathVariable(API.PathParameters.PEER_ID) String thePeerId) {
+               log.debug("{}{}", API.Roots.LOCAL, API.Paths.CATALOGS);
                return callPeer("getCatalogs", theHttpResponse, thePeerId, peer -> peer.getCatalogs());
        }
 
        /**
-        * Provides access 
+        * List solutions in peer's catalog
         * @param theHttpResponse
         *            HttpServletResponse
-        * @param thePeerId Peer ID
-        * @param theSelector
-        *            Solutions selector
+        * @param thePeerId
+        *            Peer ID
+        * @param theCatalogId
+        *            Catalog ID
         * @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)
+       @RequestMapping(value = API.Paths.SOLUTIONS, method = RequestMethod.GET, produces = APPLICATION_JSON)
        @ResponseBody
        public JsonResponse<List<MLPSolution>> getSolutions(
            HttpServletResponse theHttpResponse,
-           @PathVariable("peerId") String thePeerId,
-           @RequestParam(value = API.QueryParameters.SOLUTIONS_SELECTOR, required = false) String theSelector) {
-               log.debug(API.Roots.LOCAL + "" + API.Paths.SOLUTIONS);
-               return callPeer("getSolutions", theHttpResponse, thePeerId, peer -> peer.getSolutions(theSelector == null? null: Utils.jsonStringToMap(new String(Base64Utils.decodeFromString(theSelector), "UTF-8"))));
+           @PathVariable(API.PathParameters.PEER_ID) String thePeerId,
+           @RequestParam(value = API.QueryParameters.CATALOG_ID, required = true) String theCatalogId) {
+               log.debug("{}{}", API.Roots.LOCAL, API.Paths.SOLUTIONS);
+               return callPeer("getSolutions", theHttpResponse, thePeerId, peer -> peer.getSolutions(theCatalogId));
        }
 
+       /**
+        * Retrieve solution from peer
+        * @param theHttpResponse
+        *            HttpServletResponse
+        * @param thePeerId
+        *            Peer ID
+        * @param theSolutionId
+        *            Solution ID
+        * @return Published ML Solution in JSON format.
+        */
        @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)
+       @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(API.Roots.LOCAL + "" + API.Paths.SOLUTION_DETAILS);
+           @PathVariable(API.PathParameters.PEER_ID) String thePeerId,
+           @PathVariable(API.PathParameters.SOLUTION_ID) String theSolutionId) {
+               log.debug("{}{}", API.Roots.LOCAL, API.Paths.SOLUTION_DETAILS);
                return callPeer("getSolution", theHttpResponse, thePeerId, peer -> peer.getSolution(theSolutionId));
        }
 }
index 75bd7a2..592b295 100644 (file)
@@ -62,7 +62,7 @@ public class PeerPeersController extends AbstractController {
            HttpServletResponse theHttpResponse,
            @PathVariable("peerId") String thePeerId) {
 
-               log.debug(API.Roots.LOCAL + "" + API.Paths.PEERS);
+               log.debug("{}{}", API.Roots.LOCAL, API.Paths.PEERS);
                return callPeer("getPeers", theHttpResponse, thePeerId, peer -> peer.getPeers());
        }
 
index c66cd09..bff75dd 100644 (file)
@@ -60,7 +60,7 @@ public class PeerPingController extends AbstractController {
        public JsonResponse<MLPPeer> ping(
            HttpServletResponse theHttpResponse,
            @PathVariable("peerId") String thePeerId) {
-               log.debug(API.Roots.LOCAL + "" + API.Paths.PING);
+               log.debug("{}{}", API.Roots.LOCAL, API.Paths.PING);
                return callPeer("ping", theHttpResponse, thePeerId, peer -> peer.ping());
        }
 }
index ebd2124..92a71f0 100644 (file)
@@ -60,7 +60,7 @@ public class PeerRegistrationController extends AbstractController {
        public JsonResponse<MLPPeer> register(
            HttpServletResponse theHttpResponse,
            @PathVariable("peerId") String thePeerId) {
-               log.debug(API.Roots.LOCAL + "" + API.Paths.PEER_REGISTER);
+               log.debug("{}{}", API.Roots.LOCAL, API.Paths.PEER_REGISTER);
                return callPeer("getPeers", theHttpResponse, thePeerId, peer -> peer.register(peerService.getSelf()) );
        }
 }
index 5dee074..65a7c89 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -28,7 +28,6 @@ import org.acumos.cds.domain.MLPPeer;
 import org.acumos.federation.gateway.cds.PeerSubscription;
 import org.acumos.federation.gateway.common.API;
 import org.acumos.federation.gateway.common.JsonResponse;
-import org.acumos.federation.gateway.service.PeerService;
 import org.acumos.federation.gateway.service.PeerSubscriptionService;
 import org.acumos.federation.gateway.task.PeerSubscriptionTaskScheduler;
 import org.slf4j.Logger;
@@ -54,8 +53,6 @@ public class PeerSubscriptionController extends AbstractController {
  
        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-       @Autowired
-       private PeerService peerService;
        @Autowired
        private PeerSubscriptionService peerSubscriptionService;
        @Autowired
@@ -73,15 +70,13 @@ public class PeerSubscriptionController extends AbstractController {
                        @PathVariable("peerId") String thePeerId,
                        @PathVariable("subscriptionId") Long theSubscriptionId) {
 
-               log.debug(API.Roots.LOCAL + "" + API.Paths.SUBSCRIPTION);
+               log.debug("{}{}", API.Roots.LOCAL, API.Paths.SUBSCRIPTION);
                JsonResponse<String> response = null;
                try {
                        log.debug("trigger");
        
                        MLPPeer peer = this.peerService.getPeerById(thePeerId);
                        PeerSubscription subscription = this.peerSubscriptionService.getPeerSubscription(theSubscriptionId);
-                       //coherence check
-                       //subscription.getPeerId().equals(thePeerId);
 
                        ((PeerSubscriptionTaskScheduler)this.appCtx.getBean("peerSubscriptionTaskScheduler")).runOnce(peer, subscription);
 
index 8401ed1..9aac127 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -28,10 +28,8 @@ import javax.servlet.http.HttpServletResponse;
 import org.acumos.cds.domain.MLPPeer;
 import org.acumos.federation.gateway.common.API;
 import org.acumos.federation.gateway.common.JsonResponse;
-import org.acumos.federation.gateway.service.PeerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.CrossOrigin;
@@ -47,9 +45,6 @@ public class PeersController extends AbstractController {
 
        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-       @Autowired
-       PeerService peerService;
-
        /**
         * Basic built-in 'discovery' service.
         * @param theHttpResponse
index 951f57d..6c5ec66 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -27,10 +27,8 @@ import javax.servlet.http.HttpServletResponse;
 import org.acumos.cds.domain.MLPPeer;
 import org.acumos.federation.gateway.common.API;
 import org.acumos.federation.gateway.common.JsonResponse;
-import org.acumos.federation.gateway.service.PeerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.CrossOrigin;
@@ -46,9 +44,6 @@ public class PingController extends AbstractController {
 
        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-       @Autowired
-       private PeerService peerService;
-
        /**
         * Ping service.
         * @param theHttpResponse
@@ -56,7 +51,7 @@ public class PingController extends AbstractController {
         * @return List of Published ML Solutions in JSON format.
         */
        @CrossOrigin
-       @PreAuthorize("isActive")
+       @PreAuthorize("isActive()")
        @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
@@ -64,7 +59,7 @@ public class PingController extends AbstractController {
                        /* HttpServletRequest theHttpRequest, */
                        HttpServletResponse theHttpResponse) {
 
-               JsonResponse<MLPPeer> response = new JsonResponse<MLPPeer>();
+               JsonResponse<MLPPeer> response = new JsonResponse<>();
                log.debug(API.Paths.PING);
                try {
                        MLPPeer self = peerService.getSelf();
index 0335ac9..3f58f2a 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -27,11 +27,9 @@ import javax.servlet.http.HttpServletResponse;
 import org.acumos.cds.domain.MLPPeer;
 import org.acumos.federation.gateway.common.API;
 import org.acumos.federation.gateway.common.JsonResponse;
-import org.acumos.federation.gateway.service.PeerService;
 import org.acumos.federation.gateway.service.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.CrossOrigin;
@@ -50,9 +48,6 @@ public class RegistrationController extends AbstractController {
 
        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-       @Autowired
-       private PeerService peerService;
-
        /**
         * @param theHttpResponse
         *            HttpServletResponse
@@ -80,7 +75,7 @@ public class RegistrationController extends AbstractController {
                                                                        .build();
                                                                        
                        theHttpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
-                       log.debug("peer registration request " + peer + " was accepted");
+                       log.debug("peer registration request {} was accepted", peer);
                }
                catch (ServiceException sx) {
                        response = JsonResponse.<MLPPeer> buildErrorResponse()
@@ -100,7 +95,7 @@ public class RegistrationController extends AbstractController {
        }
 
        @CrossOrigin
-       @PreAuthorize("isKnown && hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).REGISTRATION_ACCESS)")
+       @PreAuthorize("isKnown() && hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).REGISTRATION_ACCESS)")
        @ApiOperation(value = "Invoked by another Acumos Instance to request federation termination.", response = MLPPeer.class)
        @RequestMapping(value = { API.Paths.PEER_UNREGISTER }, method = RequestMethod.POST, produces = APPLICATION_JSON)
        @ResponseBody
@@ -121,7 +116,7 @@ public class RegistrationController extends AbstractController {
                                                                        .build();
                                                                        
                        theHttpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
-                       log.debug("federation termination request from " + peer + " was registered");
+                       log.debug("federation termination request from {} was registered", peer);
                }
                catch (ServiceException sx) {
                        response = JsonResponse.<MLPPeer> buildErrorResponse()
index dd7f48c..b950129 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -72,10 +72,6 @@ public class AuthenticationConfiguration extends WebSecurityConfigurerAdapter {
        public AuthenticationConfiguration() {
        }
 
-       /*
-        * public X509AuthenticationFilter(boolean disableDefaults) {
-        * super(disableDefaults); }
-        */
        /**
         * subjectPrincipalRegex("CN=(.*?)(?:,|$)") :- The regular expression used to
         * extract a username from the client certificates subject name. (CN value of
@@ -108,7 +104,7 @@ public class AuthenticationConfiguration extends WebSecurityConfigurerAdapter {
        @Bean
        public AccessDeniedHandler accessDeniedHandler() {
                return ((request, response, exception) -> {
-                       log.info("accessDeniedHandler : " + exception);
+                       log.info("accessDeniedHandler", exception);
                        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                });
        }
@@ -135,9 +131,12 @@ public class AuthenticationConfiguration extends WebSecurityConfigurerAdapter {
                                return new Peer(new MLPPeer(), Role.ANY);
                        }
 
-                       String cn = null,
-                                                email = null,
-                                                ou = null, o = null, st = null, c = null;
+                       String cn = null;
+                       String email = null;
+                       String ou = null;
+                       String o = null;
+                       String st = null;
+                       String c = null;
                        for (Rdn rdn :  x500subject.getRdns()) {
                                if ("CN".equalsIgnoreCase(rdn.getType())) {
                                        cn = rdn.getValue().toString();
index 87805c4..d919bd2 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -35,7 +35,6 @@ public class FederationMethodSecurityConfiguration extends GlobalMethodSecurityC
     protected MethodSecurityExpressionHandler createExpressionHandler() {
         FederationMethodSecurityExpressionHandler expressionHandler = 
           new FederationMethodSecurityExpressionHandler();
-        //expressionHandler.setPermissionEvaluator(new FederationPermissionEvaluator());
         return expressionHandler;
     }
 }
index 213472a..0025299 100644 (file)
@@ -35,14 +35,17 @@ public class FederationMethodSecurityExpressionRoot
 
        private Object filterObject;
        private Object returnObject;
-       public  boolean isActive = false;
-       public  boolean isKnown = false;
+       public  boolean isActive() {
+               return ((Peer)getPrincipal()).isActive();
+       }
+
+       public  boolean isKnown() {
+               return ((Peer)getPrincipal()).isKnown();
+       }
  
        public FederationMethodSecurityExpressionRoot(Authentication theAuthentication) {
                super(theAuthentication);
                log.info("built with {}", theAuthentication);
-               this.isKnown = ((Peer) this.getPrincipal()).isKnown();
-               this.isActive = ((Peer) this.getPrincipal()).isActive();        
        }
 
        @Override
index f3af4bd..75f4d45 100644 (file)
@@ -2,7 +2,7 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 2017-2019 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");
@@ -49,7 +49,7 @@ public class Tools {
         * @return a map of requested parts and their values. Only those parts for which an entry was found will be available.