Publish E5 Federation client library 45/4445/6
authorAndrew Gauld <agauld@att.com>
Tue, 21 May 2019 14:58:32 +0000 (14:58 +0000)
committerAndrew Gauld <agauld@att.com>
Fri, 14 Jun 2019 12:35:51 +0000 (12:35 +0000)
Refactor to separate out code to access the public E5 API of the
Federation Gateway.

Change-Id: I74182767a1b987c71fef69294c5f82ec52c8f1cd
Issue-ID: ACUMOS-2760
Signed-off-by: Andrew Gauld <agauld@att.com>
290 files changed:
LICENSE.txt
README.md
acumos-fgw-client-config/.gitignore [new file with mode: 0644]
acumos-fgw-client-config/README.md [new file with mode: 0644]
acumos-fgw-client-config/pom.xml [new file with mode: 0644]
acumos-fgw-client-config/src/license/acumos/header.txt [moved from gateway/src/test/resources/mockPeerDocumentContent.txt with 52% similarity]
acumos-fgw-client-config/src/license/acumos/license.txt [new file with mode: 0644]
acumos-fgw-client-config/src/license/licenses.properties [moved from gateway/src/main/resources/application.properties with 73% similarity]
acumos-fgw-client-config/src/main/lombok/org/acumos/federation/client/config/BasicAuthConfig.java [moved from gateway/src/main/java/org/acumos/federation/gateway/service/ServiceException.java with 66% similarity]
acumos-fgw-client-config/src/main/lombok/org/acumos/federation/client/config/ClientConfig.java [moved from gateway/src/main/java/org/acumos/federation/gateway/service/PeerSubscriptionService.java with 50% similarity]
acumos-fgw-client-config/src/main/lombok/org/acumos/federation/client/config/TlsConfig.java [new file with mode: 0644]
acumos-fgw-client-config/src/main/lombok/org/acumos/federation/client/config/package-info.java [moved from gateway/src/main/java/org/acumos/federation/gateway/service/impl/package-info.java with 83% similarity]
acumos-fgw-client-test/.gitignore [new file with mode: 0644]
acumos-fgw-client-test/README.md [new file with mode: 0644]
acumos-fgw-client-test/pom.xml [new file with mode: 0644]
acumos-fgw-client-test/src/license/acumos/header.txt [new file with mode: 0644]
acumos-fgw-client-test/src/license/acumos/license.txt [new file with mode: 0644]
acumos-fgw-client-test/src/license/licenses.properties [new file with mode: 0644]
acumos-fgw-client-test/src/main/java/org/acumos/federation/client/test/ClientMocking.java [new file with mode: 0644]
acumos-fgw-client-test/src/main/java/org/acumos/federation/client/test/package-info.java [moved from gateway/src/main/java/org/acumos/federation/gateway/util/package-info.java with 83% similarity]
acumos-fgw-client-test/src/main/resources/README [moved from gateway/src/test/resources/mockPeerArtifactContent.txt with 57% similarity]
acumos-fgw-client-test/src/main/resources/acumosTrustStore.jks [moved from gateway/src/test/resources/acumosTrustStore.jks with 100% similarity]
acumos-fgw-client-test/src/main/resources/acumosa.pkcs12 [moved from gateway/src/test/resources/acumosa.pkcs12 with 100% similarity]
acumos-fgw-client-test/src/main/resources/acumosb.pkcs12 [moved from gateway/src/test/resources/acumosb.pkcs12 with 100% similarity]
acumos-fgw-client-test/src/main/resources/acumosc.pkcs12 [moved from gateway/src/test/resources/acumosc.pkcs12 with 100% similarity]
acumos-fgw-client-test/src/test/java/org/acumos/federation/client/test/ClientMockingTest.java [new file with mode: 0644]
acumos-fgw-client/.gitignore [new file with mode: 0644]
acumos-fgw-client/README.md [new file with mode: 0644]
acumos-fgw-client/pom.xml [new file with mode: 0644]
acumos-fgw-client/src/license/acumos/header.txt [new file with mode: 0644]
acumos-fgw-client/src/license/acumos/license.txt [new file with mode: 0644]
acumos-fgw-client/src/license/licenses.properties [new file with mode: 0644]
acumos-fgw-client/src/main/java/org/acumos/federation/client/ClientBase.java [new file with mode: 0644]
acumos-fgw-client/src/main/java/org/acumos/federation/client/FederationClient.java [new file with mode: 0644]
acumos-fgw-client/src/main/java/org/acumos/federation/client/GatewayClient.java [new file with mode: 0644]
acumos-fgw-client/src/main/java/org/acumos/federation/client/TlsConfigException.java [moved from gateway/src/main/java/org/acumos/federation/gateway/service/CodeNamesService.java with 63% similarity]
acumos-fgw-client/src/main/java/org/acumos/federation/client/package-info.java [moved from gateway/src/main/java/org/acumos/federation/gateway/config/package-info.java with 80% similarity]
acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Artifact.java [new file with mode: 0644]
acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Catalog.java [moved from gateway/src/main/java/org/acumos/federation/gateway/cds/Catalog.java with 67% similarity]
acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Document.java [new file with mode: 0644]
acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/JsonResponse.java [moved from gateway/src/main/java/org/acumos/federation/gateway/cds/ArtifactType.java with 59% similarity]
acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Solution.java [moved from gateway/src/main/java/org/acumos/federation/gateway/cds/PeerStatuses.java with 55% similarity]
acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/SolutionRevision.java [new file with mode: 0644]
acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/package-info.java [moved from gateway/src/main/java/org/acumos/federation/gateway/controller/package-info.java with 84% similarity]
acumos-fgw-client/src/test/java/org/acumos/federation/client/ClientDemo.java [new file with mode: 0644]
acumos-fgw-client/src/test/java/org/acumos/federation/client/ClientTest.java [new file with mode: 0644]
docs/client.rst [new file with mode: 0644]
docs/config.rst
docs/design.rst
docs/developer-guide.rst
docs/index.rst
docs/overview.rst
docs/release-notes.rst
gateway/.gitignore [deleted file]
gateway/README.md [new file with mode: 0644]
gateway/acumosa.sh
gateway/application-acumosa.properties
gateway/application-adapter.properties [deleted file]
gateway/application-dev.properties
gateway/application-onap.properties [deleted file]
gateway/pom.xml
gateway/src/license/acumos/header.txt
gateway/src/license/acumos/license.txt
gateway/src/license/licenses.properties
gateway/src/main/java/org/acumos/federation/gateway/Application.java
gateway/src/main/java/org/acumos/federation/gateway/BadRequestException.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/PeerException.java with 57% similarity]
gateway/src/main/java/org/acumos/federation/gateway/CatalogService.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/CatalogServiceImpl.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/Clients.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/ContentService.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/ContentServiceImpl.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/FederationController.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/FederationServer.java [moved from gateway/src/main/java/org/acumos/federation/gateway/config/LoggingConfiguration.java with 53% similarity]
gateway/src/main/java/org/acumos/federation/gateway/GatewayController.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/GatewayServer.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/NexusClient.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/PeerService.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/PeerServiceImpl.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/Security.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/SubscriptionPoller.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/adapter/PeerGateway.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/ONAP.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/ONAPAdapterCondition.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/ONAPAdapterConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/ToscaLab.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/sdc/ASDC.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/adapter/onap/sdc/ASDCException.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/Artifact.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/ArtifactBuilder.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/ArtifactTypes.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/CodeName.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/CodeNames.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/CodeNamesConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/Document.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/DocumentBuilder.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/Mapper.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/PeerSubscription.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/Reference.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/RevCatDescription.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/Solution.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/SolutionBuilder.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/SolutionRevision.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/SolutionRevisionBuilder.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/TimestampedEntity.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/cds/Updater.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/API.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/AbstractClient.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/Clients.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/FederationClient.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/FederationException.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/JsonRequest.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/common/JsonResponse.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/AdapterCondition.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/AdapterConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/CDMSClientConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/DockerConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/FederationConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/FederationInterfaceConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/GatewayCondition.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/GatewayConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/InterfaceConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/InterfaceConfigurationBuilder.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/LocalConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/LocalInterfaceConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/LoggingHandlerInterceptor.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/NexusConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/RegistrationCondition.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/config/SwaggerConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/AbstractController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/CatalogController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/ControllerContext.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerCatalogController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerPeersController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerPingController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerRegistrationController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeerSubscriptionController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/PeersController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/PingController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/controller/RegistrationController.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/event/PeerSubscriptionEvent.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/package-info.java [new file with mode: 0644]
gateway/src/main/java/org/acumos/federation/gateway/security/AuthenticationConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/security/FederationMethodSecurityConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/security/FederationMethodSecurityExpressionHandler.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/security/FederationMethodSecurityExpressionRoot.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/security/Peer.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/security/Priviledge.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/security/Role.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/security/Tools.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/CatalogService.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/CatalogServiceConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/ContentService.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/LocalWatchService.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/PeerService.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/ServiceContext.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/AbstractServiceImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/AbstractServiceLocalImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/CatalogServiceImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/CatalogServiceLocalImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/CodeNamesServiceImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/CodeNamesServiceLocalImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/ContentServiceImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/ContentServiceLocalImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/PeerServiceImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/PeerServiceLocalImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/impl/PeerSubscriptionServiceImpl.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/service/package-info.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/task/PeerSubscriptionTaskScheduler.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/task/TaskConfiguration.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/task/package-info.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/Errors.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/JSONHttpMessageConverter.java [deleted file]
gateway/src/main/java/org/acumos/federation/gateway/util/Utils.java [deleted file]
gateway/src/main/lombok/org/acumos/federation/gateway/DockerConfig.java [new file with mode: 0644]
gateway/src/main/lombok/org/acumos/federation/gateway/FederationConfig.java [new file with mode: 0644]
gateway/src/main/lombok/org/acumos/federation/gateway/NexusConfig.java [moved from gateway/src/main/java/org/acumos/federation/gateway/common/JSONTags.java with 61% similarity]
gateway/src/main/lombok/org/acumos/federation/gateway/ServerConfig.java [new file with mode: 0644]
gateway/src/main/lombok/org/acumos/federation/gateway/ServiceConfig.java [moved from gateway/src/main/java/org/acumos/federation/gateway/cds/PeerStatus.java with 64% similarity]
gateway/src/main/resources/logback.xml
gateway/src/test/java/org/acumos/federation/gateway/ClientsTest.java [new file with mode: 0644]
gateway/src/test/java/org/acumos/federation/gateway/FederationControllerTest.java [new file with mode: 0644]
gateway/src/test/java/org/acumos/federation/gateway/GatewayControllerTest.java [new file with mode: 0644]
gateway/src/test/java/org/acumos/federation/gateway/PollingTest.java [new file with mode: 0644]
gateway/src/test/java/org/acumos/federation/gateway/SimulatedDockerClient.java [new file with mode: 0644]
gateway/src/test/java/org/acumos/federation/gateway/test/AsdcTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/AuthorizationTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/CatalogServiceTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/CdsTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/ContentServiceTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/ControllerTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/LocalControllerTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/LocalTester.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/MockAnswer.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/MockResponse.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/PeerGatewayTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/PeerServiceTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/ServiceTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/TaskTest.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/TestAdapter.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/TestAdapterCondition.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/TestAdapterConfiguration.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/TestTemplates.java [deleted file]
gateway/src/test/java/org/acumos/federation/gateway/test/UtilsTest.java [deleted file]
gateway/src/test/resources/acumosa-catalog.json [deleted file]
gateway/src/test/resources/acumosa-codes.json [deleted file]
gateway/src/test/resources/acumosa-peers.json [deleted file]
gateway/src/test/resources/acumosb-catalog.json [deleted file]
gateway/src/test/resources/acumosb-codes.json [deleted file]
gateway/src/test/resources/acumosb-peers.json [deleted file]
gateway/src/test/resources/application-acumosa.properties [deleted file]
gateway/src/test/resources/application-acumosb.properties [deleted file]
gateway/src/test/resources/application-onap.properties [deleted file]
gateway/src/test/resources/docker-compose-test.yml [deleted file]
gateway/src/test/resources/docker-compose.yml [deleted file]
gateway/src/test/resources/ist-acumosa.pkcs12 [deleted file]
gateway/src/test/resources/ist-acumosb.pkcs12 [deleted file]
gateway/src/test/resources/logback.xml [deleted file]
gateway/src/test/resources/mockCDSAddCatalogSolutionResponse.json [deleted file]
gateway/src/test/resources/mockCDSAllowedResponse.json [deleted file]
gateway/src/test/resources/mockCDSArtifactTypeResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateArtifactResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateCatalogResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateDocumentResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateRevisionArtifactResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateRevisionDescriptionResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateRevisionDocumentResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateSolutionResponse.json [deleted file]
gateway/src/test/resources/mockCDSCreateSolutionRevisionResponse.json [deleted file]
gateway/src/test/resources/mockCDSDateSolutionsResponsePage0.json [deleted file]
gateway/src/test/resources/mockCDSDateSolutionsResponsePage1.json [deleted file]
gateway/src/test/resources/mockCDSErrorResponse.json [deleted file]
gateway/src/test/resources/mockCDSForbiddenResponse.json [deleted file]
gateway/src/test/resources/mockCDSForbiddenSolutionRevisionResponse.json [deleted file]
gateway/src/test/resources/mockCDSNoEntryWithIDResponse.json [deleted file]
gateway/src/test/resources/mockCDSNoSuchSolutionRevisionsResponse.json [deleted file]
gateway/src/test/resources/mockCDSNoSuchThingResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerCreateResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerSearchAllResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerSearchResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerSearchSelfResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerStatusResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerSubscriptionResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerSubscriptionsResponse.json [deleted file]
gateway/src/test/resources/mockCDSPeerUpdateResponse.json [deleted file]
gateway/src/test/resources/mockCDSPortalCatalogsResponse.json [deleted file]
gateway/src/test/resources/mockCDSPortalGetCatalogResponse.json [deleted file]
gateway/src/test/resources/mockCDSPortalNoSolutionsResponse.json [deleted file]
gateway/src/test/resources/mockCDSPortalPeerAccessCatalogIdsResponse.json [deleted file]
gateway/src/test/resources/mockCDSPortalSolutionCountResponse.json [deleted file]
gateway/src/test/resources/mockCDSPortalSolutionsResponse.json [deleted file]
gateway/src/test/resources/mockCDSSearchEmptyResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionPicResponse.tgz [deleted file]
gateway/src/test/resources/mockCDSSolutionResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionRevisionArtifactResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionRevisionArtifactsResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionRevisionDescriptionResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionRevisionDocumentResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionRevisionDocumentsResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionRevisionResponse.json [deleted file]
gateway/src/test/resources/mockCDSSolutionRevisionsResponse.json [deleted file]
gateway/src/test/resources/mockCDSsaveSolutionPicResponse.json [deleted file]
gateway/src/test/resources/mockPeerCatalogsResponse.json [deleted file]
gateway/src/test/resources/mockPeerDownload.tgz [deleted file]
gateway/src/test/resources/mockPeerGWCatalogsResponse.json [deleted file]
gateway/src/test/resources/mockPeerPeersResponse.json [deleted file]
gateway/src/test/resources/mockPeerPingResponse.json [deleted file]
gateway/src/test/resources/mockPeerRegisterResponse.json [deleted file]
gateway/src/test/resources/mockPeerSolutionResponse.json [deleted file]
gateway/src/test/resources/mockPeerSolutionRevisionArtifactsResponse.json [deleted file]
gateway/src/test/resources/mockPeerSolutionRevisionDocumentsResponse.json [deleted file]
gateway/src/test/resources/mockPeerSolutionRevisionResponse.json [deleted file]
gateway/src/test/resources/mockPeerSolutionRevisionsResponse.json [deleted file]
gateway/src/test/resources/mockPeerSolutionsResponse.json [deleted file]
gateway/src/test/resources/mockPeerSubscriptionResponse.json [deleted file]
gateway/src/test/resources/onap-catalog.json [deleted file]
gateway/src/test/resources/onap-peers.json [deleted file]
gateway/src/test/resources/onap.pkcs12 [deleted file]
gateway/src/test/resources/onap/sdc/BytesResponse.tgz [deleted file]
gateway/src/test/resources/onap/sdc/EmptyArrayResponse.json [deleted file]
gateway/src/test/resources/onap/sdc/EmptyObjectResponse.json [deleted file]
gateway/src/test/resources/task-test-catalog.json [deleted file]
gateway/src/test/resources/task-test-peers.json [deleted file]
gateway/src/test/resources/test-catalog.json [deleted file]
gateway/src/test/resources/test-catalogs.json [deleted file]
gateway/src/test/resources/test-codes.json [deleted file]
gateway/src/test/resources/test-peers.json [deleted file]
gateway/toscalab.xml [deleted file]
lombok.config [new file with mode: 0644]
pom.xml

index d2a3575..5c5cfd2 100644 (file)
@@ -2,14 +2,14 @@ ACUMOS
 ================================================================================
 Copyright © 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
 ================================================================================
-This Acumos software file is distributed by AT&T and Tech Mahindra 
+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, 
+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.
index f4504f7..7984aaa 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Acumos Federation
 
-This repository is to support Federation Architecture for the Acumos Platform. 
+This repository supports Federation between Acumos system instances.
 
 Please see the documentation in the "docs" folder.
 
diff --git a/acumos-fgw-client-config/.gitignore b/acumos-fgw-client-config/.gitignore
new file mode 100644 (file)
index 0000000..ae040c7
--- /dev/null
@@ -0,0 +1,10 @@
+.classpath
+.factorypath
+.project
+/.settings/
+/bin/
+/target/
+/logs/
+/debug-logs/
+/.apt_generated/
+/.apt_generated_tests/
diff --git a/acumos-fgw-client-config/README.md b/acumos-fgw-client-config/README.md
new file mode 100644 (file)
index 0000000..18e2ae7
--- /dev/null
@@ -0,0 +1,17 @@
+# Acumos Federation Gateway Client Configuration
+
+This sub-project contains classes for configuring Federation Gateway clients.
+
+Please see the documentation in the parent project's "docs" folder.
+
+## License
+
+Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+Acumos 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.
diff --git a/acumos-fgw-client-config/pom.xml b/acumos-fgw-client-config/pom.xml
new file mode 100644 (file)
index 0000000..4097ecf
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--<![CDATA[
+===============LICENSE_START=======================================================
+Acumos
+===================================================================================
+Copyright (C) 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
+limitations under the License.
+===============LICENSE_END=========================================================
+]]>-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>federation-parent</artifactId>
+               <version>0</version>
+       </parent>
+       <groupId>org.acumos.federation</groupId>
+       <artifactId>acumos-fgw-client-config</artifactId>
+       <version>1.0.0-SNAPSHOT</version>
+       <name>Federation Gateway Client Configuration Types</name>
+       <!-- Dependency/plugin versions are inherited from parent pom -->
+       <dependencies>
+               <dependency>
+                       <groupId>org.projectlombok</groupId>
+                       <artifactId>lombok</artifactId>
+                       <scope>provided</scope>
+               </dependency>
+       </dependencies>
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.projectlombok</groupId>
+                               <artifactId>lombok-maven-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.jacoco</groupId>
+                               <artifactId>jacoco-maven-plugin</artifactId>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
@@ -1,8 +1,3 @@
-===============LICENSE_START=======================================================
-Acumos
-===================================================================================
-Copyright (C) 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.
@@ -14,5 +9,3 @@ 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=========================================================
-Mock Content of a Document
diff --git a/acumos-fgw-client-config/src/license/acumos/license.txt b/acumos-fgw-client-config/src/license/acumos/license.txt
new file mode 100644 (file)
index 0000000..d901067
--- /dev/null
@@ -0,0 +1,11 @@
+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.
@@ -2,22 +2,20 @@
 # ===============LICENSE_START=======================================================
 # Acumos
 # ===================================================================================
-# Copyright (C) 2017-2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+# 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=========================================================
 ###
-# Federation-Gateway requires this to manage Spring security
-spring.main.allow-bean-definition-overriding=true
-# Allow time for the docker pull when retrieving docker image artifacts
-spring.mvc.async.request-timeout=10m
+
+acumos=acumos
@@ -2,38 +2,43 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
+package org.acumos.federation.client.config;
 
-package org.acumos.federation.gateway.service;
+import lombok.Data;
 
 /**
- *
+ * Configuration for basic authentication credentials.
  */
-public class ServiceException extends Exception {
-
-       public ServiceException(String theMessage, Throwable theCause) {
-               super(theMessage, theCause);
-       }
-
-       public ServiceException(Throwable theCause) {
-               super("", theCause);
-       }
 
-       public ServiceException(String theMessage) {
-               super(theMessage);
-       }
+@Data
+public class BasicAuthConfig {
+       /**
+        * The user name
+        *
+        * @param username The name of the user.
+        * @return The name of the user.
+        */
+       private String username;
+       /**
+        * The password
+        *
+        * @param password The password.
+        * @return The password.
+        */
+       private String password;
 }
@@ -2,54 +2,49 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
+package org.acumos.federation.client.config;
 
-package org.acumos.federation.gateway.service;
-
-import java.util.List;
-
-import org.acumos.cds.domain.MLPPeerSubscription;
-import org.acumos.federation.gateway.cds.PeerSubscription;
+import lombok.Data;
 
 /**
- * 
+ * Configuration for a client.
  *
+ * Currently, the configuration properties are all related to security and
+ * authentication.  Which, if any, of the properties are required depends on
+ * the particular security mechanisms used by the server the client
+ * is intended to use.  The currently supported mechanisms are login/password
+ * via HTTP(S) Basic Authentication, and HTTPS with and without client
+ * certificates.
  */
-public interface PeerSubscriptionService {
-
+@Data
+public class ClientConfig {
        /**
-        * @param peerId
-        *            Peer ID
-        * @return List of PeerSubscription configured in the Local Acumos Instance
+        * TLS (https) configuration for the client.
+        *
+        * @param ssl TLS configuration for the client.
+        * @return TLS configuration for the client.
         */
-       List<MLPPeerSubscription> getPeerSubscriptions(String peerId);
-
+       private TlsConfig ssl;
        /**
-        * @param subId
-        *            Peer subscription ID
-        * @return Peer Subscription based on the configured Subject Name
+        * Basic authentication credentials for the client.
+        *
+        * @param creds Credentials for the client.
+        * @return Credentials for the client.
         */
-       PeerSubscription getPeerSubscription(Long subId);
-
-       /**
-        * @param mlpPeerSubscription
-        *            MLPPeer Configuration that needs to be updated on the Platform
-        * @throws ServiceException On failure
-        */
-       void updatePeerSubscription(MLPPeerSubscription mlpPeerSubscription) throws ServiceException;
-
+       private BasicAuthConfig creds;
 }
diff --git a/acumos-fgw-client-config/src/main/lombok/org/acumos/federation/client/config/TlsConfig.java b/acumos-fgw-client-config/src/main/lombok/org/acumos/federation/client/config/TlsConfig.java
new file mode 100644 (file)
index 0000000..2c1d30f
--- /dev/null
@@ -0,0 +1,108 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client.config;
+
+import lombok.Data;
+
+/**
+ * Configuration for a TLS (https) client.
+ */
+
+@Data
+public class TlsConfig {
+       /**
+        * Key store location for 2-way authentication.
+        * If null, client side certificates are disabled.
+        *
+        * This value is interpreted by the
+        * {@link org.springframework.core.io.ResourceLoader#getResource(String)}
+        * method of whatever resource loader is specified when the client
+        * is created.  If that method cannot locate it, an attempt is made
+        * to interpret the value as a file name.
+        *
+        * @param keyStore The location.
+        * @return The location.
+        */
+       private String keyStore;
+       /**
+        * The type of the key store (default "JKS").
+        *
+        * This value is interpreted by
+        * {@link java.security.KeyStore#getInstance(String)}.
+        * The most commonly used values are "JKS" and "PKCS12" but
+        * Java security providers can and do handle
+        * many other types of key stores and there is no list of valid
+        * values.
+        *
+        * @param keyStoreType The type.
+        * @return The type.
+        */
+       private String keyStoreType = "JKS";
+       /**
+        * The password for the key store.
+        *
+        * @param keyStorePassword The password.
+        * @return The password.
+        */
+       private String keyStorePassword;
+       /**
+        * The alias of the entry in the key store to use.
+        *
+        * @param keyAlias The alias name.
+        * @return The alias name.
+        */
+       private String keyAlias;
+       /**
+        * Trust store location for validating server certificate.
+        * If null, the default trust store is used.
+        *
+        * This value is interpreted by the
+        * {@link org.springframework.core.io.ResourceLoader#getResource(String)}
+        * method of whatever resource loader is specified when the client
+        * is created.  If that method cannot locate it, an attempt is made
+        * to interpret the value as a file name.
+        *
+        * @param trustStore The location.
+        * @return The location.
+        */
+       private String trustStore;
+       /**
+        * The type of the trust store (default "JKS").
+        *
+        * This value is interpreted by
+        * {@link java.security.KeyStore#getInstance(String)}.
+        * The most commonly used values are "JKS" and "PKCS12" but
+        * Java security providers can and do handle
+        * many other types of key stores and there is no list of valid
+        * values.
+        *
+        * @param trustStoreType The type.
+        * @return The type.
+        */
+       private String trustStoreType = "JKS";
+       /**
+        * The password for the trust store.
+        * If null, the default trust store is used.
+        *
+        * @param trustStorePassword The password.
+        * @return The password.
+        */
+       private String trustStorePassword;
+}
@@ -2,27 +2,23 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-
 /**
- * 
+ * Configuration bean data types for the Acumos Federation Gateway clients.
  */
-/**
- * 
- *
- */
-package org.acumos.federation.gateway.service.impl;
+
+package org.acumos.federation.client.config;
diff --git a/acumos-fgw-client-test/.gitignore b/acumos-fgw-client-test/.gitignore
new file mode 100644 (file)
index 0000000..ae040c7
--- /dev/null
@@ -0,0 +1,10 @@
+.classpath
+.factorypath
+.project
+/.settings/
+/bin/
+/target/
+/logs/
+/debug-logs/
+/.apt_generated/
+/.apt_generated_tests/
diff --git a/acumos-fgw-client-test/README.md b/acumos-fgw-client-test/README.md
new file mode 100644 (file)
index 0000000..9007258
--- /dev/null
@@ -0,0 +1,17 @@
+# Acumos Federation Gateway Client Testing
+
+This sub-project contains classes for testing Federation Gateway clients and applications that use them.
+
+Please see the documentation in the parent project's "docs" folder.
+
+## License
+
+Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+Acumos 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.
diff --git a/acumos-fgw-client-test/pom.xml b/acumos-fgw-client-test/pom.xml
new file mode 100644 (file)
index 0000000..f577bec
--- /dev/null
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!--<![CDATA[
+===============LICENSE_START=======================================================
+Acumos
+===================================================================================
+Copyright (C) 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
+limitations under the License.
+===============LICENSE_END=========================================================
+]]>-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>federation-parent</artifactId>
+               <version>0</version>
+       </parent>
+       <groupId>org.acumos.federation</groupId>
+       <artifactId>acumos-fgw-client-test</artifactId>
+       <version>1.0.0-SNAPSHOT</version>
+       <name>Federation Gateway Client User Test Tools</name>
+       <!-- Dependency/plugin versions are inherited from parent pom -->
+       <dependencies>
+               <dependency>
+                       <groupId>org.acumos.federation</groupId>
+                       <artifactId>acumos-fgw-client-config</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.httpcomponents</groupId>
+                       <artifactId>httpclient</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.mockito</groupId>
+                       <artifactId>mockito-core</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework</groupId>
+                       <artifactId>spring-web</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework</groupId>
+                       <artifactId>spring-core</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework</groupId>
+                       <artifactId>spring-test</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.httpcomponents</groupId>
+                       <artifactId>httpcore</artifactId>
+               </dependency>
+               <!-- Runtime dependencies -->
+               <dependency>
+                       <groupId>ch.qos.logback</groupId>
+                       <artifactId>logback-classic</artifactId>
+                       <scope>runtime</scope>
+               </dependency>
+               <dependency>
+                       <groupId>com.fasterxml.jackson.core</groupId>
+                       <artifactId>jackson-databind</artifactId>
+                       <scope>runtime</scope>
+               </dependency>
+               <!-- Test dependencies -->
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot</artifactId>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.jacoco</groupId>
+                               <artifactId>jacoco-maven-plugin</artifactId>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
diff --git a/acumos-fgw-client-test/src/license/acumos/header.txt b/acumos-fgw-client-test/src/license/acumos/header.txt
new file mode 100644 (file)
index 0000000..d901067
--- /dev/null
@@ -0,0 +1,11 @@
+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.
diff --git a/acumos-fgw-client-test/src/license/acumos/license.txt b/acumos-fgw-client-test/src/license/acumos/license.txt
new file mode 100644 (file)
index 0000000..d901067
--- /dev/null
@@ -0,0 +1,11 @@
+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.
diff --git a/acumos-fgw-client-test/src/license/licenses.properties b/acumos-fgw-client-test/src/license/licenses.properties
new file mode 100644 (file)
index 0000000..71a69a0
--- /dev/null
@@ -0,0 +1,21 @@
+###
+# ===============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=========================================================
+###
+
+acumos=acumos
diff --git a/acumos-fgw-client-test/src/main/java/org/acumos/federation/client/test/ClientMocking.java b/acumos-fgw-client-test/src/main/java/org/acumos/federation/client/test/ClientMocking.java
new file mode 100644 (file)
index 0000000..7778b24
--- /dev/null
@@ -0,0 +1,375 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client.test;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.Base64;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.ArrayList;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.HttpResponse;
+import org.apache.http.message.BasicHttpResponse;
+import org.apache.http.message.BasicStatusLine;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.StatusLine;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.test.util.ReflectionTestUtils;
+import org.springframework.web.client.RestTemplate;
+
+import org.acumos.federation.client.config.ClientConfig;
+import org.acumos.federation.client.config.TlsConfig;
+import org.acumos.federation.client.config.BasicAuthConfig;
+
+/**
+ * Simulate responses from Federation Gateway or other RestTemplate based clients.
+ */
+
+public class ClientMocking implements Answer<HttpResponse> {
+       private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+       /**
+        * Replace single quotes with double quotes.
+        * Makes it easy to write JSON strings.
+        *
+        * @param s String with single quotes.
+        * @return String replacing single quotes with double quotes.
+        */
+       public static String xq(String s) {
+               return s.replaceAll("'", "\"");
+       }
+
+       /**
+        * Create a ClientConfig appropriate for use with the included
+        * test certificate resources.
+        * Name is typically acumosa, acumosb, or acumosc.
+        *
+        * @param name Base name for test certificate resource file.
+        * @return ClientConfig set up for 2-way TLS using test certificate.
+        */
+       public static ClientConfig getConfig(String name) {
+               ClientConfig ret = new ClientConfig();
+               TlsConfig tls = new TlsConfig();
+               tls.setKeyStore("classpath:" + name + ".pkcs12");
+               tls.setKeyStoreType("PKCS12");
+               tls.setKeyStorePassword(name);
+               tls.setTrustStore("classpath:acumosTrustStore.jks");
+               tls.setTrustStorePassword("acumos");
+               ret.setSsl(tls);
+               BasicAuthConfig creds = new BasicAuthConfig();
+               creds.setUsername(name);
+               creds.setPassword(name);
+               ret.setCreds(creds);
+               return ret;
+       }
+
+       private static class BasicCloseableHttpResponse extends BasicHttpResponse implements CloseableHttpResponse {
+               public BasicCloseableHttpResponse(StatusLine line) {
+                       super(line);
+               }
+
+               @Override
+               public void close() throws IOException {
+                       // no op
+               }
+       }
+
+       /**
+        * Information on request being processed
+        */
+       public static class RequestInfo {
+               private HttpUriRequest req;
+               private String line;
+
+               /**
+                * Collect information on a request.
+                * @param req The request to examine.
+                */
+               public RequestInfo(HttpUriRequest req) {
+                       this.req = req;
+                       line = getMethod() + " " + getPath() + (req.getURI().getQuery() == null ? "": ("?" + req.getURI().getQuery()));
+               }
+
+               /**
+                * Get the method.
+                *
+                * @return The HTTP method of the request.
+                */
+               public String getMethod() {
+                       return req.getMethod();
+               }
+
+               /**
+                * Get the method and URI
+                *
+                * @return The method and URI of the request, including any query string.
+                */
+               public String getLine() {
+                       return line;
+               }
+
+               /**
+                * Get the path component of the URI
+                *
+                * @return The URI excluding the query string.
+                */
+               public String getPath() {
+                       return req.getURI().getPath();
+               }
+
+               /**
+                * Check whether the named header is missing.
+                *
+                * @return true if the header is absent.
+                */
+               public boolean lacksHeader(String name) {
+                       return req.getFirstHeader(name) == null;
+               }
+
+               /**
+                * Check whether the header has the specified header value.
+                *
+                * @return true if the header is missing or has the wrong value.
+                */
+               public boolean lacksHeaderValue(String name, String value) {
+                       return req.getFirstHeader(name) == null || !value.equals(req.getFirstHeader(name).getValue());
+               }
+       }
+
+       private static class Response {
+               private Predicate<RequestInfo> matcher;
+               private byte[] body;
+               private Consumer<RequestInfo> action;
+               private int code = 200;
+               private String message = "OK";
+               private ContentType contentType = ContentType.APPLICATION_JSON;
+       }
+
+       private static Predicate<RequestInfo> s2p(String line) {
+               return r -> r.getLine().equals(line);
+       }
+
+       private ArrayList<Response> responses;
+       private HttpClient client;
+
+       /**
+        * Create a responder to handle requests.
+        */
+       public ClientMocking() throws IOException {
+               responses = new ArrayList<>();
+               client = mock(HttpClient.class);
+               when(client.execute(any(HttpUriRequest.class), any(HttpContext.class))).thenAnswer(this);
+       }
+
+       /**
+        * Redirect the template to this responder.
+        *
+        * @param template The RestTemplate to redirect.
+        * @return This responder.
+        */
+       public ClientMocking applyTo(RestTemplate template) {
+               template.setRequestFactory(new HttpComponentsClientHttpRequestFactory(client));
+               return this;
+       }
+
+       /**
+        * Set the identified RestTemplate field to use this responder.
+        *
+        * @param object The object containing the RestTemplate.
+        * @param fieldName The name of the RestTemplate field in the object.
+        * @return This responder.
+        */
+       public ClientMocking applyTo(Object object, String fieldName) {
+               return applyTo((RestTemplate)ReflectionTestUtils.getField(object, fieldName));
+       }
+
+       /**
+        * Set the restTemplate field of an object to use this responder.
+        *
+        * Typically, the object will be a FederationClient or a GatewayClient.
+        * @param object The object with the restTemplate field.
+        * @return This responder.
+        */
+       public ClientMocking applyTo(Object object) {
+               return applyTo(object, "restTemplate");
+       }
+
+       @Override
+       public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
+               RequestInfo info = new RequestInfo((HttpUriRequest)invocation.getArguments()[0]);
+               for (Response r: responses) {
+                       if (r.matcher.test(info)) {
+                               if (r.action != null) {
+                                       r.action.accept(info);
+                               }
+                               BasicCloseableHttpResponse ret = new BasicCloseableHttpResponse(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), r.code, r.message));
+                               if (r.body != null) {
+                                       ret.setEntity(new ByteArrayEntity(r.body, r.contentType));
+                                       ret.addHeader("Content-Length", String.valueOf(r.body.length));
+                                       if (r.body.length != 0) {
+                                               ret.addHeader("Content-Type", r.contentType.toString());
+                                       }
+                               }
+                               if (log.isInfoEnabled()) {
+                                       log.info("Mock client response to {} is {}", info.getLine(), (r.body == null? "null": new String(r.body)));
+                               }
+                               return ret;
+                       }
+               }
+               throw new IOException("Mock unhandled " + info.getLine());
+       }
+
+       /**
+        * Handle the specified requests.
+        *
+        * @param matcher A predicate for matching requests.
+        * @param body The response body to return.
+        * @param type The content type of the body.
+        * @param action An action to perform, whenever the request is handled.
+        * @return This responder.
+        */
+       public ClientMocking on(Predicate<RequestInfo> matcher, byte[] body, ContentType type, Consumer<RequestInfo> action) {
+               Response r = new Response();
+               r.matcher = matcher;
+               r.body = body;
+               r.contentType = type;
+               r.action = action;
+               responses.add(r);
+               return this;
+       }
+
+       /**
+        * Handle the specified request.
+        *
+        * @param line The HTTP method and URI to handle.
+        * @param body The response body to return.
+        * @param type The content type of the body.
+        * @param action An action to perform, whenever the request is handled.
+        * @return This responder.
+        */
+       public ClientMocking on(String line, String body, ContentType type, Consumer<RequestInfo> action) {
+               return on(s2p(line), body.getBytes(), type, action);
+       }
+
+       /**
+        * Handle the specified request.
+        *
+        * @param line The HTTP method and URI to handle.
+        * @param body The response body to return, as a JSON string.
+        * @param action An action to perform, whenever the request is handled.
+        * @return This responder.
+        */
+       public ClientMocking on(String line, String body, Consumer<RequestInfo> action) {
+               return on(line, body, ContentType.APPLICATION_JSON, action);
+       }
+
+       /**
+        * Handle the specified request.
+        *
+        * @param line The HTTP method and URI to handle.
+        * @param body The response body to return, as a JSON string.
+        * @return This responder.
+        */
+       public ClientMocking on(String line, String body) {
+               return on(line, body, ContentType.APPLICATION_JSON);
+       }
+
+       /**
+        * Handle the specified request.
+        *
+        * @param line The HTTP method and URI to handle.
+        * @param body The response body to return, as a JSON string.
+        * @param type The content type of the body.
+        * @return This responder.
+        */
+       public ClientMocking on(String line, String body, ContentType type) {
+               return on(line, body, type, null);
+       }
+
+       /**
+        * Fail the specified requests.
+        *
+        * @param matcher A predicate for matching requests.
+        * @param code The HTTP error code to return.
+        * @param message The HTTP error status message to return.
+        * @return This responder.
+        */
+       public ClientMocking errorOn(Predicate<RequestInfo> matcher, int code, String message) {
+               Response r = new Response();
+               r.matcher = matcher;
+               r.code = code;
+               r.message = message;
+               responses.add(r);
+               return this;
+       }
+
+       /**
+        * Fail the specified request.
+        *
+        * @param line The HTTP method and URI to handle.
+        * @param code The HTTP error code to return.
+        * @param message The HTTP error status message to return.
+        * @return This responder.
+        */
+       public ClientMocking errorOn(String line, int code, String message) {
+               return errorOn(s2p(line), code, message);
+       }
+
+       /**
+        * Fail the request if no auth header
+        *
+        * @param code The HTTP error code to return.
+        * @param message The HTTP error status message to return.
+        * @return This responder.
+        */
+       public ClientMocking errorOnNoAuth(int code, String message) {
+               return errorOn(ri -> ri.lacksHeader("Authorization"), code, message);
+       }
+
+       /**
+        * Fail the request if wrong auth header
+        *
+        * @param username The expected user name.
+        * @param password The expected password.
+        * @param code The HTTP error code to return.
+        * @param message The HTTP error status message to return.
+        * @return This responder.
+        */
+       public ClientMocking errorOnBadAuth(String username, String password, int code, String message) {
+               String authhdr = "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
+               return errorOn(ri -> ri.lacksHeaderValue("Authorization", authhdr), code, message);
+       }
+}
@@ -2,27 +2,23 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-
 /**
- * 
+ * Utilities for testing applications using the Federation Gateway clients.
  */
-/**
- * 
- *
- */
-package org.acumos.federation.gateway.util;
+
+package org.acumos.federation.client.test;
@@ -15,4 +15,18 @@ 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=========================================================
-Mock Content of an Artifact
+
+The files in this directory form an isolated 3 member TLS trust community,
+suitable for testing client/server interactions using HTTPS with client
+certificates.
+
+When invoked with "acumosa", "acumosb", or "acumosc", the method
+org.acumos.federation.client.test.ClientMocking.getConfig(name) will return
+a ClientConfig object suitably populated to use these files.
+
+The key stores, acumosa.pkcs12, acumosb.pkcs12, and acumosc.pkcs12, each contain
+a private key and corresponding certificate, and can be used by either a client
+or a server.
+
+The trust store acumosTrustStore.jks contains the certificate authority
+certificate referenced by the client certificates in the key store files.
diff --git a/acumos-fgw-client-test/src/test/java/org/acumos/federation/client/test/ClientMockingTest.java b/acumos-fgw-client-test/src/test/java/org/acumos/federation/client/test/ClientMockingTest.java
new file mode 100644 (file)
index 0000000..e7f1a40
--- /dev/null
@@ -0,0 +1,111 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client.test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.web.client.HttpClientErrorException.Unauthorized;
+import org.springframework.web.client.HttpClientErrorException.Forbidden;
+import org.springframework.web.client.ResourceAccessException;
+
+import static org.acumos.federation.client.test.ClientMocking.xq;
+import static org.acumos.federation.client.test.ClientMocking.getConfig;
+
+public class ClientMockingTest {
+       private RestTemplate restTemplate;
+       public int count;
+
+       public static class X {
+               private String y;
+               public String getY() {
+                       return y;
+               }
+               public void setY(String y) {
+                       this.y = y;
+               }
+       }
+
+       @Test
+       public void testClientMocking() throws Exception {
+               assertEquals("{\"a\":\"b\"}", xq("{'a':'b'}"));
+               assertNotNull(getConfig("acumosa"));
+               ClientMockingTest rt = this;
+               restTemplate = new RestTemplate();
+               ClientMocking answers = (new ClientMocking())
+                       .errorOnNoAuth(401, "Unauthorized")
+                       .errorOnBadAuth("user", "pass", 403, "Forbidden")
+                       .on("GET /xyzzy", "[ \"string\" ]")
+                       .on("GET /empty?withparam=Z", "", info -> { rt.count++; })
+                       .errorOn("GET /fail", 403, "Forbidden")
+                       .applyTo(this);
+               try {
+                       List<String> ret = restTemplate.exchange("http://example/xyzzy", HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>(){}).getBody();
+                       fail();
+               } catch (Unauthorized ux) {
+                       // expected case
+               }
+               ClientMocking noNoAuthAnswers = (new ClientMocking())
+                       .errorOnBadAuth("user", "pass", 403, "Forbidden")
+                       .applyTo(this);
+               try {
+                       List<String> ret = restTemplate.exchange("http://example/xyzzy", HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>(){}).getBody();
+                       fail();
+               } catch (Forbidden fx) {
+                       // expected case
+               }
+               restTemplate = new RestTemplateBuilder().basicAuthentication("user", "wrong").build();
+               answers.applyTo(this);
+               try {
+                       List<String> ret = restTemplate.exchange("http://example/xyzzy", HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>(){}).getBody();
+                       fail();
+               } catch (Forbidden fx) {
+                       // expected case
+               }
+               restTemplate = new RestTemplateBuilder().basicAuthentication("user", "pass").rootUri("http://example").build();
+               answers.applyTo(this);
+               List<String> ret = restTemplate.exchange("/xyzzy", HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>(){}).getBody();
+               assertEquals(1, ret.size());
+               assertEquals("string", ret.get(0));
+               assertNull(restTemplate.exchange("/empty?withparam={pvalue}", HttpMethod.GET, null, new ParameterizedTypeReference<X>(){}, "Z").getBody());
+               try {
+                       restTemplate.exchange("/fail", HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>(){});
+                       fail();
+               } catch (Forbidden fx) {
+                       // expected case
+               }
+               try {
+                       restTemplate.exchange("/unhandled", HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>(){});
+                       fail();
+               } catch (ResourceAccessException rae) {
+                       // expected case
+               }
+               assertEquals(1, count);
+       }
+}
diff --git a/acumos-fgw-client/.gitignore b/acumos-fgw-client/.gitignore
new file mode 100644 (file)
index 0000000..ae040c7
--- /dev/null
@@ -0,0 +1,10 @@
+.classpath
+.factorypath
+.project
+/.settings/
+/bin/
+/target/
+/logs/
+/debug-logs/
+/.apt_generated/
+/.apt_generated_tests/
diff --git a/acumos-fgw-client/README.md b/acumos-fgw-client/README.md
new file mode 100644 (file)
index 0000000..6e1d728
--- /dev/null
@@ -0,0 +1,17 @@
+# Acumos Federation Gateway Client
+
+This sub-project contains client classes for making REST requests to the Acumos Federation Gateway.
+
+Please see the documentation in the parent project's "docs" folder.
+
+## License
+
+Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+Acumos 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.
diff --git a/acumos-fgw-client/pom.xml b/acumos-fgw-client/pom.xml
new file mode 100644 (file)
index 0000000..c8ff40d
--- /dev/null
@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+<!--<![CDATA[
+===============LICENSE_START=======================================================
+Acumos
+===================================================================================
+Copyright (C) 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
+limitations under the License.
+===============LICENSE_END=========================================================
+]]>-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>federation-parent</artifactId>
+               <version>0</version>
+       </parent>
+       <groupId>org.acumos.federation</groupId>
+       <artifactId>acumos-fgw-client</artifactId>
+       <version>2.3.0-SNAPSHOT</version>
+       <name>Federation Gateway Client</name>
+       <properties>
+               <!-- dependency versions -->
+               <common-dataservice.version>2.2.2</common-dataservice.version>
+       </properties>
+       <!-- Dependency/plugin versions are inherited from parent pom -->
+       <dependencies>
+               <dependency>
+                       <groupId>org.acumos.common-dataservice</groupId>
+                       <artifactId>cmn-data-svc-client</artifactId>
+                       <version>${common-dataservice.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.acumos.federation</groupId>
+                       <artifactId>acumos-fgw-client-config</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.projectlombok</groupId>
+                       <artifactId>lombok</artifactId>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <!-- needed for RestTemplateBuilder -->
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.httpcomponents</groupId>
+                       <artifactId>httpcore</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.httpcomponents</groupId>
+                       <artifactId>httpclient</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.fasterxml.jackson.datatype</groupId>
+                       <artifactId>jackson-datatype-jsr310</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.fasterxml.jackson.core</groupId>
+                       <artifactId>jackson-databind</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.fasterxml.jackson.core</groupId>
+                       <artifactId>jackson-core</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework</groupId>
+                       <artifactId>spring-core</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework</groupId>
+                       <artifactId>spring-web</artifactId>
+               </dependency>
+               <!-- Test dependencies -->
+               <dependency>
+                       <groupId>org.acumos.federation</groupId>
+                       <artifactId>acumos-fgw-client-test</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <!-- Test runtime dependencies -->
+               <dependency>
+                       <groupId>ch.qos.logback</groupId>
+                       <artifactId>logback-classic</artifactId>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.projectlombok</groupId>
+                               <artifactId>lombok-maven-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.jacoco</groupId>
+                               <artifactId>jacoco-maven-plugin</artifactId>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
diff --git a/acumos-fgw-client/src/license/acumos/header.txt b/acumos-fgw-client/src/license/acumos/header.txt
new file mode 100644 (file)
index 0000000..d901067
--- /dev/null
@@ -0,0 +1,11 @@
+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.
diff --git a/acumos-fgw-client/src/license/acumos/license.txt b/acumos-fgw-client/src/license/acumos/license.txt
new file mode 100644 (file)
index 0000000..d901067
--- /dev/null
@@ -0,0 +1,11 @@
+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.
diff --git a/acumos-fgw-client/src/license/licenses.properties b/acumos-fgw-client/src/license/licenses.properties
new file mode 100644 (file)
index 0000000..71a69a0
--- /dev/null
@@ -0,0 +1,21 @@
+###
+# ===============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=========================================================
+###
+
+acumos=acumos
diff --git a/acumos-fgw-client/src/main/java/org/acumos/federation/client/ClientBase.java b/acumos-fgw-client/src/main/java/org/acumos/federation/client/ClientBase.java
new file mode 100644 (file)
index 0000000..50ecb23
--- /dev/null
@@ -0,0 +1,388 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client;
+
+import java.io.FileInputStream;
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URI;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.Collections;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.ssl.SSLContexts;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.http.converter.ByteArrayHttpMessageConverter;
+import org.springframework.http.converter.ResourceHttpMessageConverter;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+import org.acumos.cds.domain.MLPCatalog;
+import org.acumos.cds.domain.MLPSolution;
+import org.acumos.cds.domain.MLPSolutionRevision;
+import org.acumos.cds.domain.MLPArtifact;
+import org.acumos.cds.domain.MLPDocument;
+
+import org.acumos.federation.client.config.ClientConfig;
+import org.acumos.federation.client.config.TlsConfig;
+import org.acumos.federation.client.config.BasicAuthConfig;
+import org.acumos.federation.client.data.JsonResponse;
+import org.acumos.federation.client.data.Catalog;
+import org.acumos.federation.client.data.Solution;
+import org.acumos.federation.client.data.SolutionRevision;
+import org.acumos.federation.client.data.Artifact;
+import org.acumos.federation.client.data.Document;
+
+/**
+ * Base class for building clients.
+ *
+ * This class supports construction with a base URL for the server,
+ * configuration of 2-way certificate authentication, credential based
+ * authentication, and mapping of received data to extended classes
+ * with extra fields.
+ *
+ * This class uses the Spring Framework RestTemplate mechanism to
+ * implement the client side of REST services.
+ * In most cases, a subclass only needs to provide
+ * methods invoking one of this class' handle() or handleRequest()
+ * methods for each transaction.
+ */
+public class ClientBase {
+       /**
+        * Builder for mappers supporting parsing extended classes
+        * with extra fields.
+        */
+       public static class MapperBuilder {
+               private SimpleModule module = new SimpleModule();
+
+               /**
+                * Create a mapper builder that will use extended
+                * classes {@link Catalog}, {@link Solution}, {@link SolutionRevision}, {@link Artifact}, and {@link Document}.
+                */
+               public MapperBuilder() {
+                       add(MLPCatalog.class, Catalog.class);
+                       add(MLPSolution.class, Solution.class);
+                       add(MLPSolutionRevision.class, SolutionRevision.class);
+                       add(MLPArtifact.class, Artifact.class);
+                       add(MLPDocument.class, Document.class);
+               }
+
+               /**
+                * Add a mapping to the mapper.
+                *
+                * @param base The base (super) class to be mapped.
+                * @param enhanced The enhanced (sub) class to be used, instead.
+                * @return This builder.
+                */
+               public <B, E extends B> MapperBuilder add(Class<B> base, Class<E> enhanced) {
+                       module.addDeserializer(base, new StdDeserializer<B>(base) {
+                               @Override
+                               public B deserialize(JsonParser parser, DeserializationContext context) throws IOException {
+                                       return((ObjectMapper)parser.getCodec()).readValue(parser, enhanced);
+                               }
+                       });
+                       return this;
+               }
+
+               /**
+                * Build the mapper.
+                *
+                * @return A mapper with the specified class mappings added.
+                */
+               public ObjectMapper build() {
+                       ObjectMapper mapper = new ObjectMapper();
+                       mapper.registerModule(module);
+                       mapper.registerModule(new JavaTimeModule());
+                       return mapper;
+               }
+       }
+
+       private static ObjectMapper defaultMapper = new MapperBuilder().build();
+
+       /**
+        * Get the current default mapper.
+        *
+        * The default mapper is used when null is specified for the mapper
+        * when constructing a client.
+        * @return The mapper.
+        */
+       public static ObjectMapper getDefaultMapper() {
+               return defaultMapper;
+       }
+
+       /**
+        * Replace the current default mapper.
+        *
+        * @param mapper The new default mapper.
+        */
+       public static void setDefaultMapper(ObjectMapper mapper) {
+               defaultMapper = mapper;
+       }
+
+       /**
+        * The Spring Framework restTemplate.
+        */
+       protected RestTemplate restTemplate;
+
+       private static InputStream openResource(ResourceLoader loader, String source) throws IOException {
+               try {
+                       return loader.getResource(source).getURL().openStream();
+               } catch (FileNotFoundException fnfe) {
+                       return new FileInputStream(source);
+               }
+       }
+
+       private static KeyStore getKeyStore(ResourceLoader loader, String store, String type, String password) throws IOException, GeneralSecurityException {
+               if (store == null || type == null || password == null) {
+                       return null;
+               }
+               try (InputStream is = openResource(loader, store)) {
+                       KeyStore ret = KeyStore.getInstance(type);
+                       ret.load(is, password.toCharArray());
+                       return ret;
+               }
+       }
+
+       /**
+        * Build a RestTemplate for a client.
+        *
+        * If mapper is null, the default mapper is used.
+        * If loader is null, a DefaultResourceLoader is created and used.
+        * The loader is used for accessing the key store and trust store
+        * for TLS certificates.
+        *
+        * @param target The base URL for the server to be accessed.
+        * @param conf The configuration for certificates and credentials.
+        * @param mapper The object mapper.
+        * @param loader The resource loader.
+        * @return A RestTemplate for the supplied parameters.
+        */
+       public static RestTemplate buildRestTemplate(String target, ClientConfig conf, ObjectMapper mapper, ResourceLoader loader) {
+               try {
+                       target = new URL(target).toExternalForm().replaceAll("/*$", "");
+               } catch (MalformedURLException mue) {
+                       throw new IllegalArgumentException("Bad target URL " + target, mue);
+               }
+               if (loader == null) {
+                       loader = new DefaultResourceLoader();
+               }
+               if (mapper == null) {
+                       mapper = getDefaultMapper();
+               }
+               SSLContextBuilder sslContextBuilder = SSLContexts.custom();
+               TlsConfig tls = conf.getSsl();
+               RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.create();
+               registryBuilder.register("http", PlainConnectionSocketFactory.getSocketFactory());
+               HttpClientBuilder clientBuilder = HttpClients.custom();
+               try {
+                       if (tls != null) {
+                               KeyStore store = getKeyStore(loader, tls.getKeyStore(), tls.getKeyStoreType(), tls.getKeyStorePassword());
+                               if (store != null) {
+                                       String alias = tls.getKeyAlias();
+                                       sslContextBuilder.loadKeyMaterial(store, tls.getKeyStorePassword().toCharArray(), alias == null? null: (aliases, socket) -> alias);
+                               }
+                               store = getKeyStore(loader, tls.getTrustStore(), tls.getTrustStoreType(), tls.getTrustStorePassword());
+                               if (store != null) {
+                                       sslContextBuilder.loadTrustMaterial(store, null);
+                               }
+                       }
+                       SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), new String[] { "TLSv1.2" }, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
+                       registryBuilder.register("https", sslSocketFactory);
+                       clientBuilder.setConnectionManager(new BasicHttpClientConnectionManager(registryBuilder.build()));
+                       clientBuilder.setSSLSocketFactory(sslSocketFactory);
+               } catch (Exception ex) {
+                       throw new TlsConfigException("Invalid TLS configuration", ex);
+               }
+               HttpClient client = clientBuilder.build();
+               BasicAuthConfig creds = conf.getCreds();
+               MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
+               messageConverter.setObjectMapper(mapper);
+               ResourceHttpMessageConverter contentConverter = new ResourceHttpMessageConverter();
+               contentConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_OCTET_STREAM));
+               HttpComponentsClientHttpRequestFactory chrf = new HttpComponentsClientHttpRequestFactory(client);
+               chrf.setBufferRequestBody(false);
+               RestTemplateBuilder rtb = new RestTemplateBuilder()
+                   .requestFactory(() -> chrf)
+                   .messageConverters(new ByteArrayHttpMessageConverter(), messageConverter, contentConverter)
+                   .uriTemplateHandler(new DefaultUriBuilderFactory())
+                   .rootUri(target);
+               if (creds != null && creds.getUsername() != null && creds.getPassword() != null) {
+                       rtb = rtb.basicAuthentication(creds.getUsername(), creds.getPassword());
+               }
+               return rtb.build();
+       }
+
+       /**
+        * Create a client.
+        *
+        * If mapper is null, the default mapper is used.
+        * If loader is null, a DefaultResourceLoader is created and used.
+        * The loader is used for accessing the key store and trust store
+        * for TLS certificates.
+        *
+        * @param target The base URL for the server to be accessed.
+        * @param conf The configuration for certificates and credentials.
+        * @param mapper The object mapper.
+        * @param loader The resource loader.
+        */
+       protected ClientBase(String target, ClientConfig conf, ObjectMapper mapper, ResourceLoader loader) {
+               restTemplate = buildRestTemplate(target, conf, mapper, loader);
+       }
+
+       /**
+        * Execute a REST transaction.
+        *
+        * @param uri The URI relative, to this client's target.
+        * @param method The HTTP method.
+        * @param type The wire type of the expected response.
+        * @param params Values for parameters in the target and uri.
+        */
+       protected <T> T handle(String uri, HttpMethod method, ParameterizedTypeReference<T> type, Object ... params) {
+               return restTemplate.exchange(uri, method, null, type, params).getBody();
+       }
+
+       /**
+        * Execute a REST transaction and unwrap the response, returning its content.
+        *
+        * @param uri The URI relative, to this client's target.
+        * @param method The HTTP method.
+        * @param type The wire type of the expected response.
+        * @param params Values for parameters in the target and uri.
+        */
+       protected <T> T handleResponse(String uri, HttpMethod method, ParameterizedTypeReference<JsonResponse<T>> type, Object ... params) {
+               JsonResponse<T> ret = handle(uri, method, type, params);
+               return ret == null? null: ret.getContent();
+       }
+
+       /**
+        * Execute a REST GET transaction and unwrap the response, returning its content.
+        *
+        * @param uri The URI relative, to this client's target.
+        * @param type The wire type of the expected response.
+        * @param params Values for parameters in the target and uri.
+        */
+       protected <T> T handleResponse(String uri, ParameterizedTypeReference<JsonResponse<T>> type, Object ... params) {
+               return handleResponse(uri, HttpMethod.GET, type, params);
+       }
+
+       /**
+        * Download potentially large binary content from the specified URL.
+        *
+        * @param uri The template for the URI to download.
+        * @param params The parameters for the template.
+        * @return An InputStream for reading the content.
+        */
+       protected InputStream download(String uri, Object ... params) {
+               ClientHttpResponse response = null;
+               URI url = restTemplate.getUriTemplateHandler().expand(uri, params);
+               try { // NOSONAR
+                       /*
+                        * Sonar says use try-with-resources, but can't use it
+                        * here: have to leave response open when returning its
+                        * InputStream (normal case).  Returned InputStream
+                        * is wrapped in a FilterInputStream so When returned
+                        * value is closed, response will also be closed.
+                        */
+                       ClientHttpRequest request = restTemplate.getRequestFactory().createRequest(url, HttpMethod.GET);
+                       ResponseErrorHandler errHandler = restTemplate.getErrorHandler();
+                       request.getHeaders().setAccept(Collections.singletonList(MediaType.ALL));
+                       response = request.execute();
+                       if (errHandler.hasError(response)) {
+                               errHandler.handleError(url, HttpMethod.GET, response);
+                       }
+                       ClientHttpResponse xr = response;
+                       InputStream ret = new FilterInputStream(xr.getBody()) {
+                               @Override
+                               public void close() throws IOException {
+                                       in.close();
+                                       xr.close();
+                               }
+                       };
+                       response = null;
+                       return ret;
+               } catch (IOException ioe) {
+                       throw new ResourceAccessException("I/O error on GET request for \"" + url + "\": " + ioe.getMessage(), ioe);
+               } finally {
+                       if (response != null) {
+                               response.close();
+                       }
+               }
+       }
+
+       /**
+        * Upload potentially large binary content to the specified URL.
+        *
+        * @param uri The template for the URI to download.
+        * @param method The method (usually POST or PUT).
+        * @param inputStream The data to upload.
+        * @param params The parameters for the template.
+        */
+       protected void upload(String uri, HttpMethod method, InputStream inputStream, Object ... params) {
+               HttpHeaders headers = new HttpHeaders();
+               headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
+               restTemplate.exchange(uri, method, new HttpEntity<>(new InputStreamResource(inputStream), headers), Void.class, params);
+       }
+
+       /**
+        * Upload (PUT) potentially large binary content to the specified URL.
+        *
+        * @param uri The template for the URI to download.
+        * @param inputStream The data to upload.
+        * @param params The parameters for the template.
+        */
+       protected void upload(String uri, InputStream inputStream, Object ... params) {
+               upload(uri, HttpMethod.PUT, inputStream, params);
+       }
+}
diff --git a/acumos-fgw-client/src/main/java/org/acumos/federation/client/FederationClient.java b/acumos-fgw-client/src/main/java/org/acumos/federation/client/FederationClient.java
new file mode 100644 (file)
index 0000000..9d9dc05
--- /dev/null
@@ -0,0 +1,288 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client;
+
+import java.util.List;
+import java.io.InputStream;
+import java.net.URI;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+
+import org.acumos.cds.domain.MLPPeer;
+import org.acumos.cds.domain.MLPCatalog;
+import org.acumos.cds.domain.MLPSolution;
+import org.acumos.cds.domain.MLPSolutionRevision;
+import org.acumos.cds.domain.MLPArtifact;
+import org.acumos.cds.domain.MLPDocument;
+
+import org.acumos.federation.client.config.ClientConfig;
+import org.acumos.federation.client.data.JsonResponse;
+
+/**
+ * Client for the Federation Server's public (E5) API.  Note that servers
+ * implementing the API may restrict what information they
+ * share with clients.  Servers may refuse access to some clients, may refuse
+ * access to some operations, may restrict what data is visible to clients,
+ * etc., based on their particular policies.  This may result in client
+ * methods returning null, returning lists with reduced numbers of elements, or 
+ * throwing {@link org.springframework.web.client.RestClientException} or its
+ * subclasses.
+ * @see GatewayClient
+ */
+public class FederationClient extends ClientBase {
+       /**
+        * The base URI for pinging.
+        */
+       public static final String PING_URI = "/ping";
+       /**
+        * The base URI for listing known peers.
+        */
+       public static final String PEERS_URI = "/peers";
+       /**
+        * The base URI for listing visible catalogs.
+        */
+       public static final String CATALOGS_URI = "/catalogs";
+       /**
+        * The base URI for listing catalog solutions.
+        */
+       public static final String SOLUTIONS_URI = "/solutions";
+       /**
+        * The base URI for fetching solution metadata.
+        */
+       public static final String SOLUTION_URI = "/solutions/{solutionId}";
+       /**
+        * The base URI for listing solution revisions.
+        */
+       public static final String REVISIONS_URI = "/solutions/{solutionId}/revisions";
+       /**
+        * The base URI for fetching revision metadata.
+        */
+       public static final String REVISION_URI = "/solutions/{solutionId}/revisions/{revisionId}";
+       /**
+        * The base URI for listing revision artifacts.
+        */
+       public static final String ARTIFACTS_URI = "/solutions/{solutionId}/revisions/{revisionId}/artifacts";
+       /**
+        * The base URI for fetching artifact content.
+        */
+       public static final String ARTIFACT_URI = "/artifacts/{artifactId}/content";
+       /**
+        * The base URI for listing revision documents.
+        */
+       public static final String DOCUMENTS_URI = "/revisions/{revisionId}/documents";
+       /**
+        * The base URI for fetching document content.
+        */
+       public static final String DOCUMENT_URI = "/documents/{documentId}/content";
+       /**
+        * The base URI for registering.
+        */
+       public static final String REGISTER_URI = "/peer/register";
+       /**
+        * The base URI for unregistering.
+        */
+       public static final String UNREGISTER_URI = "/peer/unregister";
+
+       /**
+        * The query for specifying a catalog ID.
+        */
+       public static final String CATID_QUERY = "?catalogId={catalogId}";
+
+       /**
+        * Peer Status Code for Active
+        */
+       public static final String PSC_ACTIVE = "AC";
+       /**
+        * Peer Status Code for Renounced
+        */
+       public static final String PSC_RENOUNCED = "RN";
+       /**
+        * Peer Status Code for Requested
+        */
+       public static final String PSC_REQUESTED = "RQ";
+
+       /**
+        * Artifact Type Code for Docker Image
+        */
+       public static final String ATC_DOCKER = "DI";
+
+       /**
+        * Create a Federation Client with the default mapper and resource loader.
+        *
+        * @param target The base URL for the server to be accessed.
+        * @param conf The configuration for certificates and credentials.
+        */
+       public FederationClient(String target, ClientConfig conf) {
+               this(target, conf, null, null);
+       }
+
+       /**
+        * Create a Federation Client.
+        *
+        * @param target The base URL for the server to be accessed.
+        * @param conf The configuration for certificates and credentials.
+        * @param mapper The object mapper.  If mapper is null, the default
+        *               object mapper is used to read and write JSON.
+        * @param loader The resource loader.  If loader is null, a
+        *               DefaultResourceLoader is created and used.
+        *               The loader is used for accessing the key store
+        *               and trust store for TLS certificates.
+        */
+       public FederationClient(String target, ClientConfig conf, ObjectMapper mapper, ResourceLoader loader) {
+               super(target, conf, mapper, loader);
+       }
+
+       /**
+        * Check connectivity to the server.
+        *
+        * @return The server's own MLPPeer record.
+        */
+       public MLPPeer ping() {
+               return handleResponse(PING_URI, new ParameterizedTypeReference<JsonResponse<MLPPeer>>(){});
+       }
+
+       /**
+        * Get a list of the server's peers.
+        *
+        * @return The list of peers.
+        */
+       public List<MLPPeer> getPeers() {
+               return handleResponse(PEERS_URI, new ParameterizedTypeReference<JsonResponse<List<MLPPeer>>>(){});
+       }
+
+       /**
+        * Request the server to add this client to its list of peers.
+        *
+        * @return The server's own MLPPeer record.
+        */
+       public MLPPeer register() {
+               return handleResponse(REGISTER_URI, HttpMethod.POST, new ParameterizedTypeReference<JsonResponse<MLPPeer>>(){});
+       }
+
+       /**
+        * Request that the server drop this client from its list of peers.
+        *
+        * @return The server's own MLPPeer record.
+        */
+       public MLPPeer unregister() {
+               return handleResponse(UNREGISTER_URI, HttpMethod.POST, new ParameterizedTypeReference<JsonResponse<MLPPeer>>(){});
+       }
+
+       /**
+        * Get a list of the server's catalogs.
+        *
+        * @return The list of catalogs (enhanced with their sizes), the peer is willing to share.
+        */
+       public List<MLPCatalog> getCatalogs() {
+               return handleResponse(CATALOGS_URI, new ParameterizedTypeReference<JsonResponse<List<MLPCatalog>>>(){});
+       }
+
+       /**
+        * Get a list of the solutions in a catalog.
+        *
+        * @param catalogId The ID of the catalog containing the solutions.
+        * @return The list of solutions in the catalog.
+        */
+       public List<MLPSolution> getSolutions(String catalogId) {
+               return handleResponse(SOLUTIONS_URI + CATID_QUERY, new ParameterizedTypeReference<JsonResponse<List<MLPSolution>>>(){}, catalogId);
+       }
+
+       /**
+        * Get information about a solution.
+        *
+        * @param solutionId The ID of the solution.
+        * @return The solution's metadata, enhanced with its picture and revisions.
+        */
+       public MLPSolution getSolution(String solutionId) {
+               return handleResponse(SOLUTION_URI, new ParameterizedTypeReference<JsonResponse<MLPSolution>>(){}, solutionId);
+       }
+
+       /**
+        * Get a list of revisions in a solution.
+        *
+        * @param solutionId The ID of the solution.
+        * @return The solution's revisions.
+        */
+       public List<MLPSolutionRevision> getSolutionRevisions(String solutionId) {
+               return handleResponse(REVISIONS_URI, new ParameterizedTypeReference<JsonResponse<List<MLPSolutionRevision>>>(){}, solutionId);
+       }
+
+       /**
+        * Get information about a revision.
+        *
+        * Note: if catalogId is null, no description or documents will be returned.
+        * @param solutionId The ID of the solution.
+        * @param revisionId The ID of the revision.
+        * @param catalogId The ID of the catalog listing the solution.
+        * @return The revision's metadata, enhanced with its description, artifacts, and documents.
+        */
+       public MLPSolutionRevision getSolutionRevision(String solutionId, String revisionId, String catalogId) {
+               if (catalogId != null) {
+                       return handleResponse(REVISION_URI + CATID_QUERY, new ParameterizedTypeReference<JsonResponse<MLPSolutionRevision>>(){}, solutionId, revisionId, catalogId);
+               }
+               return handleResponse(REVISION_URI, new ParameterizedTypeReference<JsonResponse<MLPSolutionRevision>>(){}, solutionId, revisionId);
+       }
+
+       /**
+        * Get a list of artifacts in a revision.
+        *
+        * @param solutionId The ID of the solution.
+        * @param revisionId The ID of the revision.
+        * @return The revision's artifacts.
+        */
+       public List<MLPArtifact> getArtifacts(String solutionId, String revisionId) {
+               return handleResponse(ARTIFACTS_URI, new ParameterizedTypeReference<JsonResponse<List<MLPArtifact>>>(){}, solutionId, revisionId);
+       }
+
+       /**
+        * Fetch the content of an artifact.
+        *
+        * Note: artifact content can be large (gigabytes).
+        * @param artifactId The ID of the artifact.
+        * @return An InputStream for retrieving the artifact content.
+        */
+       public InputStream getArtifactContent(String artifactId) {
+               return download(ARTIFACT_URI, artifactId);
+       }
+
+       /**
+        * List the documents in a revision and catalog.
+        *
+        * @param revisionId The ID of the revision.
+        * @param catalogId The ID of the catalog listing the revision's solution.
+        * @return The revision's documents.
+        */
+       public List<MLPDocument> getDocuments(String revisionId, String catalogId) {
+               return handleResponse(DOCUMENTS_URI + CATID_QUERY, new ParameterizedTypeReference<JsonResponse<List<MLPDocument>>>(){}, revisionId, catalogId);
+       }
+
+       /**
+        * Fetch the content of a document.
+        *
+        * @param documentId The ID of the document.
+        * @return An InputStream for retrieving the artifact content.
+        */
+       public InputStream getDocumentContent(String documentId) {
+               return download(DOCUMENT_URI, documentId);
+       }
+}
diff --git a/acumos-fgw-client/src/main/java/org/acumos/federation/client/GatewayClient.java b/acumos-fgw-client/src/main/java/org/acumos/federation/client/GatewayClient.java
new file mode 100644 (file)
index 0000000..8f685a7
--- /dev/null
@@ -0,0 +1,167 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client;
+
+import java.util.List;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+
+
+import org.acumos.cds.domain.MLPPeer;
+import org.acumos.cds.domain.MLPCatalog;
+import org.acumos.cds.domain.MLPSolution;
+
+import org.acumos.federation.client.config.ClientConfig;
+import org.acumos.federation.client.data.JsonResponse;
+
+/**
+ * Client for the Federation Gateway's private API.  Except as specified,
+ * these operations simply request that the gateway server proxy the specified
+ * request using the gateway server's own credentials, to the specified peer
+ * federation server.  Both the gateway server, and the federation server
+ * responding to a request proxied by the gateway server, may refuse access to
+ * some clients, may refuse access to some operations, may restrict what data is
+ * visible to clients, etc. based on their particular policies.  This may result
+ * in client methods returning null, returning lists with reduced numbers of
+ * elements, or throwing
+ * {@link org.springframework.web.client.RestClientException} or its subclasses.
+ * @see FederationClient
+ */
+public class GatewayClient extends ClientBase {
+       /**
+        * The URI prefix for specifying what peer the request refers to.
+        */
+       public static final String PEER_PFX = "/peer/{peerId}";
+
+       /**
+        * The base URI for triggering subscriptions.
+        */
+       public static final String SUBSCRIPTION_URI = "/subscription/{subscriptionId}";
+
+       /**
+        * Create a Gateway Client with the default mapper and resource loader.
+        *
+        * @param target The base URL for the server to be accessed.
+        * @param conf The configuration for certificates and credentials.
+        */
+       public GatewayClient(String target, ClientConfig conf) {
+               this(target, conf, null, null);
+       }
+
+       /**
+        * Create a Gateway Client.
+        *
+        * @param target The base URL for the server to be accessed.
+        * @param conf The configuration for certificates and credentials.
+        * @param mapper The object mapper.  If mapper is null, the default
+        *               object mapper is used to read and write JSON.
+        * @param loader The resource loader.  If loader is null, a
+        *               DefaultResourceLoader is created and used.
+        *               The loader is used for accessing the key store
+        *               and trust store for TLS certificates.
+        */
+       public GatewayClient(String target, ClientConfig conf, ObjectMapper mapper, ResourceLoader loader) {
+               super(target, conf, mapper, loader);
+       }
+
+       /**
+        * Verify connectivity between the local gateway server and the remote
+        * federation server.
+        *
+        * @param peerId The ID of the peer Acumos.
+        * @return The remote server's own MLPPeer record.
+        */
+       public MLPPeer ping(String peerId) {
+               return handleResponse(PEER_PFX + FederationClient.PING_URI, new ParameterizedTypeReference<JsonResponse<MLPPeer>>(){}, peerId);
+       }
+
+       /**
+        * Ask the remote federation server for
+        * a list of its peers.
+        *
+        * @param peerId The ID of the peer Acumos.
+        * @return The list of the peer's peers.
+        */
+       public List<MLPPeer> getPeers(String peerId) {
+               return handleResponse(PEER_PFX + FederationClient.PEERS_URI, new ParameterizedTypeReference<JsonResponse<List<MLPPeer>>>(){}, peerId);
+       }
+
+       /**
+        * Ask the remote federation server to
+        * add the local server to its list of peers.
+        *
+        * @param peerId The ID of the peer Acumos.
+        * @return The remote server's own MLPPeer record.
+        */
+       public MLPPeer register(String peerId) {
+               return handleResponse(PEER_PFX + FederationClient.REGISTER_URI, HttpMethod.POST, new ParameterizedTypeReference<JsonResponse<MLPPeer>>(){}, peerId);
+       }
+
+       /**
+        * Ask the remote federation server
+        * for a list of catalogs.
+        *
+        * @param peerId The ID of the peer Acumos.
+        * @return The list of catalogs (enhanced with their sizes), the peer is willing to share.
+        */
+       public List<MLPCatalog> getCatalogs(String peerId) {
+               return handleResponse(PEER_PFX + FederationClient.CATALOGS_URI, new ParameterizedTypeReference<JsonResponse<List<MLPCatalog>>>(){}, peerId);
+       }
+
+       /**
+        * Ask the remote federation server
+        * for a list of solutions.
+        *
+        * @param peerId The ID of the peer Acumos.
+        * @param catalogId The ID of the catalog to query.
+        * @return The list of solutions in the peer's catalog.
+        */
+       public List<MLPSolution> getSolutions(String peerId, String catalogId) {
+               return handleResponse(PEER_PFX + FederationClient.SOLUTIONS_URI + FederationClient.CATID_QUERY, new ParameterizedTypeReference<JsonResponse<List<MLPSolution>>>(){}, peerId, catalogId);
+       }
+
+       /**
+        * Ask the remote federation server for information about a solution.
+        *
+        * @param peerId The ID of the peer Acumos.
+        * @param solutionId The ID of the solution.
+        * @return The solution's metadata, enhanced with its picture and revisions.
+        */
+       public MLPSolution getSolution(String peerId, String solutionId) {
+               return handleResponse(PEER_PFX + FederationClient.SOLUTION_URI, new ParameterizedTypeReference<JsonResponse<MLPSolution>>(){}, peerId, solutionId);
+       }
+
+       /**
+        * Ask the local gateway server to poll a subscription.  Note that
+        * this operation is not proxied by the local gateway server but
+        * rather requests the local gateway server to immediately poll the
+        * specified subscription to the remote federation server, without
+        * waiting until its normally scheduled time.
+        *
+        * @param peerId The ID of the peer Acumos being subscribed.
+        * @param subscriptionId The ID of the local Acumos' subscription to the peer.
+        */
+       public void triggerPeerSubscription(String peerId, long subscriptionId) {
+               handleResponse(PEER_PFX + SUBSCRIPTION_URI, HttpMethod.POST, new ParameterizedTypeReference<JsonResponse<Void>>(){}, peerId, subscriptionId);
+       }
+}
@@ -2,41 +2,36 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
+package org.acumos.federation.client;
 
-package org.acumos.federation.gateway.service;
-
-import java.util.List;
-
-import org.acumos.cds.CodeNameType;
-import org.acumos.cds.domain.MLPCodeNamePair;
+import org.springframework.web.client.RestClientException;
 
 /**
- * 
- *
+ * Exception thrown when an error occurs setting up TLS for a RestTemplate.
  */
-public interface CodeNamesService {
-
+public class TlsConfigException extends RestClientException {
        /**
-        * @param theType
-        *            Category of code names
-        * @return List of CodeNamePairs configured in the Local Acumos Instance
-        * @throws ServiceException On failure
+        * Construct a new instance of TlsConfigException with the given message and exception.
+        *
+        * @param msg The message.
+        * @param ex The exception.
         */
-       public List<MLPCodeNamePair> getCodeNames(CodeNameType theType) throws ServiceException;
-
+       public TlsConfigException(String msg, Throwable ex) {
+               super(msg, ex);
+       }
 }
@@ -2,27 +2,24 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-
 /**
- * 
+ * Client library for the Acumos Federation Gateway.
+ * Contains clients for both the local API and the external API.
  */
-/**
- * 
- *
- */
-package org.acumos.federation.gateway.config;
+
+package org.acumos.federation.client;
diff --git a/acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Artifact.java b/acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Artifact.java
new file mode 100644 (file)
index 0000000..7eeafe6
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client.data;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import org.acumos.cds.domain.MLPArtifact;
+
+/**
+ * Artifact enhanced with file name.
+ */
+@Data
+@EqualsAndHashCode(callSuper=true)
+@ToString(callSuper=true, includeFieldNames=true)
+public class Artifact extends MLPArtifact {
+       /**
+        * The "original" file or image name of the artifact, without any
+        * storage path or repository information.  E.g. parameters.json or
+        * somedockerimage.  For image names, this is only the base name of
+        * the image, without any tag.
+        *
+        * @param filename New value for the file name.
+        * @return The current value of the file name.
+        */
+       private String filename;
+}
@@ -8,46 +8,36 @@
  * 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;
+package org.acumos.federation.client.data;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
 
 import org.acumos.cds.domain.MLPCatalog;
 
 /**
- * Supplements the CDS representation of a catalog with related information: size.
- * Allows federation to pack information passed between peers.
+ * Catalog enhanced with number of contained solutions.
  */
-public class Catalog extends MLPCatalog {
-
-       private int     size;
-
-       public Catalog() {
-       }
-
-       public Catalog(MLPCatalog theCDSCatalog) {
-               super(theCDSCatalog);
-       }
 
-       public void setSize(int theSize) {
-               size = theSize;
-       }
-
-       public int getSize() {
-               return size;
-       }
-
-       @Override
-       public String toString() {
-               return super.toString() + ", size=" + size;
-       }
+@Data
+@EqualsAndHashCode(callSuper=true)
+@ToString(callSuper=true, includeFieldNames=true)
+public class Catalog extends MLPCatalog {
+       /**
+        * The number of solutions.
+        *
+        * @param size The number of solutions.
+        * @return The number of solutions.
+        */
+       private int size;
 }
-
-
diff --git a/acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Document.java b/acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/Document.java
new file mode 100644 (file)
index 0000000..d324d45
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client.data;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import org.acumos.cds.domain.MLPDocument;
+
+/**
+ * Document enhanced with file name.
+ */
+@Data
+@EqualsAndHashCode(callSuper=true)
+@ToString(callSuper=true, includeFieldNames=true)
+public class Document extends MLPDocument {
+       /**
+        * The "original" file name of the document, without any storage path
+        * information.  E.g. Description.pdf or GreatestSolutionEver.docx.
+        *
+        * @param filename New value for the file name.
+        * @return The current value of the file name.
+        */
+       private String filename;
+}
@@ -2,34 +2,49 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-package org.acumos.federation.gateway.cds;
+package org.acumos.federation.client.data;
 
-
-import org.acumos.cds.CodeNameType;
+import lombok.Data;
 
 /**
- * A particular class of codes used to encode artifact types.
+ * Wrapper for Federation REST responses.
  */
-public interface ArtifactType extends CodeName {
-
-       public default CodeNameType getType() {
-               return CodeNameType.ARTIFACT_TYPE;
-       }
+@Data
+public class JsonResponse<T> {
+       /**
+        * Error message.
+        *
+        * @param error The error message.
+        * @return The error message (null on success).
+        */
+       private String error;
+       /**
+        * Success message.
+        *
+        * @param message The status message.
+        * @return The status message (null on error).
+        */
+       private String message;
+       /**
+        * Result.
+        *
+        * @param content The reply value.
+        * @return The reply value (null on error).
+        */
+       private T content;
 }
-
-
@@ -2,47 +2,50 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-package org.acumos.federation.gateway.cds;
+package org.acumos.federation.client.data;
 
 import java.util.List;
+import org.acumos.cds.domain.MLPSolution;
+import org.acumos.cds.domain.MLPSolutionRevision;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
 
 /**
+ * Solution enhanced to add revisions and picture.
  */
-public class PeerStatuses extends CodeNames<PeerStatus> {
-
-       public static final PeerStatus Active = forCode("AC");
-       public static final PeerStatus Inactive = forCode("IN");
-       public static final PeerStatus Requested = forCode("RQ");
-       public static final PeerStatus Renounced = forCode("RN");
-       public static final PeerStatus Declined = forCode("DC");
-       public static final PeerStatus Unknown = forCode("UK");
-
-       public PeerStatuses() {
-       }
-
-       public static PeerStatus forCode(String theCode) {
-               return CodeNames.forCode(theCode, PeerStatus.class);
-       }
-
-       public static List<PeerStatus> codes() {
-               return codes(PeerStatus.class);
-       } 
-
+@Data
+@EqualsAndHashCode(callSuper=true)
+@ToString(callSuper=true, includeFieldNames=true)
+public class Solution extends MLPSolution {
+       /**
+        * The revisions of this solution.
+        *
+        * @param revisions The revisions.
+        * @return The revisions.
+        */
+       private List<MLPSolutionRevision> revisions;
+       /**
+        * The picture for this solution.
+        *
+        * @param picture The picture.
+        * @return The picture.
+        */
+       private byte[] picture;
 }
-
-
diff --git a/acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/SolutionRevision.java b/acumos-fgw-client/src/main/lombok/org/acumos/federation/client/data/SolutionRevision.java
new file mode 100644 (file)
index 0000000..bb7c1e9
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client.data;
+
+import java.util.Collections;
+import java.util.List;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import org.acumos.cds.domain.MLPArtifact;
+import org.acumos.cds.domain.MLPDocument;
+import org.acumos.cds.domain.MLPRevCatDescription;
+import org.acumos.cds.domain.MLPSolutionRevision;
+
+/**
+ * Revision enhanced with artifacts, documents, and description.
+ */
+
+@Data
+@EqualsAndHashCode(callSuper=true)
+@ToString(callSuper=true, includeFieldNames=true)
+public class SolutionRevision extends MLPSolutionRevision {
+       /**
+        * The artifacts for the revision.
+        *
+        * @param artifacts The artifacts.
+        * @return The artifacts.
+        */
+       private List<MLPArtifact> artifacts = Collections.emptyList();
+       /**
+        * The documents for the revision.
+        *
+        * @param documents The documents for the revision for the current catalog.
+        * @return The documents for the revision for the current catalog.
+        */
+       private List<MLPDocument> documents = Collections.emptyList();
+       /**
+        * The description of the revision.
+        *
+        * @param revCatDescription The description of the revision for the current catalog.
+        * @return The description of the revision for the current catalog.
+        */
+       private MLPRevCatDescription revCatDescription;
+}
@@ -2,24 +2,23 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-
 /**
- * 
- *
+ * API data types for the Acumos Federation Gateway clients.
  */
-package org.acumos.federation.gateway.controller;
+
+package org.acumos.federation.client.data;
diff --git a/acumos-fgw-client/src/test/java/org/acumos/federation/client/ClientDemo.java b/acumos-fgw-client/src/test/java/org/acumos/federation/client/ClientDemo.java
new file mode 100644 (file)
index 0000000..9bc9002
--- /dev/null
@@ -0,0 +1,68 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client;
+
+import java.util.List;
+
+import org.acumos.cds.domain.MLPCatalog;
+
+import org.acumos.federation.client.config.ClientConfig;
+import org.acumos.federation.client.config.TlsConfig;
+import org.acumos.federation.client.data.Catalog;
+import org.acumos.federation.client.FederationClient;
+import org.acumos.federation.client.GatewayClient;
+
+/**
+ * Demonstrates use of the Federation (public "E5" interface) and
+ * Gateway (private internal interface) clients.
+ */
+public class ClientDemo {
+       private static final String peerApiUrl = "https://public.otheracumos.org:9084";
+       private static final String internalApiUrl = "https://federation-service:9011";
+       private static final String keystore = "keystore.jks";
+       private static final String keystorepass = "keystore_pass";
+       private static final String firstpeerid = "12345678-1234-1234-1234-1234567890ab";
+       private static final String secondpeerid = "cafebebe-cafe-bebe-cafe-bebecafebebe";
+
+       public static void main(String[] args) throws Exception {
+               ClientConfig cconf = new ClientConfig();
+               cconf.setSsl(new TlsConfig());
+               cconf.getSsl().setKeyStore(keystore);
+               cconf.getSsl().setKeyStorePassword(keystorepass);
+               FederationClient fedclient = new FederationClient(peerApiUrl, cconf);
+               System.out.println("Checking connectivity to remote acumos using public E5 interface");
+               System.out.println("Response from remote acumos is " + fedclient.ping());
+               System.out.println("Listing remote acumos catalogs using public E5 interface");
+               for (MLPCatalog mcat: fedclient.getCatalogs()) {
+                       System.out.println("Catalog " + mcat.getName() + " has " + ((Catalog)mcat).getSize() + " models");
+               }
+               GatewayClient gwclient = new GatewayClient(internalApiUrl, cconf);
+               System.out.println("Verifying first peer access from inside Acumos using private interface");
+               System.out.println("Response from peer acumos is " + gwclient.ping(firstpeerid));
+               System.out.println("Fetching first peer's catalogs from inside Acumos using private interface");
+               for (MLPCatalog mcat: gwclient.getCatalogs(firstpeerid)) {
+                       System.out.println("Catalog " + mcat.getName() + " has " + ((Catalog)mcat).getSize() + " models");
+               }
+               System.out.println("Fetching second peer's catalogs from inside Acumos using private interface");
+               for (MLPCatalog mcat: gwclient.getCatalogs(secondpeerid)) {
+                       System.out.println("Catalog " + mcat.getName() + " has " + ((Catalog)mcat).getSize() + " models");
+               }
+       }
+}
diff --git a/acumos-fgw-client/src/test/java/org/acumos/federation/client/ClientTest.java b/acumos-fgw-client/src/test/java/org/acumos/federation/client/ClientTest.java
new file mode 100644 (file)
index 0000000..dd134d4
--- /dev/null
@@ -0,0 +1,202 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.Before;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import org.apache.http.entity.ContentType;
+
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.web.client.HttpClientErrorException.Forbidden;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.util.UriTemplateHandler;
+
+
+import org.acumos.cds.domain.MLPSolution;
+
+import org.acumos.federation.client.config.ClientConfig;
+import org.acumos.federation.client.data.Solution;
+import org.acumos.federation.client.data.SolutionRevision;
+
+import org.acumos.federation.client.test.ClientMocking;
+import static org.acumos.federation.client.test.ClientMocking.getConfig;
+import static org.acumos.federation.client.test.ClientMocking.xq;
+
+public class ClientTest {
+       @Test
+       public void testConfig() throws Exception {
+               ClientBase.setDefaultMapper(ClientBase.getDefaultMapper());
+               ClientConfig cx = getConfig("acumosa");
+               cx.getSsl().setKeyAlias("acumosa");
+               try {
+                       new FederationClient("malformed:9999", cx, null, null);
+                       fail();
+               } catch (IllegalArgumentException iae) {
+                       // expected case
+               }
+               new FederationClient("http://localhost:9999", cx);
+               cx.getSsl().setKeyStore(null);
+               cx.getSsl().setTrustStore("--no-such-file--");
+               try {
+                       new FederationClient("http://localhost:9999", cx, ClientBase.getDefaultMapper(), new DefaultResourceLoader());
+                       fail();
+               } catch (TlsConfigException tcx) {
+                       // expected case
+               }
+               cx.getSsl().setTrustStore("/dev/null");
+               try {
+                       new FederationClient("http://localhost:9999", cx, null, null);
+                       fail();
+               } catch (TlsConfigException tcx) {
+                       // expected case
+               }
+               cx.getSsl().setTrustStorePassword(null);
+               cx.getCreds().setPassword(null);
+               new FederationClient("http://localhost:9999", cx, null, null);
+               cx.getSsl().setTrustStoreType(null);
+               cx.getCreds().setUsername(null);
+               new FederationClient("http://localhost:9999", cx, null, null);
+               cx.setSsl(null);
+               cx.setCreds(null);
+               new FederationClient("http://localhost:9999", cx, null, null);
+       }
+
+       @Test
+       public void testGateway() throws Exception {
+               GatewayClient client = new GatewayClient("http://localhost:8888", getConfig("acumosa"));
+               (new ClientMocking())
+                   .errorOnNoAuth(401, "Unauthorized")
+                   .errorOnBadAuth("acumosa", "acumosa", 403, "Forbidden")
+                   .on("GET /peer/somepeerid/ping", "{}")
+                   .on("GET /peer/somepeerid/solutions/someid", xq("{ 'content': { 'solutionId': 'someId', 'picture': '9999', 'revisions': [ { 'artifacts': [], 'documents': [], 'revCatDescription': {} }] }}"))
+                   .on("GET /peer/somepeerid/solutions?catalogId=somecatid", xq("{ 'content': [ { 'solutionId': 'someId' }, { 'solutionId': 'someOtherId' }]}"))
+                   .on("GET /peer/somepeerid/catalogs", xq("{ 'content': [ { 'catalogId': '1' }, { 'catalogId': '2' }]}"))
+                   .on("GET /peer/somepeerid/peers", xq("{ 'content': [ { 'peerId': '1' } ] }"))
+                   .on("POST /peer/somepeerid/peer/register", xq("{ 'content': { 'peerId': '1' } }"))
+                   .on("POST /peer/somepeerid/subscription/99", xq("{ }"))
+                   .applyTo(client);
+               assertNull(client.ping("somepeerid"));
+               Solution sol = (Solution)client.getSolution("somepeerid", "someid");
+               assertNotNull(sol.getSolutionId());
+               assertNotNull(sol.getPicture());
+               assertNotNull(sol.getRevisions());
+               List<MLPSolution> sols = client.getSolutions("somepeerid", "somecatid");
+               assertEquals(2, sols.size());
+               assertEquals(2, client.getCatalogs("somepeerid").size());
+               assertEquals(1, client.getPeers("somepeerid").size());
+               assertNotNull(client.register("somepeerid"));
+               client.triggerPeerSubscription("somepeerid", 99);
+       }
+
+       @Test
+       public void testFederation() throws Exception {
+               FederationClient client = new FederationClient("http://localhost:9999", getConfig("acumosa"), null, null);
+               (new ClientMocking())
+                   .on("GET /ping", "{}")
+                   .on("GET /solutions/someid", xq("{ 'content': { 'solutionId': 'someId', 'picture': '9999', 'revisions': [ { 'artifacts': [], 'documents': [], 'revCatDescription': {} }] }}"))
+                   .on("GET /solutions?catalogId=somecatid", xq("{ 'content': [ { 'solutionId': 'someId' }, { 'solutionId': 'someOtherId' }]}"))
+                   .on("GET /solutions?catalogId=emptyanswer", "")
+                   .on("GET /catalogs", xq("{ 'content': [ { 'catalogId': '1', 'size': 7 }, { 'catalogId': '2' }]}"))
+                   .on("GET /peers", xq("{ 'content': [ { 'peerId': '1' } ] }"))
+                   .on("GET /solutions/solid/revisions", xq("{ 'content': [ { 'revisionId': '1' } ] }"))
+                   .on("GET /revisions/revid/documents?catalogId=catid", xq("{ 'content': [ { 'documentId': '1' } ] }"))
+                   .on("GET /solutions/solid/revisions/revid/artifacts", xq("{ 'content': [ { 'artifactId': '1' } ] }"))
+                   .on("GET /solutions/solid/revisions/revid", xq("{ 'content': { 'revisionId': 'revid', 'artifacts': [ { 'artifactId': '1' } ] } }"))
+                   .on("GET /solutions/solid/revisions/revid?catalogId=catid", xq("{ 'content': { 'revisionId': 'revid', 'artifacts': [ { 'artifactId': '1' } ], 'documents': [ { 'documentId': '2' } ] } }"))
+                   .on("POST /peer/register", xq("{ 'content': { 'peerId': '1' } }"))
+                   .on("POST /peer/unregister", xq("{ 'content': { 'peerId': '1' } }"))
+                   .on("GET /artifacts/artid/content", "abcde", ContentType.APPLICATION_OCTET_STREAM)
+                   .on("GET /documents/docid/content", "abcd", ContentType.APPLICATION_OCTET_STREAM)
+                   .errorOn("GET /artifacts/artnotallowed/content", 403, "Forbidden")
+                   .applyTo(client);
+               assertNull(client.ping());
+               Solution sol = (Solution)client.getSolution("someid");
+               assertNotNull(sol.getSolutionId());
+               assertNotNull(sol.getPicture());
+               assertNotNull(sol.getRevisions());
+               List<MLPSolution> sols = client.getSolutions("somecatid");
+               assertEquals(2, sols.size());
+               client.getSolutions("emptyanswer");
+               assertEquals(2, client.getCatalogs().size());
+               assertEquals(1, client.getPeers().size());
+               assertEquals(1, client.getSolutionRevisions("solid").size());
+               assertEquals(1, client.getSolutionRevisions("solid").size());
+               assertEquals(1, client.getDocuments("revid", "catid").size());
+               assertEquals(1, client.getArtifacts("solid", "revid").size());
+               assertEquals(1, ((SolutionRevision)client.getSolutionRevision("solid", "revid", null)).getArtifacts().size());
+               assertEquals(1, ((SolutionRevision)client.getSolutionRevision("solid", "revid", "catid")).getDocuments().size());
+               assertNotNull(client.register());
+               assertNotNull(client.unregister());
+               byte buf[] = new byte[6];
+               InputStream is = client.getArtifactContent("artid");
+               assertEquals(5, is.read(buf));
+               is.close();
+               is = client.getDocumentContent("docid");
+               assertEquals(4, is.read(buf));
+               is.close();
+               try {
+                       client.getDocumentContent("nosuchdocid");
+                       fail();
+               } catch (ResourceAccessException rse) {
+                       // expected case
+               }
+               try {
+                       client.getArtifactContent("artnotallowed");
+                       fail();
+               } catch (Forbidden un) {
+                       // expected case
+               }
+       }
+
+       private static class UploadTest extends ClientBase {
+               public UploadTest() throws Exception {
+                       super("http://example", getConfig("acumosa"), null, null);
+               }
+               public void up(String param, InputStream data) {
+                       upload("/something/{someparam}", data, param);
+               }
+       }
+
+       @Test
+       public void testUpload() throws Exception {
+               UploadTest client = new UploadTest();
+               (new ClientMocking())
+                   .errorOnNoAuth(401, "Unauthorized")
+                   .errorOnBadAuth("acumosa", "acumosa", 403, "Forbidden")
+                   .on("PUT /something/paramvalue", "")
+                   .applyTo(client);
+               client.up("paramvalue", new ByteArrayInputStream("hello".getBytes()));
+       }
+
+       @Test
+       public void testURLEncoding() throws Exception {
+               UriTemplateHandler uth = ClientBase.buildRestTemplate("https://hostname:999/funky%+ url//", new ClientConfig(), null, null).getUriTemplateHandler();
+               assertEquals("https://hostname:999/funky%25+%20url/x%20%40%25%2BA%7B%7D%20x/y%20B%2FC%20y", uth.expand("/x {var1} x/y {var2} y", "@%+A{}", "B/C").toString());
+       }
+}
diff --git a/docs/client.rst b/docs/client.rst
new file mode 100644 (file)
index 0000000..80f08e2
--- /dev/null
@@ -0,0 +1,141 @@
+.. ===============LICENSE_START=======================================================
+.. Acumos CC-BY-4.0
+.. ===================================================================================
+.. Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+.. ===================================================================================
+.. This Acumos documentation file is distributed by AT&T and Tech Mahindra
+.. under the Creative Commons Attribution 4.0 International License (the "License");
+.. you may not use this file except in compliance with the License.
+.. You may obtain a copy of the License at
+..
+.. http://creativecommons.org/licenses/by/4.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=========================================================
+
+==================================================
+Developer Guide for the Federation Gateway Clients
+==================================================
+
+The acumos-fgw-client library provides clients for using the
+public "E5" and private interfaces of the Acumos machine-learning platform's
+Federation Gateway.
+
+This document offers guidance for both client developers and client users
+(developers who want to use the clients in their Java projects).
+
+Maven Dependency
+----------------
+
+The client jar is deployed to these Nexus repositories at the Linux Foundation::
+
+
+       <repository>
+               <id>releases</id>
+               <url>https://nexus.acumos.org/content/repositories/releases</url>
+       </repository>
+
+Use this dependency information, ideally with the latest version number shown in the release notes::
+
+       <dependency>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>acumos-fgw-client</artifactId>
+               <version>2.x.x</version>
+       </dependency>
+       <dependency>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>acumos-fgw-client-config</artifactId>
+               <version>2.x.x</version>
+       </dependency>
+
+Building and Packaging
+----------------------
+
+As of this writing the build (continuous integration) process is fully automated in the Linux Foundation system
+using Gerrit and Jenkins.  This section describes how to perform local builds for development and testing.
+
+Prerequisites
+~~~~~~~~~~~~~
+
+The build and test machine needs the following:
+
+1. Java version 1.8
+2. Maven version 3
+3. Connectivity to Maven Central to download required jars
+
+Use maven to build and package the client jar using this command::
+
+    mvn package
+
+Client Packages
+---------------
+
+The client consists of several Maven sub-projects each defining one or more
+Java packages.
+
+
+acumos-fgw-client-config
+  Dependency::
+       <dependency>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>acumos-fgw-client-config</artifactId>
+               <version>2.x.x-SNAPSHOT</version>
+       </dependency>
+
+  Packages:
+    org.acumos.federation.client.config
+      This contains pure bean classes for specifying TLS (SSL) and authentication
+      parameters to be used by a client.  These beans use Project Lombok for
+      automatic generation of code for their setter, getter, constructor,
+      equals, and hashcode methods.  Their code may be found under
+      src/main/lombok.
+
+acumos-fgw-client-test
+  Dependency::
+       <dependency>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>acumos-fgw-client-test</artifactId>
+               <version>2.x.x-SNAPSHOT</version>
+               <scope>test</scope>
+       </dependency>
+
+  Packages:
+    org.acumos.federation.client.test
+      This contains classes for mocking out client responses in junit testing
+      in order to test applications using the clients (such as the Federation
+      Gateway itself) as well as test key- and trust-store files for using the
+      clients to test servers supporting the REST APIs.  It also contains
+      convenience routines for generating configuration beans using those
+      key- and trust-store files and for mapping single quotes to double quotes
+      for writing JSON strings in Java code with a minimum of backslashes.
+
+acumos-fgw-client
+  Dependency::
+       <dependency>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>acumos-fgw-client</artifactId>
+               <version>2.x.x-SNAPSHOT</version>
+       </dependency>
+
+  Packages:
+    org.acumos.federation.client.data
+      This contains pure bean classes for messages sent between the clients
+      and the Federation Gateway server that are unique to those APIs.
+      These beans use Project Lombok for automatic generation of code
+      for their setter, getter, constructor, equals, and hashcode methods.
+      Their code may be found under src/main/lombok.
+    org.acumos.federation.client
+      This contains the actual client code, itself, consisting of a ClientBase
+      class used as the common superclass for both interfaces, and
+      FederationClient and GatewayClient for the public "E5" and private
+      interfaces, respectively.
+
+Client Usage Example
+--------------------
+
+A Java class named "ClientDemo" demonstrates use of the clients.
+Please browse for this file in the client project test area using this link:
+`ClientDemo.java <https://gerrit.acumos.org/r/gitweb?p=federation.git;a=blob;f=acumos-fgw-client/src/test/java/org/acumos/federation/client/ClientDemo.java;hb=refs/heads/master>`_.
index ef6778c..38178e1 100644 (file)
@@ -1,7 +1,7 @@
 .. ===============LICENSE_START=======================================================
 .. Acumos CC-BY-4.0
 .. ===================================================================================
-.. 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 documentation file is distributed by AT&T and Tech Mahindra
 .. under the Creative Commons Attribution 4.0 International License (the "License");
 Federation Gateway Configuration Guide
 ======================================
 
-The Acumos Federation Gateway is configured by setting properties using the
+The Acumos Federation Gateway Server is configured by setting properties using the
 SPRING_APPLICATION_JSON environment variable.  See the Spring-Boot documentation
 on Externalized Configuration for information on how the
 SPRING_APPLICATION_JSON environment variable is parsed and on other methods for
 setting configuration property values.
 
-Most of the configuration properties for the Acumos Federation Gateway always
-apply, but some are selectively enabled by others.  The conditionally enabled
-configuration properties are listed, below, in separate sections, grouped by
-the conditions that activate them.
-
-General Configuration Properties
---------------------------------
-
-The following configuration properties are always enabled:
+Configuration Properties
+------------------------
+
+Example (with syntactically valid but completely made up values)::
+  export SPRING_APPLICATION_JSON='
+    "federation.address": "externalname.example.com",
+    "federation.server.port": 8443,
+    "federation.ssl": {
+      "key-store": "/somedirectory/externalname.jks",
+      "key-store-password": "some value 1"
+    },
+    "local": {
+      "address": "internalname.example.com",
+      "server": {
+        "port": 9443
+      },
+      "ssl.key-store": "classpath:internalname.jks",
+      "ssl.key-store-password": "some value 2"
+    },
+    "cdms.client": {
+      "url": "http://cdshost:8080/ccds",
+      "username": "theuser",
+      "password": "some value 3",
+    },
+    "docker": {
+      "registry-url": "myregistry:10443",
+      "registry-username": "myregistryuser",
+      "registry-password": "some value 4",
+      "registry-email": "someuser@somehost",
+    },
+    "nexus": {
+      "url": "https://mynexus:7443/repository/myrepo",
+      "username": "nexususer",
+      "password": "nexuspass",
+      "nexus.group-id": "myorg"
+    }
+  }'
+
+Note that::
+  { "a.b": "x", "a.c": "y" }
+and::
+  { "a": { "b": "x", "c": "y" }}
+are equivalent, in SPRING_APPLICATION_JSON.
 
 federation.address
-  Required.  FQDN or IP address.
+  Optional.  FQDN or IP address.
 
   This specifies which IP interface, on the federation host machine, listens
-  for incoming requests from peers.  A value of 0.0.0.0 specifies listening
+  for incoming requests from peers.  Defaults to listening
   on all interfaces.
 
-federation.instance
-  Required.  Allowed values: "gateway" and "adapter".
-
-  This property controls the mode of operation of federation.
-
-  In "gateway" mode, federation uses the common data service to store
-  metadata, and federation polls its peers for solutions matching its
-  subscriptions.  In this mode, the spring.profiles.active property
-  controls how artifact and document content is stored.
-
-  In "adapter" mode, federation does not process subscriptions and
-  uses flat files to store metadata, artifacts, and documents.
-
-federation.operator
-  Required.
-
-  User ID for importing solutions, for subscriptions that do not
-  have an associated user ID of their own.
-
 federation.registration.enabled
   Optional.  Default False.
 
@@ -73,8 +88,8 @@ federation.server.port
   This specifies which TCP/IP port, on the interface(s) specified by
   federation.address, listens for incoming requests from peers.
 
-federation.ssl.client-auth
-  Optional.  Allowed values "need", "request", "none".  Default "need".
+federation.client-auth
+  Optional.  Allowed values "NEED", "WANT", "NONE".  Default "WANT".
 
   This specifies whether to request or require 2-way TLS authentication
   of incoming connections from peers.
@@ -114,11 +129,11 @@ federation.ssl.trust-store-type
   Allowed values: JKS or PKCS12.
 
 local.address
-  Required.  FQDN or IP address.
+  Optional.  FQDN or IP address.
 
   This specifies which IP interface, on the federation host machine, listens
   for incoming requests from the local Acumos marketplace portal (the portal).
-  A value of 0.0.0.0 specifies listening on all interfaces.
+  Defaults to listening on all interfaces.
 
 local.server.port
   Required.
@@ -126,8 +141,8 @@ local.server.port
   This specifies which TCP/IP port, on the interface(s) specified by
   federation.address, listens for incoming requests from the portal.
 
-local.ssl.client-auth
-  Optional.  Allowed values "need", "request", "none".  Default "need".
+local.client-auth
+  Optional.  Allowed values "NEED", "WANT", "NONE".  Default "WANT".
 
   This specifies whether to request or require 2-way TLS authentication
   of incoming connections from the portal.
@@ -168,36 +183,6 @@ local.ssl.trust-store-type
 
   This specifies the format of the trust store file.
 
-task.scheduler-pool-size
-  Optional.  Default 100.
-
-  This is the thread pool size for the gateway scheduler.
-
-task.executor-core-pool-size
-  Optional.  Default 20.
-
-  This is the core size of the executor thread pool.
-
-task.executor-max-pool-size
-  Optional.  Default 100.
-
-  This is the maximum size of the executor thread pool.
-
-task.executor-queue-capacity
-  Optional.  Default 50.
-
-  This is the maximum capacity of the executor queue.
-
-Gateway Configuration Properties
---------------------------------
-
-The following configuration properties are enabled when federation.instance is "gateway":
-
-catalog.catalogs-selector
-  Optional.  Default { "accessTypeCode": "PB" }
-
-  A JSON string giving filters to be used when searching for catalogs.
-
 cdms.client.url
   Required.
 
@@ -213,32 +198,12 @@ cdms.client.password
 
   Password for authenticating to the common data service.
 
-cdms.client.page-size
-  Optional.  Default 100
-
-  The number of responses, per "page" to request from the common data service.
-
 peer.jobchecker.interval
   Optional.  Default 400.
 
   The time, in seconds, between checking for changes to the set of active
   subscriptions.
 
-spring.profiles.active
-  Optional.  Default empty.
-
-  If the set of active profiles contains "local", then flat files are used
-  to store artifacts and documents.  If it doesn't and federation.instance is
-  "gateway", artifacts that are Docker images are stored in the Docker
-  Registry and documents and other artifacts are stored in the Nexus
-  repository.
-
-Repository Configuration Properties
------------------------------------
-
-The following configuration properties are enabled when federation.instance
-is "gateway" and spring.profiles.active does not contain "local":
-
 docker.api-version
   Optional.
 
@@ -323,46 +288,6 @@ nexus.name-separator
   Separator between components of the path prefix within the Nexus repository.
   The prefix is of the form groupid separator solutionid separator revisionid.
 
-File-base Metadata Store Configuration Properties
--------------------------------------------------
-
-The following configuration properties are enabled when federation.instance
-is "adapter":
-
-catalog-local.source
-  Required.
-
-  Path to file containing solution metadata available to remote peers.
-  This file is a JSON array of Solution metadata.
-
-catalog-local.catalogs
-  Required.
-
-  Path to file containing catalog metadata available to remote peers.
-  This file is a JSON array of Catalog metadata.
-
-codes-local.source
-  Required.
-
-  Path to file containing code mapping data available to remote peers.
-  This file is a JSON object with keys "ARTIFACT_TYPE", and "PEER_STATUS".
-  The values corresponding to these keys are arrays of code/name pairs, for
-  example, { "ARTIFACT_TYPE": [{ "code": "DI", "name": "DockerImage" }, ... }
-
-peers-local.source
-  Required
-
-  Path to file containing peer metadata.
-  This file is a JSON array of Peer metadata.
-
-peer-local.interval
-  Optional.  Default 60.
-
-  The time, in seconds, between checks for updates to the files specified
-  by the catalog-local.source, catalog-local.catalogs, codes-local.source,
-  and peers-local.source files.
-
-
 =========================================
 Federation Gateway Certificate Generation
 =========================================
index 7cfe658..2395273 100644 (file)
@@ -1,7 +1,7 @@
 .. ===============LICENSE_START=======================================================
 .. Acumos CC-BY-4.0
 .. ===================================================================================
-.. Copyright (C) 2017-2018 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+.. Copyright (C) 2017-2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
 .. ===================================================================================
 .. This Acumos documentation file is distributed by AT&T and Tech Mahindra
 .. under the Creative Commons Attribution 4.0 International License (the "License");
@@ -16,9 +16,9 @@
 .. limitations under the License.
 .. ===============LICENSE_END=========================================================
 
-===============================
-Federation Gateway Design Notes
-===============================
+======================================
+Federation Gateway Server Design Notes
+======================================
 
 The federation gateway is an optional component of an Acumos system whose role
 is to facilitate communication with other Acumos systems (i.e. with their gateways)
@@ -45,11 +45,11 @@ The public "E5" interface
 
 The federation (public) interface is also known in the Acumos project as the E5 interface.
 This is a public, REST-based API specification: any system that decides to federate needs to implement it.
-This interface assumes a pull-based mechanism. 
+This interface assumes a pull-based mechanism.
 As such, only the ‘server’ side is defined by E5.
 
 The client side is based on a set of subscriptions, where each subscription defines a set of solutions
-the client is interested in, through a selector (see :ref:`selecting`), and employs periodic polling to detect new material.
+the client is interested in, through a list of one or more catalogs, and employs periodic polling to detect new material.
 This interface defines no shared state, nothing to synchronize; all responsibility resides with the interested party.
 Requires a pre-provisioned peer on the server side, and uses both client and server authentication (CA based),
 principal to certificate matching.
@@ -61,9 +61,6 @@ The private interface
 The private (local) interface is system specific, because a localized mapping of information must be done.
 In Acumos, this includes interactions with the Common Data Service and Portal components and represents
 is a one-to-one mapping of solution information and related artifacts.
-In ONAP, this interacts with the SDC component based on its REST API and
-requires additional processing, for example transforming an Acumos artifact into a set of SDC Asset Artifacts.
-
 
 Federation concepts
 -------------------
@@ -78,7 +75,7 @@ Handshake
 ~~~~~~~~~
 
 Establishment of a peer relationship (known as a handshake) is done by out-of-band information exchange
-to obtain and share certificates.  Site administrators with adequate permissions exchange required information: 
+to obtain and share certificates.  Site administrators with adequate permissions exchange required information:
 the E5 REST endpoint coordinates and the expected principal info.  They then proceed with local peer provisioning
 through the Acumos Portal federation administration page.
 
@@ -86,18 +83,16 @@ Subscriptions
 ~~~~~~~~~~~~~
 
 A federation subscription defines which models an Acumos system is interested in importing from a peer.
-The subscription is primarily a selector over a peer’s catalog, and can support different scopes,
-ranging from pinpointing one particular solution to all available solutions.
+The subscription is primarily list of catalogs.
 Subscriptions are subject to policies in the peer regarding which models are exposed to whom.
-Current options on a subscription include the refresh period, 
-and full (copy everything) vs. by reference (no artifact content is transferred).
+Current options on a subscription include the refresh period.
 
 Federating models
 ~~~~~~~~~~~~~~~~~
 
 The federation gateway behavior is driven by the peer and subscription information provisioned
 in the CDS. Through the local interface API other components can trigger gateway
-behavior, i.e. trigger interactions with peers. 
+behavior, i.e. trigger interactions with peers.
 The peer information represents all other Acumos systems (or other through adapters) this system
 has agreed to communicate/exchange information with. The 'handshake' procedure by which two systems
 agree to communicate and provision the required information can take place 'out-of-band' (email etc.
@@ -114,15 +109,13 @@ A subscription towards a peer represents a subset of that peer's model set that
 The subscription information is there to drive the behavior of the federation gateway (which does
 the actual peer polling and local provisioning of the retrieved information); no subscription
 information is shared between peers. An Acumos instance can have multiple subscriptions towards another
-peer. A subscription can range from one specific model to all the models a peer exposes (with any
-combination of model level selection criteria in between). A subscription further specifies
-options such as the frequency with each the federation gateway should check for updates, how much
-model information should be retrieved every time,etc.
+peer.
+A subscription further specifies
+options such as the frequency with each the federation gateway should check for updates, etc.
 
 It is important to notice that the federation gateway mechanisms for model information exchange
 does not impose an overall peer organization/deployment architecture: tree like structures, fully or sparse
-connected graphs, etc are all possible.
-
+connected graphs, etc. are all possible.
 
 Federation mechanisms
 ---------------------
@@ -146,7 +139,6 @@ In addition to the model information exchange APIs the federation gateway offers
 - in-band registration
 - peer information sharing
 
-
 Dependencies
 ------------
 
index 78c3a55..0d3b773 100644 (file)
@@ -41,7 +41,7 @@ Use below maven command to build and package the gateway service into a single j
 Development and Local Testing
 -----------------------------
 
-This section provides information for developing and testing the federaton gateway locally.
+This section provides information for developing and testing the federation gateway locally.
 We will run two instances of the gateway to depict two instance of Acumos federated to each other.
 In below scenario, we are going to run Acumos A and Acumos B for testing locally.
 
@@ -53,7 +53,7 @@ Start two microservice instances for development and testing as follows, with th
     java -Djavax.net.ssl.trustStore=src/test/resources/acumosTrustStore.jks \
          -Djavax.net.ssl.trustStorePassword=acumos \
          -jar target/gateway-1.x.y-SNAPSHOT.jar \
-         --spring.profiles.active="default,acumosa" 
+         --spring.profiles.active="default,acumosa"
 
     java -Djavax.net.ssl.trustStore=src/test/resources/acumosTrustStore.jks \
          -Djavax.net.ssl.trustStorePassword=acumos \
@@ -81,7 +81,11 @@ API
 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:
+
+Online documentation of the API is available on each interface at
+/swagger-ui.html.
+
+The following endpoints are defined on the public "E5" interface:
 
 * /catalogs
 
index efe6ca9..f4b5e8d 100644 (file)
@@ -1,7 +1,7 @@
 .. ===============LICENSE_START=======================================================
 .. Acumos CC-BY-4.0
 .. ===================================================================================
-.. Copyright (C) 2017-2018 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+.. Copyright (C) 2017-2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
 .. ===================================================================================
 .. This Acumos documentation file is distributed by AT&T and Tech Mahindra
 .. under the Creative Commons Attribution 4.0 International License (the "License");
@@ -19,7 +19,7 @@
 ==================
 Federation Gateway
 ==================
-    
+
 .. toctree::
        :maxdepth: 2
 
@@ -29,4 +29,5 @@ Federation Gateway
        developer-guide.rst
        selectors.rst
        config.rst
+       client.rst
        release-notes.rst
index c8180c8..9590016 100644 (file)
@@ -27,12 +27,17 @@ The goal was to have a mechanism that provides great flexibility when designing
 The Gateway feature does not define how multiple Acumos instances are to be interconnected
 or what roles they play.
 
-Like many other system components, the Gateway is implemented as a server that listens 
+Like many other system components, the Gateway is implemented as a server that listens
 for requests on a REST API.  The Gateway provides two interfaces, both using REST:
 
 * Public: towards peers (also known as the "E5" interface)
 * Private: changes between gateway and different adapter implementations
 
+The Gateway feature is delivered as a docker image containing the Federation
+Gateway server, a Java library containing the client implementations for the
+two interfaces, and a Java library containing a unit test tool for simulating
+responses to client requests.
+
 Architecture
 ------------
 
@@ -46,7 +51,7 @@ other Acumos features.  All communication is secured by use of client and server
 Developer Resources
 -------------------
 The source is available from the Linux Foundation Gerrit server:
+
     `<https://gerrit.acumos.org/r/gitweb?p=federation.git;a=summary>`_
 
 The build (CI) jobs are in the Linux Foundation Jenkins server:
index dce63b0..9bb2f72 100644 (file)
@@ -21,7 +21,59 @@ 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. 
+The image name is "federation-gateway" and the tag is a version string as shown below.
+
+Version 2.3.0, 2019-06-14
+-------------------------
+* Publish E5 Federation client library (`ACUMOS-2760 <https://jira.acumos.org/browse/ACUMOS-2760>`_)
+
+  3 new sub-projects are introduced, in addition to the existing "gateway" sub-project.
+  * "acumos-fgw-client-config" contains bean classes used to specify properties
+    of a client's connection to its server, including basic authentication and
+    TLS (SSL) related properties.
+
+  * "acumos-fgw-client-test" contains classes for providing mock responses to
+    a client for testing applications that make calls to a server, as well as
+    dummy key store and trust store files to enable a client to be used to
+    test a server.
+
+  * "acumos-fgw-client" contains implementations of clients for both the
+    external "E5" and private interfaces to the Acumos Federation Gateway
+    as well as bean classes for the JSON wire formats used by those interfaces.
+
+  The existing "gateway" project is modified to use the client subproject when
+  making requests to a peer Acumos instance, when sending or receiving
+  artifacts from the Nexus server, and for creating the rest template used
+  to communicate with CDS.
+
+* Access to the Swagger API is fixed and now gives responses appropriate to
+  the interface being queried (external "E5" or private).
+
+* Some configuration is simplified.
+  * The federation.ssl.client-auth configuration parameter is now named
+    federation.client-auth and defaults to WANT, enabling access to the
+    Swagger specification on the external "E5" interface without requiring
+    a client certificate.  Attempts to access the REST API endpoints without
+    providing a client certificate will return a 403 Forbidden error.
+  * The local.ssl.client-auth configuration parameter is now named
+    local.client-auth and defaults to WANT, enabling access to the
+    Swagger specification on the private interface without requiring
+    a client certificate.  Attempts to access the REST API endpoints without
+    providing a client certificate will return a 403 Forbidden error.
+  * The federation.registration.enabled configuration parameter is now named
+    federation.registration-enabled.  It still defaults to False.
+  * The federation.instance configuration parameter no longer needs to be set to
+    "gateway" and no longer has any effect.
+  * The value "local" in the spring.profiles.active configuration parameter no
+    longer has any effect.
+  * The catalog.catalogs-selector configuration parameter no longer has any effect.
+  * The various task.* configuration parameters no longer have any effect.
+  * The cdms.client.page-size configuration parameter no longer has any effect.
+  * The catalog-local.source, catalog-local.catalogs, codes-local.source,
+    peers-local.source, and peer-local.interval configuration parameters no
+    longer have any effect.
+
+* Documentation is updated to reflect these changes.
 
 Version 2.2.0, 2019-04-16
 -------------------------
@@ -33,7 +85,7 @@ 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:
+  public and private interfaces:
 
   * When listing solutions, the optional selector query parameter is replaced
     by a required catalogId query parameter
@@ -164,8 +216,8 @@ Version 1.17.0, 2018-08-14
 * Add revision document federation (`ACUMOS-1606 <https://jira.acumos.org/browse/ACUMOS-1606>`_)
 * Add tag federation (`ACUMOS-1544 <https://jira.acumos.org/browse/ACUMOS-1544>`_)
 * Fix authorship federation (`ACUMOS-626 <https://jira.acumos.org/browse/ACUMOS-626>`_)
-* The federation API for access to artifact and document content access have changed 
-  to /solutions/{solutionId}/revisions/{revisionId}/artifacts/{artifactId}/content 
+* The federation API for access to artifact and document content access have changed
+  to /solutions/{solutionId}/revisions/{revisionId}/artifacts/{artifactId}/content
   and /solutions/{solutionId}/revisions/{revisionId}/documents/{documentId}/content
 
 Version 1.16.1, 2018-08-08
diff --git a/gateway/.gitignore b/gateway/.gitignore
deleted file mode 100644 (file)
index c3faa9b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/.classpath
-/.project
-/.settings/
-/debug-logs
diff --git a/gateway/README.md b/gateway/README.md
new file mode 100644 (file)
index 0000000..d88febd
--- /dev/null
@@ -0,0 +1,17 @@
+# Acumos Federation Gateway Server
+
+This sub-project contains classes implementing the Acumos Federation Gateway server.
+
+Please see the documentation in the parent project's "docs" folder.
+
+## License
+
+Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+Acumos 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.
index c4ed98f..2488ab9 100755 (executable)
@@ -8,13 +8,13 @@
 # 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.
 
-#java -Djavax.net.ssl.trustStore=src/test/resources/acumosTrustStore.jks -Djavax.net.ssl.trustStorePassword=acumos -Djavax.net.debug=all -jar target/federated-gateway-1.0.0-SNAPSHOT.jar --spring.profiles.active="default,acumosa" 
-java -Djavax.net.ssl.trustStore=src/test/resources/acumosTrustStore.jks -Djavax.net.ssl.trustStorePassword=acumos -Djava.security.egd=file:/dev/./urandom -jar target/gateway-1.0.0-SNAPSHOT.jar --spring.profiles.active="default,acumosa" 
+#java -Djavax.net.ssl.trustStore=src/test/resources/acumosTrustStore.jks -Djavax.net.ssl.trustStorePassword=acumos -Djavax.net.debug=all -jar target/federated-gateway-1.0.0-SNAPSHOT.jar --spring.profiles.active="default,acumosa"
+java -Djavax.net.ssl.trustStore=src/test/resources/acumosTrustStore.jks -Djavax.net.ssl.trustStorePassword=acumos -Djava.security.egd=file:/dev/./urandom -jar target/gateway-1.0.0-SNAPSHOT.jar --spring.profiles.active="default,acumosa"
index 121e8a5..0f728c2 100644 (file)
@@ -21,6 +21,6 @@ local.ssl.key-password = acumosa
 local.ssl.trust-store = classpath:acumosTrustStore.jks
 local.ssl.trust-store-password = acumos
 
-#replace 
+#replace
 peersLocal.source=classpath:/acumosa-peers.json
 catalogLocal.source=classpath:/acumosa-catalog.json
diff --git a/gateway/application-adapter.properties b/gateway/application-adapter.properties
deleted file mode 100644 (file)
index 0612ebd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# REST endpoint configuration; i.e., where this server listens
-server.port=8086
-
-#Instance of this component could be gateway or adapter
-#Based on the value configured, the behavior of this instance will vary.
-federation.instance=adapter
-federation.instance.name=ONAP
-
-#local config
-peersLocal.sourceUri=file:///{path_to_peers_local}
index d037af0..1dcd687 100644 (file)
@@ -39,7 +39,7 @@ docker.registryUsername = snr_acumos_model_rw
 docker.registryPassword = password
 docker.registryEmail =
 
-#replace 
+#replace
 #peersLocal.source=file:///home/jora/src/acumos/gerrit/federation/gateway/src/test/resources/acumosr-test-peers.json
 #catalogLocal.source=file:///home/jora/src/acumos/gerrit/federation/gateway/src/test/resources/acumosr-test-catalog.json
 
diff --git a/gateway/application-onap.properties b/gateway/application-onap.properties
deleted file mode 100644 (file)
index e81ca6d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#onap
-onap.sdcUri=http://Test:123456@135.21.125.105:8080#demo
-onap.sdcRootPath=/sdc/v1/catalog/
index cc77c69..f46bc4a 100644 (file)
@@ -3,7 +3,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");
        limitations under the License.
        ===============LICENSE_END=========================================================
        ]]>-->
-<project
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
-       xmlns="http://maven.apache.org/POM/4.0.0"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.acumos.federation</groupId>
+               <artifactId>federation-parent</artifactId>
+               <version>0</version>
+       </parent>
        <groupId>org.acumos.federation</groupId>
        <artifactId>gateway</artifactId>
-       <version>2.2.0-SNAPSHOT</version>
+       <version>2.3.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.4.RELEASE</version>
-               <!-- silence warning about parent relative path -->
-               <relativePath />
-       </parent>
-
+       <description>Federated Acumos Interface for inter-acumos communication</description>
        <properties>
-               <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-               <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+               <!-- skip the deploy-jar-to-nexus step -->
+               <maven.install.skip>true</maven.install.skip>
+               <maven.deploy.skip>true</maven.deploy.skip>
                <!-- Stand-alone RESTFul application -->
                <start-class>org.acumos.federation.gateway.Application</start-class>
-               <!-- Jenkins invokes mvn with argument -Dbuild.number=${BUILD_NUMBER} -->
-               <build.number>0</build.number>
-               <skipTests>false</skipTests>
-               <!-- dependencies versions -->
-               <logback.version>1.2.3</logback.version>
-               <springfox.version>2.7.0</springfox.version>
+               <!-- dependencies version -->
+               <acumos-fgw-client.version>${project.version}</acumos-fgw-client.version>
+               <docker-java.version>3.1.2</docker-java.version>
+               <springfox.version>2.9.2</springfox.version>
+               <guava.version>20.0</guava.version>
                <!-- Not supplied to all jobs; e.g., Javadoc -->
                <docker.pull.registry>nexus3.acumos.org:10001</docker.pull.registry>
                <!-- Supplied by Jenkins -->
                <docker.push.registry>${env.NEXUS3_PUSH_REGISTRY}</docker.push.registry>
        </properties>
-
-       <!-- Some dependencies are specific to Acumos, but this POM defines no repositories 
-               section. The Jenkins server specifies Acumos repositories. Developers should 
-               ensure their ~/.m2/settings.xml file has the following URLs in both the repositories 
-               and pluginRepositories sections or in a profile: https://nexus.acumos.org/content/repositories/snapshots/ 
-               https://nexus.acumos.org/content/repositories/releases/ -->
-
+       <!-- Dependency/plugin versions are inherited from parent pom -->
        <dependencies>
                <dependency>
-                       <groupId>org.acumos.acumos-nexus-client</groupId>
-                       <artifactId>acumos-nexus-client</artifactId>
-                       <version>2.2.1</version>
+                       <groupId>org.acumos.federation</groupId>
+                       <artifactId>acumos-fgw-client</artifactId>
+                       <version>${acumos-fgw-client.version}</version>
                </dependency>
                <dependency>
-                       <groupId>org.acumos.common-dataservice</groupId>
-                       <artifactId>cmn-data-svc-client</artifactId>
-                       <version>2.2.1</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.json</groupId>
-                       <artifactId>json</artifactId>
-                       <!-- Override Spring-boot choice -->
-                       <version>20160212</version><!--$NO-MVN-MAN-VER$ -->
+                       <!-- resolve conflicting transitive dependencies -->
+                       <groupId>com.google.guava</groupId>
+                       <artifactId>guava</artifactId>
+                       <version>${guava.version}</version>
                </dependency>
                <dependency>
-                       <groupId>org.slf4j</groupId>
-                       <artifactId>slf4j-api</artifactId>
-                       <!-- spring sets the <version>${slf4j.version}</version> -->
+                       <groupId>com.github.docker-java</groupId>
+                       <artifactId>docker-java</artifactId>
+                       <version>${docker-java.version}</version>
                </dependency>
                <dependency>
-                       <groupId>ch.qos.logback</groupId>
-                       <artifactId>logback-classic</artifactId>
-                       <!-- spring sets the <version>${logback.version}</version> -->
+                       <groupId>io.springfox</groupId>
+                       <artifactId>springfox-swagger2</artifactId>
+                       <version>${springfox.version}</version>
                </dependency>
                <dependency>
-                       <groupId>ch.qos.logback</groupId>
-                       <artifactId>logback-core</artifactId>
-                       <!-- spring sets the <version>${logback.version}</version> -->
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter</artifactId>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-starter-security</artifactId>
-                       <!-- spring sets the ${spring.boot.starter.security.version}</version> -->
+                       <artifactId>spring-boot-starter-json</artifactId>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-web</artifactId>
-                       <!-- spring sets the <version>${spring.boot.starter.web.version}</version> -->
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-configuration-processor</artifactId>
-                       <!-- spring sets the <version>${spring.boot.configuration.processor.version}</version> -->
-                       <optional>true</optional>
-               </dependency>
-               <dependency>
-                       <groupId>org.glassfish.jersey.inject</groupId>
-                       <artifactId>jersey-hk2</artifactId>
                </dependency>
                <dependency>
-                       <groupId>com.google.guava</groupId>
-                       <artifactId>guava</artifactId>
-                       <version>19.0</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.apache.httpcomponents</groupId>
-                       <artifactId>httpclient</artifactId>
-                       <!-- spring sets the <version>4.5</version> -->
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework.shell</groupId>
-                       <artifactId>spring-shell</artifactId>
-                       <version>1.2.0.RELEASE</version>
-               </dependency>
-               <dependency>
-                       <groupId>io.springfox</groupId>
-                       <artifactId>springfox-swagger2</artifactId>
-                       <version>${springfox.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>io.springfox</groupId>
-                       <artifactId>springfox-swagger-ui</artifactId>
-                       <version>${springfox.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>javax.inject</groupId>
-                       <artifactId>javax.inject</artifactId>
-                       <version>1</version>
-               </dependency>
-               <dependency>
-                       <groupId>io.jsonwebtoken</groupId>
-                       <artifactId>jjwt</artifactId>
-                       <version>0.6.0</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.python</groupId>
-                       <artifactId>jython-standalone</artifactId>
-                       <version>2.7.1-rc3</version>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-security</artifactId>
                </dependency>
+               <!-- Compile time only dependencies -->
                <dependency>
-                       <groupId>com.fasterxml.jackson.core</groupId>
-                       <artifactId>jackson-core</artifactId>
-                       <!-- spring sets the <version>2.9.7</version> -->
+                       <groupId>org.projectlombok</groupId>
+                       <artifactId>lombok</artifactId>
+                       <scope>provided</scope>
                </dependency>
+               <!-- Test dependencies -->
                <dependency>
-                       <groupId>com.fasterxml.jackson.datatype</groupId>
-                       <artifactId>jackson-datatype-jsr310</artifactId>
+                       <groupId>org.acumos.federation</groupId>
+                       <artifactId>acumos-fgw-client-test</artifactId>
+                       <scope>test</scope>
                </dependency>
-
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
-                       <!-- spring sets the <version>3.8.1</version> -->
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>commons-cli</groupId>
-                       <artifactId>commons-cli</artifactId>
-                       <version>1.2</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.apache.commons</groupId>
-                       <artifactId>commons-lang3</artifactId>
-                       <!-- spring sets the <version>3.6</version> -->
-               </dependency>
-               <dependency>
-                       <groupId>org.apache.commons</groupId>
-                       <artifactId>commons-compress</artifactId>
-                       <version>1.5</version>
-               </dependency>
-               <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
-               <dependency>
-                       <groupId>commons-beanutils</groupId>
-                       <artifactId>commons-beanutils</artifactId>
-                       <version>1.9.3</version>
-               </dependency>
-               <dependency>
-                       <groupId>com.github.docker-java</groupId>
-                       <artifactId>docker-java</artifactId>
-                       <version>3.0.14</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.aspectj</groupId>
-                       <artifactId>aspectjweaver</artifactId>
-                       <!-- spring sets the <version>1.8.13</version> -->
-               </dependency>
-               <dependency>
-                       <groupId>org.assertj</groupId>
-                       <artifactId>assertj-core</artifactId>
-                       <!-- spring sets the <version>3.8.0</version> -->
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.mockito</groupId>
-                       <artifactId>mockito-core</artifactId>
-                       <!-- spring sets the <version>2.21.0</version> -->
                        <scope>test</scope>
                </dependency>
+               <!-- Test runtime dependencies -->
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-test</artifactId>
-                       <!-- spring sets the <version>2.1.2.RELEASE</version> -->
                        <exclusions>
-                               <!-- silence warning about duplicate JSON class -->
                                <exclusion>
                                        <groupId>com.vaadin.external.google</groupId>
                                        <artifactId>android-json</artifactId>
                        <scope>test</scope>
                </dependency>
        </dependencies>
-
        <build>
                <plugins>
                        <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-compiler-plugin</artifactId>
-                               <!-- spring sets the <version>3.0</version> -->
-                               <configuration>
-                                       <source>1.8</source>
-                                       <target>1.8</target>
-                               </configuration>
+                               <groupId>org.projectlombok</groupId>
+                               <artifactId>lombok-maven-plugin</artifactId>
                        </plugin>
-                       <!-- Add the build number to the jar manifest. Spring-Boot uses a complex 
-                               packaging process that makes access to the original Manifest.MF very difficult. 
-                               However, Java provides access to the implementation version for a package, 
-                               so cram the build number into there. -->
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-jar-plugin</artifactId>
                                                </manifestEntries>
                                        </archive>
                                </configuration>
-                               <executions>
-                                       <execution>
-                                               <goals>
-                                                       <goal>test-jar</goal>
-                                               </goals>
-                                       </execution>
-                               </executions>
                        </plugin>
                        <plugin>
                                <groupId>org.springframework.boot</groupId>
                                        </execution>
                                </executions>
                        </plugin>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-dependency-plugin</artifactId>
-                               <!-- spring sets the <version>2.10</version> -->
-                               <executions>
-                                       <execution>
-                                               <id>copy-dependencies</id>
-                                               <phase>package</phase>
-                                               <goals>
-                                                       <goal>copy-dependencies</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <outputDirectory>${project.build.directory}/deps</outputDirectory>
-                                                       <overWriteReleases>true</overWriteReleases>
-                                                       <overWriteSnapshots>true</overWriteSnapshots>
-                                                       <overWriteIfNewer>true</overWriteIfNewer>
-                                               </configuration>
-                                       </execution>
-                               </executions>
-                       </plugin>
-                       <!-- No need to deploy Spring super-jar -->
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-deploy-plugin</artifactId>
-                               <!-- Spring sets the <version>2.8</version> -->
                                <configuration>
                                        <skip>true</skip>
                                </configuration>
                        <plugin>
                                <groupId>io.fabric8</groupId>
                                <artifactId>docker-maven-plugin</artifactId>
-                               <version>0.23.0</version>
+                               <version>0.28.0</version>
                                <configuration>
                                        <verbose>true</verbose>
-                                       <dockerHost>${docker.host.url}</dockerHost>
-                                       <registry>${docker.registry.url}</registry>
-                                       <authConfig>
-                                               <username>${docker.registry.login}</username>
-                                               <password>${docker.registry.password}</password>
-                                       </authConfig>
+                                       <pullRegistry>${docker.pull.registry}</pullRegistry>
+                                       <pushRegistry>${docker.push.registry}</pushRegistry>
                                        <images>
                                                <image>
-                                                       <!-- Specify a tag to avoid default tag "latest" -->
                                                        <name>federation-gateway:${project.version}</name>
                                                        <build>
                                                                <from>openjdk:8-jre-slim</from>
                                                                <tags>
-                                                                       <!-- Add tag with build number -->
                                                                        <tag>${project.version}-b${build.number}</tag>
                                                                </tags>
                                                                <assembly>
-                                                                       <inline>
-                                                                               <files>
-                                                                                       <file>
-                                                                                               <source>target/${project.artifactId}-${project.version}.${project.packaging}</source>
-                                                                                               <outputDirectory />
-                                                                                       </file>
-                                                                               </files>
-                                                                       </inline>
+                                                                       <descriptorRef>artifact</descriptorRef>
                                                                </assembly>
                                                                <runCmds>
-                                                                       <!-- Ensure logs dir exists and is world writable -->
                                                                        <runCmd>mkdir /maven/logs</runCmd>
                                                                        <runCmd>chmod -R 777 /maven</runCmd>
                                                                </runCmds>
-                                                               <!-- This is the same CMD used in a Dockerfile -->
                                                                <cmd>
-                                                                       <!-- CDATA prevents Eclipse formatter from breaking line -->
                                                                        <shell><![CDATA[cd /maven; java -Xms256m -Xmx2g -Djava.security.egd=file:/dev/./urandom -jar ${project.artifactId}-${project.version}.${project.packaging}]]></shell>
                                                                </cmd>
                                                        </build>
                                                </image>
-                                               <image>
-                                                       <name>federation-gateway-test:${project.version}</name>
-                                                       <build>
-                                                               <from>openjdk:8-jre-slim</from>
-                                                               <tags>
-                                                                       <tag>${project.version}-b${build.number}</tag>
-                                                               </tags>
-                                                               <assembly>
-                                                                       <inline>
-                                                                               <files>
-                                                                                       <file>
-                                                                                               <source>target/${project.artifactId}-${project.version}.${project.packaging}.original</source>
-                                                                                               <outputDirectory />
-                                                                                               <!-- <destName>target/${project.artifactId}-${project.version}.${project.packaging}</destName> -->
-                                                                                       </file>
-                                                                                       <file>
-                                                                                               <source>target/${project.artifactId}-${project.version}-tests.${project.packaging}</source>
-                                                                                               <outputDirectory />
-                                                                                       </file>
-                                                                               </files>
-                                                                               <fileSets>
-                                                                                       <fileSet>
-                                                                                               <!-- <directory>${project.build.directory}/deps/</directory> -->
-                                                                                               <directory>target/deps/</directory>
-                                                                                               <outputDirectory>/libs/</outputDirectory>
-                                                                                               <includes>
-                                                                                                       <include>*</include>
-                                                                                               </includes>
-                                                                                               <fileMode>0755</fileMode>
-                                                                                       </fileSet>
-                                                                               </fileSets>
-                                                                       </inline>
-                                                               </assembly>
-                                                               <runCmds>
-                                                                       <!-- Ensure logs dir exists and is world writable -->
-                                                                       <runCmd>mkdir /maven/logs</runCmd>
-                                                                       <runCmd>chmod -R 777 /maven</runCmd>
-                                                               </runCmds>
-                                                               <cmd>
-                                                                       <!-- CDATA prevents Eclipse formatter from breaking line -->
-                                                                       <shell><![CDATA[cd /maven; java -Xms256m -Xmx2g -cp ${project.artifactId}-${project.version}.${project.packaging}.original:${project.artifactId}-${project.version}-tests.${project.packaging}:/libs/* -Djava.security.egd=file:/dev/./urandom org.springframework.boot.loader.PropertiesLauncher]]></shell>
-                                                               </cmd>
-                                                       </build>
-                                               </image>
                                        </images>
                                </configuration>
                                <executions>
                                        </execution>
                                </executions>
                        </plugin>
-                       <!--
-                       <plugin>
-                               <groupId>org.codehaus.mojo</groupId>
-                               <artifactId>license-maven-plugin</artifactId>
-                               <version>1.14</version>
-                               <configuration>
-                                       <licenseName>acumos</licenseName>
-                                       <licenseResolver>${project.baseUri}/src/license</licenseResolver>
-                                       <addJavaLicenseAfterPackage>false</addJavaLicenseAfterPackage>
-                                       <processStartTag>===============LICENSE_START=======================================================</processStartTag>
-                                       <processEndTag>===============LICENSE_END=========================================================</processEndTag>
-                                       <sectionDelimiter>===================================================================================</sectionDelimiter>
-                                       <inceptionYear>2017</inceptionYear>
-                                       <organizationName>AT&amp;T Intellectual Property &amp; Tech
-                                               Mahindra. All rights reserved.</organizationName>
-                                       <projectName>Acumos</projectName>
-                                       <canUpdateCopyright>true</canUpdateCopyright>
-                                       <canUpdateDescription>true</canUpdateDescription>
-                                       <canUpdateLicense>true</canUpdateLicense>
-                                       <emptyLineAfterHeader>true</emptyLineAfterHeader>
-                                       <includes>
-                                               <include>**/*.java</include>
-                                       </includes>
-                               </configuration>
-                               <executions>
-                                       <execution>
-                                               <id>first</id>
-                                               <goals>
-                                                       <goal>update-file-header</goal>
-                                               </goals>
-                                               <phase>process-sources</phase>
-                                       </execution>
-                               </executions>
-                       </plugin>
-                       -->
                        <plugin>
                                <groupId>org.jacoco</groupId>
                                <artifactId>jacoco-maven-plugin</artifactId>
-                               <version>0.7.9</version>
-                               <executions>
-                                       <execution>
-                                               <id>default-prepare-agent</id>
-                                               <goals>
-                                                       <goal>prepare-agent</goal>
-                                               </goals>
-                                       </execution>
-                                       <execution>
-                                               <id>default-report</id>
-                                               <phase>prepare-package</phase>
-                                               <goals>
-                                                       <goal>report</goal>
-                                               </goals>
-                                       </execution>
-                               </executions>
                        </plugin>
                </plugins>
        </build>
index a4d3fc4..d901067 100644 (file)
@@ -2,10 +2,10 @@ 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.
\ No newline at end of file
+limitations under the License.
index a4d3fc4..d901067 100644 (file)
@@ -2,10 +2,10 @@ 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.
\ No newline at end of file
+limitations under the License.
index 36c4443..71a69a0 100644 (file)
@@ -8,9 +8,9 @@
 # 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
index 07429f3..101cf85 100644 (file)
  * ===============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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-
 package org.acumos.federation.gateway;
 
 import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.function.Function;
+import java.util.List;
 
-import org.acumos.federation.gateway.config.FederationConfiguration;
-import org.acumos.federation.gateway.config.LocalConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.boot.Banner;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+
+import org.springframework.beans.factory.BeanInitializationException;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
-import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.Banner;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.FilterType;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+import org.springframework.boot.web.server.Ssl;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+import org.acumos.cds.transport.RestPageRequest;
+import org.acumos.cds.transport.RestPageResponse;
+
+import org.acumos.federation.client.config.TlsConfig;
+
+
 /**
- * 
- * Configuration classes are also Conponents so they are subject to Component scanning.
+ * Main program for the Acumos Federation Gateway Server.
  */
 @SpringBootApplication
-@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,
-               DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
 @EnableConfigurationProperties
-@ComponentScan(basePackages = "org.acumos.federation",
-                                                        useDefaultFilters = false,
-                                                        includeFilters =
-                                                               @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,
-                                                                                                                                                       classes={org.acumos.federation.gateway.config.GatewayConfiguration.class,
-                                                                                                                                                                                        org.acumos.federation.gateway.config.AdapterConfiguration.class}))
+@EnableGlobalMethodSecurity(securedEnabled=true)
+@EnableScheduling
 public class Application {
+       private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-       private static final Logger log = LoggerFactory.getLogger(Application.class);
+       /**
+        * Create instance of application class.  Used by SpringBoot framework.
+        */
+       public Application(){} //NOSONAR
 
        /**
-        * We should be able to swap the LocalConfiguration in the case of adapters.
-        * 
-        * @param args
-        *            Ignored
-        * @throws IOException
-        *             if environment config cannot be parsed
+        * Gather values from multi-page common-dataservice requests.
+        * @param fcn Function to fetch a page of values.
+        * @return All of the values.
         */
-       public static void main(String[] args) throws IOException {
-               checkEnvironmentConfig();
-               SpringApplicationBuilder gatewayBuilder =
-                       new SpringApplicationBuilder(Application.class)
-                                                                                       .bannerMode(Banner.Mode.OFF)
-                                                                                       .web(WebApplicationType.NONE);
-               gatewayBuilder.child(FederationConfiguration.class)
-                                                                                       .bannerMode(Banner.Mode.OFF)
-                                                                                       .web(WebApplicationType.SERVLET)
-                                                                                       .run(args);
-               gatewayBuilder.child(LocalConfiguration.class)
-                                                                                       .bannerMode(Banner.Mode.OFF)
-                                                                                       .web(WebApplicationType.SERVLET)
-                                                                                       .run(args);
+       public static <T> List<T> cdsAll(Function<RestPageRequest, RestPageResponse<T>> fcn) {
+               RestPageRequest request = new RestPageRequest(0, 100);
+               List<T> ret = new ArrayList<>();
+               RestPageResponse<T> response;
+               do {
+                       response = fcn.apply(request);
+                       ret.addAll(response.getContent());
+                       request.setPage(response.getNumber() + 1);
+               } while (!response.isLast());
+               return ret;
+       }
 
+       /**
+        * Configure one of the child servers (Federation and Gateway).
+        *
+        * @param server The server to configure.
+        * @param config The host, port, and TLS the server should use.
+        */
+       public static void configureServer(ConfigurableServletWebServerFactory server, ServerConfig config) {
+               if (config.getServer() != null && config.getServer().getPort() != 0) {
+                       server.setPort(config.getServer().getPort());
+               }
+               if (config.getAddress() != null) {
+                       try {
+                               server.setAddress(InetAddress.getByName(config.getAddress()));
+                       } catch (UnknownHostException uhe) {
+                               throw new BeanInitializationException("Invalid server address", uhe);
+                       }
+               }
+               TlsConfig tls = config.getSsl();
+               if (tls != null) {
+                       Ssl ssl = new Ssl();
+                       ssl.setEnabled(true);
+                       ssl.setProtocol("TLSv1.2");
+                       ssl.setKeyStore(tls.getKeyStore());
+                       ssl.setKeyStorePassword(tls.getKeyStorePassword());
+                       ssl.setKeyAlias(tls.getKeyAlias());
+                       ssl.setKeyStoreType(tls.getKeyStoreType());
+                       ssl.setTrustStore(tls.getTrustStore());
+                       ssl.setTrustStorePassword(tls.getTrustStorePassword());
+                       ssl.setTrustStoreType(tls.getTrustStoreType());
+                       ssl.setClientAuth(config.getClientAuth());
+                       server.setSsl(ssl);
+               }
        }
 
-       private static final String CONFIG_ENV_VAR_NAME = "SPRING_APPLICATION_JSON";
+       @Bean
+       @ConfigurationProperties(prefix="local")
+       ServerConfig local() {
+               return new ServerConfig();
+       }
 
-       private static void checkEnvironmentConfig() throws IOException {
-               final String springApplicationJson = System.getenv(CONFIG_ENV_VAR_NAME);
-               if (springApplicationJson != null && springApplicationJson.contains("{")) {
-                       final ObjectMapper mapper = new ObjectMapper();
-                       // ensure it's valid
-                       mapper.readTree(springApplicationJson);
-                       log.info("main: successfully parsed configuration from environment {}", CONFIG_ENV_VAR_NAME);
+       @Bean
+       @ConfigurationProperties(prefix="federation")
+       FederationConfig federation() {
+               return new FederationConfig();
+       }
+
+       @Bean
+       @ConfigurationProperties(prefix="cdms.client")
+       ServiceConfig cdmsConfig() {
+               return new ServiceConfig();
+       }
+
+       @Bean
+       @ConfigurationProperties(prefix="nexus")
+       NexusConfig nexusConfig() {
+               return new NexusConfig();
+       }
+
+       @Bean
+       @ConfigurationProperties(prefix="docker")
+       DockerConfig dockerConfig() {
+               return new DockerConfig();
+       }
+
+       @Bean
+       Clients clients() {
+               return new Clients();
+       }
+
+       @Bean
+       PeerService peerService() {
+               return new PeerServiceImpl();
+       }
+
+       @Bean
+       ContentService contentService() {
+               return new ContentServiceImpl();
+       }
+
+       @Bean
+       WebSecurityConfigurerAdapter security() {
+               return new Security();
+       }
+
+       @Bean
+       CatalogService catalogService() {
+               return new CatalogServiceImpl();
+       }
+
+       static Docket getApi() {
+               String version = Application.class.getPackage().getImplementationVersion();
+               return new Docket(DocumentationType.SWAGGER_2)
+                   .select()
+                   .apis(RequestHandlerSelectors.basePackage(Application.class.getPackage().getName()))
+                   .paths(PathSelectors.any())
+                   .build()
+                   .apiInfo(
+                       new ApiInfoBuilder()
+                           .title("Acumos Federation Gateway REST API")
+                           .description(
+                               "Provides Model Sharing services for " +
+                               "Acumos.  All service endpoints use " +
+                               "2-way TLS/HTTPS certificate authentication.")
+                           .termsOfServiceUrl("Terms of service")
+                           .contact(new Contact(
+                               "Acumos Dev Team",
+                               "http://acumos.readthedocs.io/en/latest/submodules/federation/docs/",
+                               "noreply@acumos.org"))
+                           .license("Apache 2.0 License")
+                           .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
+                           .version(version == null? "version not available": version)
+                           .build());
+       }
+
+       public static void main(String[] args) throws IOException {
+               String configenv = System.getenv("SPRING_APPLICATION_JSON");
+               if (configenv != null && (new ObjectMapper()).readTree(configenv) != null) {
+                       log.info("Parseable environment configuration found.");
                } else {
-                       log.warn("main: no configuration found in environment {}", CONFIG_ENV_VAR_NAME);
+                       log.warn("No valid environment configuration found.");
                }
+               SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class)
+                   .properties(
+                       "spring.main.allow-bean-definition-overriding=true",
+                       "spring.mvc.async.request-timeout=10m")
+                   .bannerMode(Banner.Mode.OFF)
+                   .web(WebApplicationType.NONE);
+               builder.child(FederationServer.class)
+                   .bannerMode(Banner.Mode.OFF)
+                   .web(WebApplicationType.SERVLET)
+                   .run(args);
+               builder.child(GatewayServer.class)
+                   .bannerMode(Banner.Mode.OFF)
+                   .web(WebApplicationType.SERVLET)
+                   .run(args);
        }
 }
@@ -2,39 +2,47 @@
  * ===============LICENSE_START=======================================================
  * Acumos
  * ===================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * Copyright (C) 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
  * limitations under the License.
  * ===============LICENSE_END=========================================================
  */
-
-package org.acumos.federation.gateway.common;
-
-import java.net.URI;
-
-import org.springframework.web.client.HttpStatusCodeException;
+package org.acumos.federation.gateway;
 
 /**
- * Federation error as explcitly reported by a peer
+ * Exception to abort current processing and reply to the peer with
+ * the specified HTTP response code and message.
  */
-public class PeerException extends FederationException {
+public class BadRequestException extends RuntimeException {
+       private final int code;
 
-       public PeerException(URI theUri, HttpStatusCodeException theCause) {
-               super(theUri, theCause);
+       /**
+        * Exception for when the peer's request is unacceptable.
+        *
+        * @param code The HTTP response code to send.
+        * @param message Text description of the problem.
+        */
+       public BadRequestException(int code, String message) {
+               super(message);
+               this.code = code;
        }
 
-       public PeerException(String theUri, HttpStatusCodeException theCause) {
-               super(theUri, theCause);
+       /**
+        * Get the HTTP response code.
+        *
+        * @return The response code.
+        */
+       public int getCode() {
+               return code;
        }
-
 }
diff --git a/gateway/src/main/java/org/acumos/federation/gateway/CatalogService.java b/gateway/src/main/java/org/acumos/federation/gateway/CatalogService.java
new file mode 100644 (file)
index 0000000..58833bb
--- /dev/null
@@ -0,0 +1,269 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * 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
+ * limitations under the License.
+ * ===============LICENSE_END=========================================================
+ */
+package org.acumos.federation.gateway;
+
+import java.util.List;
+
+import org.acumos.cds.domain.MLPArtifact;
+import org.acumos.cds.domain.MLPCatalog;
+import org.acumos.cds.domain.MLPDocument;
+import org.acumos.cds.domain.MLPRevCatDescription;
+import org.acumos.cds.domain.MLPSolution;
+import org.acumos.cds.domain.MLPSolutionRevision;
+
+/**
+ * API for accessing catalogs and related items.
+ *
+ * Provides methods for finding catalogs, solutions, revisions, artifacts, and
+ * documents, and for checking whether the current peer has access to them.
+ */
+public interface CatalogService {
+       /**
+        * Get a list of all catalogs.
+        *
+        * @return List of catalogs.
+        */
+       public List<MLPCatalog> getAllCatalogs();
+       /**
+        * Get a list of the catalogs visible to the current peer.
+        *
+        * @return List of visible catalogs.
+        */
+       public List<MLPCatalog> getCatalogs();
+       /**
+        * Create a catalog
+        *
+        * @param catalog The catalog
+        */
+       public void createCatalog(MLPCatalog catalog);
+       /**
+        * Add a solution to a catalog
+        *
+        * @param solutionId The ID of the solution.
+        * @param catalogId The ID of the catalog.
+        */
+       public void addSolution(String solutionId, String catalogId);
+       /**
+        * Get a list of the solutions in a catalog.
+        *
+        * @param catalogId The ID of the catalog to search.
+        * @return List of solutions in the catalog.
+        */
+       public List<MLPSolution> getSolutions(String catalogId);
+       /**
+        * Get details of a solution.
+        *
+        * @param solutionId The ID of the solution to retrieve.
+        * @return The solution extended with a list of its revisions.
+        */
+       public MLPSolution getSolution(String solutionId);
+       /**
+        * Create a solution.
+        *
+        * @param solution The solution to create.
+        * @return The created solution.
+        */
+       public MLPSolution createSolution(MLPSolution solution);
+       /**
+        * Update a solution.
+        *
+        * @param solution The solution to update.
+        */
+       public void updateSolution(MLPSolution solution);
+       /**
+        * Save the picture for a solution.
+        *
+        * @param solutionId The ID of the solution.
+        * @param picture The picture for the solution.
+        */
+       public void savePicture(String solutionId, byte[] picture);
+       /**
+        * Get revisions of a solution.
+        *
+        * @param solutionId The ID of the solution.
+        * @return The revisions of the solution.
+        */
+       public List<MLPSolutionRevision> getRevisions(String solutionId);
+       /**
+        * Get details of a revision.
+        *
+        * If catalogId is null, no description and no documents for the
+        * revision are returned.
+        *
+        * @param revisionId The ID of the revision.
+        * @param catalogId The ID of the catalog (can be null).
+        * @return The revision extended with its description, artifacts, and documents.
+        */
+       public MLPSolutionRevision getRevision(String revisionId, String catalogId);
+       /**
+        * Create a revision.
+        *
+        * @param revision The revision to create.
+        * @return The created revision.
+        */
+       public MLPSolutionRevision createRevision(MLPSolutionRevision revision);
+       /**
+        * Update a revision.
+        *
+        * @param revision The revision to update.
+        */
+       public void updateRevision(MLPSolutionRevision revision);
+       /**
+        * Get artifacts of a revision.
+        *
+        * @param revisionId The ID of the revision.
+        * @return The artifacts of the revision.
+        */
+       public List<MLPArtifact> getArtifacts(String revisionId);
+       /**
+        * Get details of an artifact.
+        *
+        * @param artifactId The ID of the artifact.
+        * @return The artifact.
+        */
+       public MLPArtifact getArtifact(String artifactId);
+       /**
+        * Create an artifact.
+        *
+        * @param artifact The artifact to create.
+        * @return The created artifact.
+        */
+       public MLPArtifact createArtifact(MLPArtifact artifact);
+       /**
+        * Update an artifact.
+        *
+        * @param artifact The artifact to update.
+        */
+       public void updateArtifact(MLPArtifact artifact);
+       /**
+        * Add an artifact to a revision.
+        *
+        * @param solutionId The ID of the revision's solution.
+        * @param revisionId The ID of the revision.
+        * @param artifactId The ID of the artifact.
+        */
+       public void addArtifact(String solutionId, String revisionId, String artifactId);
+       /**
+        * Create a revision description in a catalog.
+        *
+        * @param revCatDescription The description
+        * @return The description
+        */
+       public MLPRevCatDescription createDescription(MLPRevCatDescription revCatDescription);
+       /**
+        * Update a revision description in a catalog.
+        *
+        * @param revCatDescription The description
+        */
+       public void updateDescription(MLPRevCatDescription revCatDescription);
+       /**
+        * Delete a revision description from a catalog.
+        *
+        * @param revisionId The ID of the revision.
+        * @param catalogId The ID of the catalog.
+        */
+       public void deleteDescription(String revisionId, String catalogId);
+       /**
+        * Get documents of a revision in a catalog.
+        *
+        * @param revisionId The ID of the revision.
+        * @param catalogId The ID of the catalog.
+        * @return The documents.
+        */
+       public List<MLPDocument> getDocuments(String revisionId, String catalogId);
+       /**
+        * Get details of a document.
+        *
+        * @param documentId The ID of the document.
+        * @return The document.
+        */
+       public MLPDocument getDocument(String documentId);
+       /**
+        * Create a document.
+        *
+        * @param document The document.
+        * @return The document.
+        */
+       public MLPDocument createDocument(MLPDocument document);
+       /**
+        * Update a document.
+        *
+        * @param document The document.
+        */
+       public void updateDocument(MLPDocument document);
+       /**
+        * Add a document to a catalog.
+        *
+        * @param revisionId The ID of the revision.
+        * @param catalogId The ID of the catalog.
+        * @param documentId The ID of the document.
+        */
+       public void addDocument(String revisionId, String catalogId, String documentId);
+       /**
+        * Determine whether the current peer has access to a catalog.
+        *
+        * A peer should have access if the catalog is public or if the peer
+        * has been granted specific access to the catalog.
+        *
+        * @param catalogId The ID of the catalog.
+        * @return true if the current peer has access.
+        */
+       public boolean isCatalogAllowed(String catalogId);
+       /**
+        * Determine whether the current peer has access to a solution.
+        *
+        * A peer should have access if the solution is in a catalog
+        * the peer can access.
+        *
+        * @param solutionId The ID of the solution.
+        * @return true if the current peer has access.
+        */
+       public boolean isSolutionAllowed(String solutionId);
+       /**
+        * Determine whether the current peer has access to a revision.
+        *
+        * A peer should have access if the revision is in a solution
+        * the peer can access.
+        *
+        * @param revisionId The ID of the revision.
+        * @return true if the current peer has access.
+        */
+       public