From f449c3379f15dcbba0555e3e06c604fbb348a7fc Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Wed, 2 Oct 2024 14:27:49 +0200 Subject: [PATCH] refactor: supports multi protocols dsp-http (#4514) refactor: supports multi protocols in DspRequest and DspHttpRemoteMessageDispatcherImpl --- .../http/api/DspCatalogApiExtension.java | 23 +++- .../controller/DspCatalogApiController.java | 9 ++ .../DspCatalogApiController20241.java | 7 +- .../http/api/DspCatalogApiExtensionTest.java | 14 ++- .../DspCatalogHttpDispatcherExtension.java | 7 +- .../delegate/ByteArrayBodyExtractor.java | 2 +- .../delegate/ByteArrayBodyExtractorTest.java | 6 +- .../DspCatalogTransformExtension.java | 15 ++- .../DspApiConfigurationExtension.java | 14 ++- .../dsp/http/DspHttpCoreExtension.java | 36 +++++- .../DspHttpRemoteMessageDispatcherImpl.java | 6 +- .../dispatcher/GetDspHttpRequestFactory.java | 16 ++- .../dispatcher/PostDspHttpRequestFactory.java | 15 ++- .../http/message/DspRequestHandlerImpl.java | 47 ++++++-- .../http/protocol/DspProtocolParserImpl.java | 54 +++++++++ .../JsonLdRemoteMessageSerializerImpl.java | 19 ++- .../JsonLdResponseBodyDeserializer.java | 23 +++- ...spProtocolTypeTransformerRegistryImpl.java | 42 +++++++ ...spHttpRemoteMessageDispatcherImplTest.java | 8 +- .../GetDspHttpRequestFactoryTest.java | 8 +- .../PostDspHttpRequestFactoryTest.java | 9 +- .../message/DspRequestHandlerImplTest.java | 109 ++++++++++++++---- .../protocol/DspProtocolParserImplTest.java | 63 ++++++++++ ...JsonLdRemoteMessageSerializerImplTest.java | 25 +++- .../JsonLdResponseBodyDeserializerTest.java | 23 +++- ...otocolTypeTransformerRegistryImplTest.java | 44 +++++++ .../dsp/http/spi/DspProtocolParser.java | 30 +++++ .../spi/dispatcher/DspHttpRequestFactory.java | 7 ++ .../DspHttpResponseBodyExtractor.java | 4 +- .../dsp/http/spi/message/DspRequest.java | 11 ++ .../http/spi/types/HttpMessageProtocol.java | 5 + .../http/api/DspNegotiationApiExtension.java | 2 + .../DspNegotiationApiController.java | 19 +++ .../DspNegotiationApiController20241.java | 3 +- ...DspNegotiationHttpDispatcherExtension.java | 22 ++-- .../DspNegotiationTransformExtension.java | 12 +- .../DspProtocolTypeTransformerRegistry.java | 26 +++++ .../protocol/dsp/spi/type/DspConstants.java | 8 ++ .../protocol/dsp/spi/version/DspVersions.java | 4 + .../api/DspTransferProcessApiExtension.java | 2 + .../DspTransferProcessApiController.java | 13 +++ .../DspTransferProcessApiController20241.java | 3 +- ...DspTransferProcessDispatcherExtension.java | 20 ++-- .../DspTransferProcessTransformExtension.java | 16 ++- .../http/api/DspVersionApiController.java | 2 + .../test/system/utils/Participant.java | 4 + .../domain/message/ProcessRemoteMessage.java | 15 +-- .../domain/message/ProtocolRemoteMessage.java | 32 +++++ .../catalog/spi/CatalogRequestMessage.java | 4 +- .../test/e2e/TransferPullEndToEndTest.java | 32 +++++ 50 files changed, 807 insertions(+), 133 deletions(-) create mode 100644 data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImpl.java create mode 100644 data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImpl.java create mode 100644 data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImplTest.java create mode 100644 data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImplTest.java create mode 100644 data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/DspProtocolParser.java create mode 100644 data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/transform/DspProtocolTypeTransformerRegistry.java create mode 100644 spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProtocolRemoteMessage.java diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java index 0b5f0aefdb6..ff9c26e4e17 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java @@ -24,9 +24,11 @@ import org.eclipse.edc.protocol.dsp.catalog.http.api.decorator.Base64continuationTokenSerDes; import org.eclipse.edc.protocol.dsp.catalog.http.api.decorator.ContinuationTokenManagerImpl; import org.eclipse.edc.protocol.dsp.catalog.http.api.validation.CatalogRequestMessageValidator; +import org.eclipse.edc.protocol.dsp.http.spi.message.ContinuationTokenManager; import org.eclipse.edc.protocol.dsp.http.spi.message.DspRequestHandler; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.protocol.ProtocolWebhook; import org.eclipse.edc.spi.query.CriterionOperatorRegistry; import org.eclipse.edc.spi.system.ServiceExtension; @@ -37,6 +39,9 @@ import org.eclipse.edc.web.spi.configuration.ApiContext; import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_REQUEST_MESSAGE; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_08; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_2024_1; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_08; import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1; /** @@ -64,7 +69,10 @@ public class DspCatalogApiExtension implements ServiceExtension { @Inject private ProtocolVersionRegistry versionRegistry; @Inject - private TypeTransformerRegistry typeTransformerRegistry; + private TypeTransformerRegistry transformerRegistry; + @Inject + private Monitor monitor; + @Inject private JsonLd jsonLd; @@ -77,10 +85,9 @@ public String name() { public void initialize(ServiceExtensionContext context) { validatorRegistry.register(DSPACE_TYPE_CATALOG_REQUEST_MESSAGE, CatalogRequestMessageValidator.instance(criterionOperatorRegistry)); - var continuationTokenSerDes = new Base64continuationTokenSerDes(typeTransformerRegistry.forContext("dsp-api"), jsonLd); - var catalogPaginationResponseDecoratorFactory = new ContinuationTokenManagerImpl(continuationTokenSerDes, context.getMonitor()); - webService.registerResource(ApiContext.PROTOCOL, new DspCatalogApiController(service, dspRequestHandler, catalogPaginationResponseDecoratorFactory)); - webService.registerResource(ApiContext.PROTOCOL, new DspCatalogApiController20241(service, dspRequestHandler, catalogPaginationResponseDecoratorFactory)); + + webService.registerResource(ApiContext.PROTOCOL, new DspCatalogApiController(service, dspRequestHandler, continuationTokenManager(monitor, DSP_TRANSFORMER_CONTEXT_V_08))); + webService.registerResource(ApiContext.PROTOCOL, new DspCatalogApiController20241(service, dspRequestHandler, continuationTokenManager(monitor, DSP_TRANSFORMER_CONTEXT_V_2024_1))); dataServiceRegistry.register(DataService.Builder.newInstance() .endpointDescription("dspace:connector") @@ -88,5 +95,11 @@ public void initialize(ServiceExtensionContext context) { .build()); versionRegistry.register(V_2024_1); + versionRegistry.register(V_08); + } + + private ContinuationTokenManager continuationTokenManager(Monitor monitor, String version) { + var continuationTokenSerDes = new Base64continuationTokenSerDes(transformerRegistry.forContext(version), jsonLd); + return new ContinuationTokenManagerImpl(continuationTokenSerDes, monitor); } } diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController.java index 85d28dbea10..9c66bffcd10 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController.java @@ -41,6 +41,7 @@ import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.BASE_PATH; import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.CATALOG_REQUEST; import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.DATASET_REQUEST; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_ERROR; import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_REQUEST_MESSAGE; @@ -55,11 +56,17 @@ public class DspCatalogApiController { private final CatalogProtocolService service; private final DspRequestHandler dspRequestHandler; private final ContinuationTokenManager continuationTokenManager; + private final String protocol; public DspCatalogApiController(CatalogProtocolService service, DspRequestHandler dspRequestHandler, ContinuationTokenManager continuationTokenManager) { + this(service, dspRequestHandler, continuationTokenManager, DATASPACE_PROTOCOL_HTTP); + } + + public DspCatalogApiController(CatalogProtocolService service, DspRequestHandler dspRequestHandler, ContinuationTokenManager continuationTokenManager, String protocol) { this.service = service; this.dspRequestHandler = dspRequestHandler; this.continuationTokenManager = continuationTokenManager; + this.protocol = protocol; } @POST @@ -80,6 +87,7 @@ public Response requestCatalog(JsonObject jsonObject, @HeaderParam(AUTHORIZATION .message(messageJson) .serviceCall(service::getCatalog) .errorType(DSPACE_TYPE_CATALOG_ERROR) + .protocol(protocol) .build(); var responseDecorator = continuationTokenManager.createResponseDecorator(uriInfo.getAbsolutePath().toString()); @@ -94,6 +102,7 @@ public Response getDataset(@PathParam("id") String id, @HeaderParam(AUTHORIZATIO .id(id) .serviceCall(service::getDataset) .errorType(DSPACE_TYPE_CATALOG_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.getResource(request); diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController20241.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController20241.java index da0a8e86521..5d380424333 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController20241.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/controller/DspCatalogApiController20241.java @@ -20,21 +20,22 @@ import org.eclipse.edc.connector.controlplane.services.spi.catalog.CatalogProtocolService; import org.eclipse.edc.protocol.dsp.http.spi.message.ContinuationTokenManager; import org.eclipse.edc.protocol.dsp.http.spi.message.DspRequestHandler; -import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; import static org.eclipse.edc.protocol.dsp.catalog.http.api.CatalogApiPaths.BASE_PATH; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP_V_2024_1; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1_PATH; /** * Versioned Catalog endpoint, same as {@link DspCatalogApiController} but exposed on the /2024/1 path */ @Consumes({ APPLICATION_JSON }) @Produces({ APPLICATION_JSON }) -@Path(DspVersions.V_2024_1_PATH + BASE_PATH) +@Path(V_2024_1_PATH + BASE_PATH) public class DspCatalogApiController20241 extends DspCatalogApiController { public DspCatalogApiController20241(CatalogProtocolService service, DspRequestHandler dspRequestHandler, ContinuationTokenManager responseDecorator) { - super(service, dspRequestHandler, responseDecorator); + super(service, dspRequestHandler, responseDecorator, DATASPACE_PROTOCOL_HTTP_V_2024_1); } } diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtensionTest.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtensionTest.java index ee0916dc207..46ffdb18487 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtensionTest.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtensionTest.java @@ -14,9 +14,10 @@ package org.eclipse.edc.protocol.dsp.catalog.http.api; -import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersion; import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersionRegistry; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; +import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.junit.jupiter.api.BeforeEach; @@ -24,22 +25,28 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.eclipse.edc.protocol.dsp.spi.type.DspCatalogPropertyAndTypeNames.DSPACE_TYPE_CATALOG_REQUEST_MESSAGE; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_08; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) class DspCatalogApiExtensionTest { private final JsonObjectValidatorRegistry validatorRegistry = mock(); private final ProtocolVersionRegistry versionRegistry = mock(); + private final DspProtocolTypeTransformerRegistry dspTransformerRegistry = mock(); @BeforeEach void setUp(ServiceExtensionContext context) { context.registerService(JsonObjectValidatorRegistry.class, validatorRegistry); context.registerService(ProtocolVersionRegistry.class, versionRegistry); + context.registerService(DspProtocolTypeTransformerRegistry.class, dspTransformerRegistry); + + when(dspTransformerRegistry.forProtocol(any())).thenReturn(Result.success(mock())); } @Test @@ -53,6 +60,7 @@ void shouldRegisterMessageValidator(DspCatalogApiExtension extension, ServiceExt void shouldRegisterDspVersion(DspCatalogApiExtension extension, ServiceExtensionContext context) { extension.initialize(context); - verify(versionRegistry).register(isA(ProtocolVersion.class)); + verify(versionRegistry).register(V_08); + verify(versionRegistry).register(V_2024_1); } } diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/DspCatalogHttpDispatcherExtension.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/DspCatalogHttpDispatcherExtension.java index a31a110b770..2c43c33477d 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/DspCatalogHttpDispatcherExtension.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/DspCatalogHttpDispatcherExtension.java @@ -19,6 +19,7 @@ import org.eclipse.edc.protocol.dsp.catalog.http.dispatcher.delegate.ByteArrayBodyExtractor; import org.eclipse.edc.protocol.dsp.http.dispatcher.GetDspHttpRequestFactory; import org.eclipse.edc.protocol.dsp.http.dispatcher.PostDspHttpRequestFactory; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.DspHttpRemoteMessageDispatcher; import org.eclipse.edc.protocol.dsp.http.spi.serialization.JsonLdRemoteMessageSerializer; import org.eclipse.edc.runtime.metamodel.annotation.Extension; @@ -43,6 +44,8 @@ public class DspCatalogHttpDispatcherExtension implements ServiceExtension { private DspHttpRemoteMessageDispatcher messageDispatcher; @Inject private JsonLdRemoteMessageSerializer remoteMessageSerializer; + @Inject + private DspProtocolParser dspProtocolParser; @Override public String name() { @@ -55,12 +58,12 @@ public void initialize(ServiceExtensionContext context) { messageDispatcher.registerMessage( CatalogRequestMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> BASE_PATH + CATALOG_REQUEST), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> BASE_PATH + CATALOG_REQUEST), byteArrayBodyExtractor ); messageDispatcher.registerMessage( DatasetRequestMessage.class, - new GetDspHttpRequestFactory<>(m -> BASE_PATH + DATASET_REQUEST + "/" + m.getDatasetId()), + new GetDspHttpRequestFactory<>(dspProtocolParser, m -> BASE_PATH + DATASET_REQUEST + "/" + m.getDatasetId()), byteArrayBodyExtractor ); } diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractor.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractor.java index a48dde70a19..913618e25d2 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractor.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractor.java @@ -25,7 +25,7 @@ */ public class ByteArrayBodyExtractor implements DspHttpResponseBodyExtractor { @Override - public byte[] extractBody(ResponseBody responseBody) { + public byte[] extractBody(ResponseBody responseBody, String protocol) { try { if (responseBody == null) { return null; diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractorTest.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractorTest.java index 1c3dfe76eab..8b72e284b3a 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractorTest.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-dispatcher/src/test/java/org/eclipse/edc/protocol/dsp/catalog/http/dispatcher/delegate/ByteArrayBodyExtractorTest.java @@ -35,14 +35,14 @@ void shouldReturnBodyAsBytes() throws IOException { var bytes = "test".getBytes(); when(responseBody.bytes()).thenReturn(bytes); - var result = extractor.extractBody(responseBody); + var result = extractor.extractBody(responseBody, "protocol"); assertThat(result).isEqualTo(bytes); } @Test void shouldReturnNull_whenBodyIsNull() { - var result = extractor.extractBody(null); + var result = extractor.extractBody(null, "protocol"); assertThat(result).isNull(); } @@ -52,7 +52,7 @@ void shouldThrowException_whenCannotExtractBytes() throws IOException { var responseBody = mock(ResponseBody.class); when(responseBody.bytes()).thenThrow(new IOException()); - assertThatThrownBy(() -> extractor.extractBody(responseBody)).isInstanceOf(EdcException.class); + assertThatThrownBy(() -> extractor.extractBody(responseBody, "protocol")).isInstanceOf(EdcException.class); } } diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java index ad2aba0abab..86729ccaeae 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java @@ -14,6 +14,7 @@ package org.eclipse.edc.protocol.dsp.catalog.transform; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.Json; import org.eclipse.edc.protocol.dsp.catalog.transform.from.JsonObjectFromCatalogRequestMessageTransformer; import org.eclipse.edc.protocol.dsp.catalog.transform.from.JsonObjectFromCatalogTransformer; @@ -31,6 +32,8 @@ import java.util.Map; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_08; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_2024_1; import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; /** @@ -57,10 +60,16 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var jsonFactory = Json.createBuilderFactory(Map.of()); var mapper = typeManager.getMapper(JSON_LD); - var dspApiTransformerRegistry = registry.forContext("dsp-api"); + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_08, mapper); + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_2024_1, mapper); + } + + private void registerTransformers(String version, ObjectMapper mapper) { + var jsonFactory = Json.createBuilderFactory(Map.of()); + + var dspApiTransformerRegistry = registry.forContext(version); dspApiTransformerRegistry.register(new JsonObjectFromCatalogRequestMessageTransformer(jsonFactory)); dspApiTransformerRegistry.register(new JsonObjectToCatalogRequestMessageTransformer()); @@ -69,4 +78,4 @@ public void initialize(ServiceExtensionContext context) { dspApiTransformerRegistry.register(new JsonObjectFromDistributionTransformer(jsonFactory)); dspApiTransformerRegistry.register(new JsonObjectFromDataServiceTransformer(jsonFactory)); } -} +} \ No newline at end of file diff --git a/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java b/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java index 33d2c788f6a..38257d06713 100644 --- a/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java +++ b/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java @@ -14,6 +14,7 @@ package org.eclipse.edc.protocol.dsp.http.api.configuration; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.Json; import org.eclipse.edc.connector.controlplane.transform.edc.from.JsonObjectFromAssetTransformer; import org.eclipse.edc.connector.controlplane.transform.edc.to.JsonObjectToAssetTransformer; @@ -62,6 +63,8 @@ import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX; import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_08; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_2024_1; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX; import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; @@ -132,17 +135,18 @@ public void initialize(ServiceExtensionContext context) { webService.registerResource(ApiContext.PROTOCOL, new ObjectMapperProvider(jsonLdMapper)); webService.registerResource(ApiContext.PROTOCOL, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE)); - registerTransformers(); - } - - private void registerTransformers() { var mapper = typeManager.getMapper(JSON_LD); mapper.registerSubtypes(AtomicConstraint.class, LiteralExpression.class); + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_08, mapper); + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_2024_1, mapper); + } + + private void registerTransformers(String version, ObjectMapper mapper) { var jsonBuilderFactory = Json.createBuilderFactory(Map.of()); // EDC model to JSON-LD transformers - var dspApiTransformerRegistry = transformerRegistry.forContext("dsp-api"); + var dspApiTransformerRegistry = transformerRegistry.forContext(version); dspApiTransformerRegistry.register(new JsonObjectFromPolicyTransformer(jsonBuilderFactory, participantIdMapper)); dspApiTransformerRegistry.register(new JsonObjectFromAssetTransformer(jsonBuilderFactory, mapper)); dspApiTransformerRegistry.register(new JsonObjectFromDataAddressDspaceTransformer(jsonBuilderFactory, mapper)); diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java index 2841c032963..8a935270cc2 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java @@ -22,6 +22,7 @@ import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiationTerminationMessage; import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequestMessage; import org.eclipse.edc.connector.controlplane.contract.spi.types.protocol.ContractRemoteMessage; +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersionRegistry; import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferCompletionMessage; import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferRemoteMessage; import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferRequestMessage; @@ -34,10 +35,14 @@ import org.eclipse.edc.policy.engine.spi.PolicyScope; import org.eclipse.edc.protocol.dsp.http.dispatcher.DspHttpRemoteMessageDispatcherImpl; import org.eclipse.edc.protocol.dsp.http.message.DspRequestHandlerImpl; +import org.eclipse.edc.protocol.dsp.http.protocol.DspProtocolParserImpl; import org.eclipse.edc.protocol.dsp.http.serialization.JsonLdRemoteMessageSerializerImpl; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.DspHttpRemoteMessageDispatcher; import org.eclipse.edc.protocol.dsp.http.spi.message.DspRequestHandler; import org.eclipse.edc.protocol.dsp.http.spi.serialization.JsonLdRemoteMessageSerializer; +import org.eclipse.edc.protocol.dsp.http.transform.DspProtocolTypeTransformerRegistryImpl; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; @@ -53,7 +58,9 @@ import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP_V_2024_1; import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT; import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; /** @@ -109,6 +116,13 @@ public class DspHttpCoreExtension implements ServiceExtension { @Inject private JsonObjectValidatorRegistry validatorRegistry; + @Inject + private ProtocolVersionRegistry versionRegistry; + + private DspProtocolTypeTransformerRegistry dspTransformerRegistry; + private DspProtocolParser dspProtocolParser; + + @Override public String name() { return NAME; @@ -129,17 +143,34 @@ public DspHttpRemoteMessageDispatcher dspHttpRemoteMessageDispatcher(ServiceExte registerTransferProcessPolicyScopes(dispatcher); registerCatalogPolicyScopes(dispatcher); dispatcherRegistry.register(DATASPACE_PROTOCOL_HTTP, dispatcher); + dispatcherRegistry.register(DATASPACE_PROTOCOL_HTTP_V_2024_1, dispatcher); return dispatcher; } @Provider public DspRequestHandler dspRequestHandler() { - return new DspRequestHandlerImpl(monitor, validatorRegistry, transformerRegistry.forContext("dsp-api")); + return new DspRequestHandlerImpl(monitor, validatorRegistry, dspTransformerRegistry()); } @Provider public JsonLdRemoteMessageSerializer jsonLdRemoteMessageSerializer() { - return new JsonLdRemoteMessageSerializerImpl(transformerRegistry.forContext("dsp-api"), typeManager.getMapper(JSON_LD), jsonLdService, DSP_SCOPE); + return new JsonLdRemoteMessageSerializerImpl(dspTransformerRegistry(), typeManager.getMapper(JSON_LD), jsonLdService, DSP_SCOPE); + } + + @Provider + public DspProtocolTypeTransformerRegistry dspTransformerRegistry() { + if (dspTransformerRegistry == null) { + dspTransformerRegistry = new DspProtocolTypeTransformerRegistryImpl(transformerRegistry, DSP_TRANSFORMER_CONTEXT, dspProtocolParser()); + } + return dspTransformerRegistry; + } + + @Provider + public DspProtocolParser dspProtocolParser() { + if (dspProtocolParser == null) { + dspProtocolParser = new DspProtocolParserImpl(versionRegistry); + } + return dspProtocolParser; } private void registerNegotiationPolicyScopes(DspHttpRemoteMessageDispatcher dispatcher) { @@ -162,5 +193,4 @@ private void registerCatalogPolicyScopes(DspHttpRemoteMessageDispatcher dispatch dispatcher.registerPolicyScope(CatalogRequestMessage.class, CATALOGING_REQUEST_SCOPE, CatalogRequestMessage::getPolicy); dispatcher.registerPolicyScope(DatasetRequestMessage.class, CATALOGING_REQUEST_SCOPE, DatasetRequestMessage::getPolicy); } - } diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImpl.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImpl.java index 3a141541c7a..b5138a4a124 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImpl.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImpl.java @@ -126,7 +126,7 @@ public CompletableFuture> dispatch( .build(); return httpClient.executeAsync(requestWithAuth, List.of(retryWhenStatusNot2xxOr4xx())) - .thenApply(response -> handleResponse(response, responseType, handler.bodyExtractor)); + .thenApply(response -> handleResponse(response, message.getProtocol(), responseType, handler.bodyExtractor)); }) .orElse(failure -> failedFuture(new EdcException(format("Unable to obtain credentials: %s", failure.getFailureDetail())))); } @@ -143,10 +143,10 @@ public void registerPolicyScope(Class messageClass, } @NotNull - private StatusResult handleResponse(Response response, Class responseType, DspHttpResponseBodyExtractor bodyExtractor) { + private StatusResult handleResponse(Response response, String protocol, Class responseType, DspHttpResponseBodyExtractor bodyExtractor) { try (var responseBody = response.body()) { if (response.isSuccessful()) { - var responsePayload = bodyExtractor.extractBody(responseBody); + var responsePayload = bodyExtractor.extractBody(responseBody, protocol); return StatusResult.success(responseType.cast(responsePayload)); } else { diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactory.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactory.java index 38055818a03..63a084faaa8 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactory.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactory.java @@ -16,8 +16,11 @@ import okhttp3.HttpUrl; import okhttp3.Request; +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersion; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.DspHttpRequestFactory; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.RequestPathProvider; +import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; /** @@ -28,13 +31,22 @@ public class GetDspHttpRequestFactory implements DspHttpRequestFactory { private final RequestPathProvider pathProvider; - public GetDspHttpRequestFactory(RequestPathProvider pathProvider) { + private final DspProtocolParser protocolParser; + + public GetDspHttpRequestFactory(DspProtocolParser protocolParser, RequestPathProvider pathProvider) { + this.protocolParser = protocolParser; this.pathProvider = pathProvider; } @Override public Request createRequest(M message) { - var url = HttpUrl.get(message.getCounterPartyAddress() + pathProvider.providePath(message)); + + var protocolPath = protocolParser.parse(message.getProtocol()) + .map(ProtocolVersion::path) + .map(this::removeTrailingSlash) + .orElseThrow(failure -> new EdcException(failure.getFailureDetail())); + + var url = HttpUrl.get(message.getCounterPartyAddress() + protocolPath + pathProvider.providePath(message)); return new Request.Builder() .url(url) diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactory.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactory.java index f307a299222..9e9c9cf5918 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactory.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactory.java @@ -18,9 +18,12 @@ import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersion; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.DspHttpRequestFactory; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.RequestPathProvider; import org.eclipse.edc.protocol.dsp.http.spi.serialization.JsonLdRemoteMessageSerializer; +import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; /** @@ -33,9 +36,12 @@ public class PostDspHttpRequestFactory implements DspHt public static final String APPLICATION_JSON = "application/json"; private final RequestPathProvider pathProvider; private final JsonLdRemoteMessageSerializer serializer; + private final DspProtocolParser protocolParser; - public PostDspHttpRequestFactory(JsonLdRemoteMessageSerializer serializer, RequestPathProvider pathProvider) { + + public PostDspHttpRequestFactory(JsonLdRemoteMessageSerializer serializer, DspProtocolParser protocolParser, RequestPathProvider pathProvider) { this.serializer = serializer; + this.protocolParser = protocolParser; this.pathProvider = pathProvider; } @@ -44,7 +50,12 @@ public Request createRequest(M message) { var body = serializer.serialize(message); var requestBody = RequestBody.create(body, MediaType.get(APPLICATION_JSON)); - var url = HttpUrl.get(message.getCounterPartyAddress() + pathProvider.providePath(message)); + var protocolPath = protocolParser.parse(message.getProtocol()) + .map(ProtocolVersion::path) + .map(this::removeTrailingSlash) + .orElseThrow(failure -> new EdcException(failure.getFailureDetail())); + + var url = HttpUrl.get(message.getCounterPartyAddress() + protocolPath + pathProvider.providePath(message)); return new Request.Builder() .url(url) diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImpl.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImpl.java index 0f6770b9a34..ff6e7f9a574 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImpl.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImpl.java @@ -21,29 +21,29 @@ import org.eclipse.edc.protocol.dsp.http.spi.message.GetDspRequest; import org.eclipse.edc.protocol.dsp.http.spi.message.PostDspRequest; import org.eclipse.edc.protocol.dsp.http.spi.message.ResponseDecorator; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.types.domain.message.ProcessRemoteMessage; +import org.eclipse.edc.spi.types.domain.message.ProtocolRemoteMessage; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import java.util.UUID; import static org.eclipse.edc.protocol.dsp.http.spi.error.DspErrorResponse.type; -import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; public class DspRequestHandlerImpl implements DspRequestHandler { private final Monitor monitor; private final JsonObjectValidatorRegistry validatorRegistry; - private final TypeTransformerRegistry transformerRegistry; + private final DspProtocolTypeTransformerRegistry dspTransformerRegistry; - public DspRequestHandlerImpl(Monitor monitor, JsonObjectValidatorRegistry validatorRegistry, TypeTransformerRegistry transformerRegistry) { + public DspRequestHandlerImpl(Monitor monitor, JsonObjectValidatorRegistry validatorRegistry, DspProtocolTypeTransformerRegistry dspTransformerRegistry) { this.monitor = monitor; this.validatorRegistry = validatorRegistry; - this.transformerRegistry = transformerRegistry; + this.dspTransformerRegistry = dspTransformerRegistry; } @Override @@ -64,7 +64,13 @@ public Response getResource(GetDspRequest request) { var resource = serviceResult.getContent(); - var transformation = transformerRegistry.transform(resource, JsonObject.class); + var registryResult = dspTransformerRegistry.forProtocol(request.getProtocol()); + if (registryResult.failed()) { + monitor.debug(() -> "DSP: Unsupported protocol %s: %s".formatted(request.getProtocol(), registryResult.getFailureMessages())); + return type(request.getErrorType()).badRequest(); + } + var registry = registryResult.getContent(); + var transformation = registry.transform(resource, JsonObject.class); if (transformation.failed()) { var errorCode = UUID.randomUUID(); monitor.warning("Error transforming %s, error id %s: %s".formatted(request.getResultClass().getSimpleName(), errorCode, transformation.getFailureDetail())); @@ -92,10 +98,18 @@ public Response createResource(PostDspRequest return type(request.getErrorType()).badRequest(); } - var inputTransformation = transformerRegistry.transform(request.getMessage(), request.getInputClass()) + var registryResult = dspTransformerRegistry.forProtocol(request.getProtocol()); + + if (registryResult.failed()) { + monitor.debug(() -> "DSP: Unsupported protocol %s: %s".formatted(request.getProtocol(), registryResult.getFailureMessages())); + return type(request.getErrorType()).badRequest(); + } + + var registry = registryResult.getContent(); + var inputTransformation = registry.transform(request.getMessage(), request.getInputClass()) .compose(message -> { - if (message instanceof ProcessRemoteMessage processRemoteMessage) { - processRemoteMessage.setProtocol(DATASPACE_PROTOCOL_HTTP); + if (message instanceof ProtocolRemoteMessage protocolRemoteMessage) { + protocolRemoteMessage.setProtocol(request.getProtocol()); } return Result.success(message); }); @@ -116,7 +130,7 @@ public Response createResource(PostDspRequest var resource = serviceResult.getContent(); - var outputTransformation = transformerRegistry.transform(resource, JsonObject.class); + var outputTransformation = registry.transform(resource, JsonObject.class); if (outputTransformation.failed()) { var errorCode = UUID.randomUUID(); monitor.warning("Error transforming %s, error id %s: %s".formatted(request.getResultClass().getSimpleName(), errorCode, outputTransformation.getFailureDetail())); @@ -149,13 +163,22 @@ public Response updateResource(PostDspRequest return type(request.getErrorType()).processId(request.getProcessId()).badRequest(); } - var inputTransformation = transformerRegistry.transform(request.getMessage(), request.getInputClass()) + var registryResult = dspTransformerRegistry.forProtocol(request.getProtocol()); + + if (registryResult.failed()) { + monitor.debug(() -> "DSP: Unsupported protocol %s: %s".formatted(request.getProtocol(), registryResult.getFailureMessages())); + return type(request.getErrorType()).badRequest(); + } + + var registry = registryResult.getContent(); + + var inputTransformation = registry.transform(request.getMessage(), request.getInputClass()) .compose(message -> { if (message instanceof ProcessRemoteMessage processRemoteMessage) { var processIdValidation = processRemoteMessage.isValidProcessId(request.getProcessId()); if (processIdValidation.succeeded()) { processRemoteMessage.setProcessId(request.getProcessId()); - processRemoteMessage.setProtocol(DATASPACE_PROTOCOL_HTTP); + processRemoteMessage.setProtocol(request.getProtocol()); return Result.success(message); } else { return Result.failure("DSP: %s".formatted(processIdValidation.getFailureDetail())); diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImpl.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImpl.java new file mode 100644 index 00000000000..3ae5fc20ca2 --- /dev/null +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImpl.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.http.protocol; + +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersion; +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersionRegistry; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; +import org.eclipse.edc.spi.result.Result; + +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP_SEPARATOR; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_08; + +public class DspProtocolParserImpl implements DspProtocolParser { + + private final ProtocolVersionRegistry versionRegistry; + + public DspProtocolParserImpl(ProtocolVersionRegistry versionRegistry) { + this.versionRegistry = versionRegistry; + } + + @Override + public Result parse(String protocol) { + var protocolWithVersion = protocol.split(DATASPACE_PROTOCOL_HTTP_SEPARATOR); + var protocolName = protocolWithVersion[0]; + + if (!protocolName.equals(DATASPACE_PROTOCOL_HTTP)) { + return Result.failure("Protocol %s not supported. Expected protocol: %s".formatted(protocolName, DATASPACE_PROTOCOL_HTTP)); + } + + if (protocolWithVersion.length == 1) { + return Result.success(V_08); + } + var protocolVersion = protocolWithVersion[1]; + + return versionRegistry.getAll().protocolVersions() + .stream().filter(protoVersion -> protoVersion.version().equals(protocolVersion)) + .findFirst() + .map(Result::success) + .orElseGet(() -> Result.failure("Protocol %s with version %s not supported".formatted(protocolName, protocolVersion))); + } +} diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java index a37260fb73e..1f3b8503f90 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java @@ -19,6 +19,7 @@ import jakarta.json.JsonObject; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.protocol.dsp.http.spi.serialization.JsonLdRemoteMessageSerializer; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; @@ -31,14 +32,14 @@ */ public class JsonLdRemoteMessageSerializerImpl implements JsonLdRemoteMessageSerializer { - private final TypeTransformerRegistry registry; private final ObjectMapper mapper; private final JsonLd jsonLdService; - private final String scope; + private final DspProtocolTypeTransformerRegistry dspTransformerRegistry; - public JsonLdRemoteMessageSerializerImpl(TypeTransformerRegistry registry, ObjectMapper mapper, JsonLd jsonLdService, String scope) { - this.registry = registry; + public JsonLdRemoteMessageSerializerImpl(DspProtocolTypeTransformerRegistry dspTransformerRegistry, + ObjectMapper mapper, JsonLd jsonLdService, String scope) { + this.dspTransformerRegistry = dspTransformerRegistry; this.mapper = mapper; this.jsonLdService = jsonLdService; this.scope = scope; @@ -55,7 +56,14 @@ public JsonLdRemoteMessageSerializerImpl(TypeTransformerRegistry registry, Objec @Override public String serialize(RemoteMessage message) { try { - var transformResult = registry.transform(message, JsonObject.class); + var transformerRegistryResult = dspTransformerRegistry.forProtocol(message.getProtocol()); + if (transformerRegistryResult.failed()) { + throw new EdcException(format("Failed to serialize %s: %s", message.getClass().getSimpleName(), join(", ", transformerRegistryResult.getFailureMessages()))); + + } + + var transformerRegistry = transformerRegistryResult.getContent(); + var transformResult = transformerRegistry.transform(message, JsonObject.class); if (transformResult.succeeded()) { var compacted = jsonLdService.compact(transformResult.getContent(), scope); @@ -69,4 +77,5 @@ public String serialize(RemoteMessage message) { throw new EdcException(format("Failed to serialize %s", message.getClass().getSimpleName()), e); } } + } diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java index 197b5ded92b..082a8b522fe 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java @@ -19,14 +19,17 @@ import okhttp3.ResponseBody; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.response.DspHttpResponseBodyExtractor; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.result.Failure; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.function.Function; +import static java.lang.String.format; +import static java.lang.String.join; + /** * Extract a Json-LD represented body from {@link ResponseBody} */ @@ -34,21 +37,28 @@ public class JsonLdResponseBodyDeserializer implements DspHttpResponseBodyExt private final Class type; private final ObjectMapper objectMapper; private final JsonLd jsonLd; - private final TypeTransformerRegistry transformerRegistry; + private final DspProtocolTypeTransformerRegistry dspTransformerRegistry; - public JsonLdResponseBodyDeserializer(Class type, ObjectMapper objectMapper, JsonLd jsonLd, TypeTransformerRegistry transformerRegistry) { + public JsonLdResponseBodyDeserializer(Class type, ObjectMapper objectMapper, JsonLd jsonLd, DspProtocolTypeTransformerRegistry dspTransformerRegistry) { this.type = type; this.objectMapper = objectMapper; this.jsonLd = jsonLd; - this.transformerRegistry = transformerRegistry; + this.dspTransformerRegistry = dspTransformerRegistry; } @Override - public T extractBody(ResponseBody responseBody) { + public T extractBody(ResponseBody responseBody, String protocol) { try { var jsonObject = objectMapper.readValue(responseBody.byteStream(), JsonObject.class); + var transformerRegistryResult = dspTransformerRegistry.forProtocol(protocol); + if (transformerRegistryResult.failed()) { + throw new EdcException(format("Failed to extract body: %s", join(", ", transformerRegistryResult.getFailureMessages()))); + } + + var registry = transformerRegistryResult.getContent(); + var expanded = jsonLd.expand(jsonObject).orElseThrow(exception("Cannot expand json-ld")); - return transformerRegistry.transform(expanded, type) + return registry.transform(expanded, type) .orElseThrow(exception("Cannot transform json to ContractNegotiationAck")); } catch (IOException e) { @@ -60,4 +70,5 @@ public T extractBody(ResponseBody responseBody) { private Function exception(String message) { return f -> new EdcException("%s: %s".formatted(message, f.getFailureDetail())); } + } diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImpl.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImpl.java new file mode 100644 index 00000000000..e046edd0bfc --- /dev/null +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.http.transform; + +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; + +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_CONTEXT_SEPARATOR; + +public class DspProtocolTypeTransformerRegistryImpl implements DspProtocolTypeTransformerRegistry { + + private final TypeTransformerRegistry transformerRegistry; + private final String transformerContextPrefix; + private final DspProtocolParser protocolParser; + + public DspProtocolTypeTransformerRegistryImpl(TypeTransformerRegistry transformerRegistry, String transformerContextPrefix, DspProtocolParser protocolParser) { + this.transformerRegistry = transformerRegistry; + this.transformerContextPrefix = transformerContextPrefix; + this.protocolParser = protocolParser; + } + + @Override + public Result forProtocol(String protocol) { + return protocolParser.parse(protocol) + .map(protocolVersion -> transformerRegistry.forContext(transformerContextPrefix + DSP_CONTEXT_SEPARATOR + protocolVersion.version())); + } + +} diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImplTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImplTest.java index 268e424a2e9..1aeb9f18a3b 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImplTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/DspHttpRemoteMessageDispatcherImplTest.java @@ -362,7 +362,7 @@ class Response { @Test void shouldShouldReturnSuccess_whenResponseIsSuccessful() { respondWith(dummyResponse(200), bodyExtractor); - when(bodyExtractor.extractBody(any())).thenReturn("response"); + when(bodyExtractor.extractBody(any(), any())).thenReturn("response"); var future = dispatcher.dispatch(String.class, new TestMessage()); @@ -384,7 +384,7 @@ void shouldReturnFatalError_whenResponseIsClientError() { assertThat(failure.getMessages()).containsOnly("expectedValue"); }); }); - verify(bodyExtractor, never()).extractBody(any()); + verify(bodyExtractor, never()).extractBody(any(), any()); } @Test @@ -399,7 +399,7 @@ void shouldReturnFatalError_whenResponseIsClientErrorAndBodyIsNull() { assertThat(failure.getMessages()).allMatch(it -> it.contains("is null")); }); }); - verify(bodyExtractor, never()).extractBody(any()); + verify(bodyExtractor, never()).extractBody(any(), any()); } @Test @@ -413,7 +413,7 @@ void shouldReturnRetryError_whenResponseIsServerError() { assertThat(failure.status()).isEqualTo(ERROR_RETRY); }); }); - verify(bodyExtractor, never()).extractBody(any()); + verify(bodyExtractor, never()).extractBody(any(), any()); } private void respondWith(okhttp3.Response response, DspHttpResponseBodyExtractor bodyExtractor) { diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactoryTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactoryTest.java index ae001d0c0e5..5853ac85cc8 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactoryTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/GetDspHttpRequestFactoryTest.java @@ -15,7 +15,10 @@ package org.eclipse.edc.protocol.dsp.http.dispatcher; import org.eclipse.edc.protocol.dsp.http.TestMessage; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.RequestPathProvider; +import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; +import org.eclipse.edc.spi.result.Result; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -26,11 +29,13 @@ class GetDspHttpRequestFactoryTest { private final RequestPathProvider pathProvider = mock(); - private final GetDspHttpRequestFactory factory = new GetDspHttpRequestFactory<>(pathProvider); + private final DspProtocolParser dspProtocolParser = mock(); + private final GetDspHttpRequestFactory factory = new GetDspHttpRequestFactory<>(dspProtocolParser, pathProvider); @Test void shouldCreateProperHttpRequest() { when(pathProvider.providePath(any())).thenReturn("/message/request/path"); + when(dspProtocolParser.parse("protocol")).thenReturn(Result.success(DspVersions.V_08)); var message = new TestMessage("protocol", "http://counter-party", "counterPartyId"); var request = factory.createRequest(message); @@ -38,4 +43,5 @@ void shouldCreateProperHttpRequest() { assertThat(request.url().url().toString()).isEqualTo("http://counter-party/message/request/path"); assertThat(request.method()).isEqualTo("GET"); } + } diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactoryTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactoryTest.java index 327ceee2646..3c8e64df70f 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactoryTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/dispatcher/PostDspHttpRequestFactoryTest.java @@ -17,8 +17,11 @@ import okhttp3.MediaType; import okio.Buffer; import org.eclipse.edc.protocol.dsp.http.TestMessage; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.RequestPathProvider; import org.eclipse.edc.protocol.dsp.http.spi.serialization.JsonLdRemoteMessageSerializer; +import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; +import org.eclipse.edc.spi.result.Result; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -30,11 +33,13 @@ class PostDspHttpRequestFactoryTest { private final RequestPathProvider pathProvider = mock(); private final JsonLdRemoteMessageSerializer serializer = mock(); - private final PostDspHttpRequestFactory factory = new PostDspHttpRequestFactory<>(serializer, pathProvider); + private final DspProtocolParser dspProtocolParser = mock(); + private final PostDspHttpRequestFactory factory = new PostDspHttpRequestFactory<>(serializer, dspProtocolParser, pathProvider); @Test void shouldCreateProperHttpRequest() { when(serializer.serialize(any())).thenReturn("serializedMessage"); + when(dspProtocolParser.parse("protocol")).thenReturn(Result.success(DspVersions.V_08)); when(pathProvider.providePath(any())).thenReturn("/message/request/path"); var message = new TestMessage("protocol", "http://counter-party", "counterPartyId"); @@ -52,4 +57,6 @@ void shouldCreateProperHttpRequest() { }); } + + } diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImplTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImplTest.java index 1480f1f3c86..22d3a5586e1 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImplTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/message/DspRequestHandlerImplTest.java @@ -19,6 +19,7 @@ import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.protocol.dsp.http.spi.message.GetDspRequest; import org.eclipse.edc.protocol.dsp.http.spi.message.PostDspRequest; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.ServiceResult; @@ -26,6 +27,7 @@ import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.validator.spi.ValidationResult; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -50,8 +52,35 @@ class DspRequestHandlerImplTest { private final JsonObjectValidatorRegistry validatorRegistry = mock(); + private final DspProtocolTypeTransformerRegistry dspTransformerRegistry = mock(); private final TypeTransformerRegistry transformerRegistry = mock(); - private final DspRequestHandlerImpl handler = new DspRequestHandlerImpl(mock(), validatorRegistry, transformerRegistry); + + private final DspRequestHandlerImpl handler = new DspRequestHandlerImpl(mock(), validatorRegistry, dspTransformerRegistry); + private final String protocol = DATASPACE_PROTOCOL_HTTP; + + @BeforeEach + void beforeEach() { + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); + } + + private static class TestProcessRemoteMessage extends ProcessRemoteMessage { + + @Override + public Policy getPolicy() { + return null; + } + + public static class Builder extends ProcessRemoteMessage.Builder { + + protected Builder() { + super(new TestProcessRemoteMessage()); + } + + public static Builder newInstance() { + return new Builder(); + } + } + } @Nested class GetResource { @@ -61,12 +90,14 @@ void shouldSucceed() { var content = new Object(); var resourceJson = Json.createObjectBuilder().build(); BiFunction> serviceCall = (m, t) -> ServiceResult.success(content); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(transformerRegistry.transform(any(), any())).thenReturn(Result.success(resourceJson)); var request = GetDspRequest.Builder.newInstance(Object.class) .token("token") .id("id") .serviceCall(serviceCall) .errorType("errorType") + .protocol(protocol) .build(); var result = handler.getResource(request); @@ -117,6 +148,7 @@ void shouldFail_whenServiceCallFails() { @Test void shouldFail_whenTransformationFails() { + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(transformerRegistry.transform(any(), any())).thenReturn(Result.failure("error")); var request = getDspRequestBuilder().build(); @@ -125,12 +157,25 @@ void shouldFail_whenTransformationFails() { assertThat(result.getStatus()).isEqualTo(500); } + @Test + void shouldFail_whenProtocolParseFails() { + var faultyProtocol = "faultyProtocol"; + when(dspTransformerRegistry.forProtocol(faultyProtocol)).thenReturn(Result.failure("faultyProtocol")); + + var request = getDspRequestBuilder().protocol(faultyProtocol).build(); + + var result = handler.getResource(request); + + assertThat(result.getStatus()).isEqualTo(400); + } + private GetDspRequest.Builder getDspRequestBuilder() { return GetDspRequest.Builder.newInstance(Object.class) .token("token") .id("id") .serviceCall((i, c) -> ServiceResult.success()) - .errorType("errorType"); + .errorType("errorType") + .protocol(protocol); } } @@ -143,6 +188,7 @@ void shouldSucceed() { var content = new Object(); var responseJson = Json.createObjectBuilder().build(); BiFunction> serviceCall = (m, t) -> ServiceResult.success(content); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), eq(TestProcessRemoteMessage.class))).thenReturn(Result.success(message)); when(transformerRegistry.transform(any(), eq(JsonObject.class))).thenReturn(Result.success(responseJson)); @@ -152,6 +198,7 @@ void shouldSucceed() { .message(jsonMessage) .serviceCall(serviceCall) .errorType("errorType") + .protocol(protocol) .build(); var result = handler.createResource(request); @@ -184,6 +231,7 @@ void shouldFail_whenTokenIsNotValid() { var request = postDspRequestBuilder().errorType("errorType").serviceCall((m, t) -> ServiceResult.unauthorized("unauthorized")).build(); var message = mock(TestProcessRemoteMessage.class); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), eq(TestProcessRemoteMessage.class))).thenReturn(Result.success(message)); @@ -209,6 +257,7 @@ void shouldFail_whenValidationFails() { @Test void shouldFail_whenTransformationFails() { + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), any())).thenReturn(Result.failure("error")); var request = postDspRequestBuilder().build(); @@ -218,10 +267,23 @@ void shouldFail_whenTransformationFails() { assertThat(result.getStatus()).isEqualTo(400); } + @Test + void shouldFail_whenProtocolParseFails() { + var faultyProtocol = "faultyProtocol"; + when(dspTransformerRegistry.forProtocol(faultyProtocol)).thenReturn(Result.failure(faultyProtocol)); + when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); + var request = postDspRequestBuilder().protocol(faultyProtocol).build(); + + var result = handler.createResource(request); + + assertThat(result.getStatus()).isEqualTo(400); + } + @Test void shouldFail_whenServiceCallFails() { var message = mock(TestProcessRemoteMessage.class); BiFunction> serviceCall = (m, t) -> ServiceResult.conflict("error"); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), any())).thenReturn(Result.success(message)); var request = postDspRequestBuilder().serviceCall(serviceCall).build(); @@ -234,6 +296,7 @@ void shouldFail_whenServiceCallFails() { @Test void shouldReturnInternalServerError_whenOutputTransformationFails() { var message = mock(TestProcessRemoteMessage.class); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), eq(TestProcessRemoteMessage.class))).thenReturn(Result.success(message)); when(transformerRegistry.transform(any(), eq(JsonObject.class))).thenReturn(Result.failure("error")); @@ -251,6 +314,7 @@ void shouldDecorateResponse_whenDecoratorSpecified() { var content = new Object(); var responseJson = Json.createObjectBuilder().build(); BiFunction> serviceCall = (m, t) -> ServiceResult.success(content); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), eq(TestProcessRemoteMessage.class))).thenReturn(Result.success(message)); when(transformerRegistry.transform(any(), eq(JsonObject.class))).thenReturn(Result.success(responseJson)); @@ -260,6 +324,7 @@ void shouldDecorateResponse_whenDecoratorSpecified() { .message(jsonMessage) .serviceCall(serviceCall) .errorType("errorType") + .protocol(protocol) .build(); var result = handler.createResource(request, (r, i, o) -> r.header("test", "test")); @@ -272,6 +337,7 @@ private PostDspRequest.Builder postDspRequestB .newInstance(TestProcessRemoteMessage.class, Object.class) .errorType("errorType") .token("token") + .protocol(protocol) .serviceCall((i, c) -> ServiceResult.success()); } @@ -285,6 +351,7 @@ void shouldSucceed() { var message = TestProcessRemoteMessage.Builder.newInstance().providerPid("providerPid").consumerPid("processId").build(); var content = new Object(); BiFunction> serviceCall = (m, t) -> ServiceResult.success(content); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), eq(TestProcessRemoteMessage.class))).thenReturn(Result.success(message)); var request = PostDspRequest.Builder.newInstance(TestProcessRemoteMessage.class, Object.class) @@ -294,6 +361,7 @@ void shouldSucceed() { .message(jsonMessage) .serviceCall(serviceCall) .errorType("errorType") + .protocol(protocol) .build(); var result = handler.updateResource(request); @@ -317,6 +385,7 @@ void shouldFail_whenTokenIsNotValid() { .build(); var message = TestProcessRemoteMessage.Builder.newInstance().providerPid("providerPid").consumerPid("processId").build(); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), eq(TestProcessRemoteMessage.class))).thenReturn(Result.success(message)); @@ -371,6 +440,7 @@ void shouldFail_whenValidationFails() { @Test void shouldFail_whenTransformationFails() { + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), any())).thenReturn(Result.failure("error")); var request = postDspRequestBuilder().processId("processId").errorType("errorType").build(); @@ -386,12 +456,26 @@ void shouldFail_whenTransformationFails() { }); } + @Test + void shouldFail_whenProtocolParseFails() { + var faultyProtocol = "faultyProtocol"; + when(dspTransformerRegistry.forProtocol(faultyProtocol)).thenReturn(Result.failure(faultyProtocol)); + + when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); + var request = postDspRequestBuilder().protocol(faultyProtocol).build(); + + var result = handler.createResource(request); + + assertThat(result.getStatus()).isEqualTo(400); + } + @Test void shouldFail_whenIdIsNotValid() { var message = TestProcessRemoteMessage.Builder.newInstance() .consumerPid("consumerPid") .providerPid("providerPid") .build(); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), any())).thenReturn(Result.success(message)); var request = postDspRequestBuilder().processId("anotherId").errorType("errorType").build(); @@ -411,6 +495,7 @@ void shouldFail_whenIdIsNotValid() { void shouldFail_whenServiceCallFails() { var message = TestProcessRemoteMessage.Builder.newInstance().providerPid("providerPid").consumerPid("processId").build(); BiFunction> serviceCall = (m, t) -> ServiceResult.conflict("error"); + when(dspTransformerRegistry.forProtocol(protocol)).thenReturn(Result.success(transformerRegistry)); when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); when(transformerRegistry.transform(any(), any())).thenReturn(Result.success(message)); var request = postDspRequestBuilder().processId("processId").serviceCall(serviceCall).build(); @@ -431,28 +516,10 @@ private PostDspRequest.Builder postDspRequestB .newInstance(TestProcessRemoteMessage.class, Object.class) .errorType("errorType") .token("token") + .protocol(protocol) .serviceCall((i, c) -> ServiceResult.success()); } } - private static class TestProcessRemoteMessage extends ProcessRemoteMessage { - - @Override - public Policy getPolicy() { - return null; - } - - public static class Builder extends ProcessRemoteMessage.Builder { - - public static Builder newInstance() { - return new Builder(); - } - - protected Builder() { - super(new TestProcessRemoteMessage()); - } - } - } - } diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImplTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImplTest.java new file mode 100644 index 00000000000..2f8af96b993 --- /dev/null +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/protocol/DspProtocolParserImplTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.http.protocol; + +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersionRegistry; +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersions; +import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP_V_2024_1; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DspProtocolParserImplTest { + + private final ProtocolVersionRegistry protocolVersionRegistry = mock(); + private final DspProtocolParserImpl parser = new DspProtocolParserImpl(protocolVersionRegistry); + private final ProtocolVersions protocolVersions = new ProtocolVersions(List.of(DspVersions.V_08, DspVersions.V_2024_1)); + + @BeforeEach + void beforeEach() { + when(protocolVersionRegistry.getAll()).thenReturn(protocolVersions); + } + + @Test + void shouldParseProtocol() { + assertThat(parser.parse(DATASPACE_PROTOCOL_HTTP)).isSucceeded() + .isEqualTo(DspVersions.V_08); + } + + @Test + void shouldParseProtocolWithVersion() { + assertThat(parser.parse(DATASPACE_PROTOCOL_HTTP_V_2024_1)).isSucceeded() + .isEqualTo(DspVersions.V_2024_1); + } + + @Test + void shouldFailToParseProtocol_whenTypeNotSupported() { + assertThat(parser.parse("myprotocol:v10")).isFailed(); + } + + @Test + void shouldFailToParseProtocol_whenVersionNotSupported() { + assertThat(parser.parse(DATASPACE_PROTOCOL_HTTP + ":wrongVersion")).isFailed(); + } +} diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java index 11982177832..043ee1dfde0 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java @@ -19,6 +19,7 @@ import jakarta.json.Json; import jakarta.json.JsonObject; import org.eclipse.edc.jsonld.TitaniumJsonLd; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; @@ -29,6 +30,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_08; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; @@ -39,6 +42,8 @@ class JsonLdRemoteMessageSerializerImplTest { private final TypeTransformerRegistry registry = mock(TypeTransformerRegistry.class); + private final DspProtocolTypeTransformerRegistry dspTransformerRegistry = mock(); + private final ObjectMapper mapper = mock(ObjectMapper.class); private final RemoteMessage message = mock(RemoteMessage.class); private JsonLdRemoteMessageSerializerImpl serializer; @@ -47,7 +52,9 @@ class JsonLdRemoteMessageSerializerImplTest { void setUp() { var jsonLdService = new TitaniumJsonLd(mock(Monitor.class)); jsonLdService.registerNamespace("schema", "http://schema/"); //needed for compaction - serializer = new JsonLdRemoteMessageSerializerImpl(registry, mapper, jsonLdService, "scope"); + when(registry.forContext(DSP_TRANSFORMER_CONTEXT_V_08)).thenReturn(registry); + serializer = new JsonLdRemoteMessageSerializerImpl(dspTransformerRegistry, mapper, jsonLdService, "scope"); + when(message.getProtocol()).thenReturn(DATASPACE_PROTOCOL_HTTP); } @Test @@ -55,6 +62,7 @@ void serialize_shouldReturnString_whenValidMessage() throws JsonProcessingExcept var json = messageJson(); var serialized = "serialized"; + when(dspTransformerRegistry.forProtocol(DATASPACE_PROTOCOL_HTTP)).thenReturn(Result.success(registry)); when(registry.transform(message, JsonObject.class)) .thenReturn(Result.success(json)); when(mapper.writeValueAsString(any(JsonObject.class))).thenReturn(serialized); @@ -70,6 +78,7 @@ void serialize_shouldReturnString_whenValidMessage() throws JsonProcessingExcept @Test void serialize_shouldThrowException_whenTransformationFails() { + when(dspTransformerRegistry.forProtocol(DATASPACE_PROTOCOL_HTTP)).thenReturn(Result.success(registry)); when(registry.transform(message, JsonObject.class)) .thenReturn(Result.failure("error")); @@ -81,6 +90,20 @@ void serialize_shouldThrowException_whenTransformationFails() { void serialize_shouldThrowException_whenSerializationFails() throws JsonProcessingException { var json = messageJson(); + when(dspTransformerRegistry.forProtocol(DATASPACE_PROTOCOL_HTTP)).thenReturn(Result.success(registry)); + when(registry.transform(message, JsonObject.class)) + .thenReturn(Result.success(json)); + when(mapper.writeValueAsString(any(JsonObject.class))).thenThrow(JsonProcessingException.class); + + assertThatThrownBy(() -> serializer.serialize(message)) + .isInstanceOf(EdcException.class); + } + + @Test + void serialize_shouldThrowException_whenProtocolParseFails() throws JsonProcessingException { + var json = messageJson(); + + when(dspTransformerRegistry.forProtocol(DATASPACE_PROTOCOL_HTTP)).thenReturn(Result.failure("failure")); when(registry.transform(message, JsonObject.class)) .thenReturn(Result.success(json)); when(mapper.writeValueAsString(any(JsonObject.class))).thenThrow(JsonProcessingException.class); diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java index 6a40393e5d1..16357da73bf 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java @@ -19,10 +19,12 @@ import okhttp3.MediaType; import okhttp3.ResponseBody; import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -30,12 +32,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -46,8 +50,15 @@ class JsonLdResponseBodyDeserializerTest { private final ObjectMapper objectMapper = mock(); private final JsonLd jsonLd = mock(); private final TypeTransformerRegistry transformerRegistry = mock(); + private final DspProtocolTypeTransformerRegistry dspTransformerRegistry = mock(); private final JsonLdResponseBodyDeserializer bodyExtractor = - new JsonLdResponseBodyDeserializer<>(Object.class, objectMapper, jsonLd, transformerRegistry); + new JsonLdResponseBodyDeserializer<>(Object.class, objectMapper, jsonLd, dspTransformerRegistry); + + + @BeforeEach + void beforeEach() { + when(dspTransformerRegistry.forProtocol(DATASPACE_PROTOCOL_HTTP)).thenReturn(Result.success(transformerRegistry)); + } @Test void shouldTransformBody() throws IOException { @@ -58,7 +69,7 @@ void shouldTransformBody() throws IOException { when(jsonLd.expand(any())).thenReturn(Result.success(expanded)); when(transformerRegistry.transform(any(), any())).thenReturn(Result.success(object)); - var result = bodyExtractor.extractBody(createResponseBody()); + var result = bodyExtractor.extractBody(createResponseBody(), DATASPACE_PROTOCOL_HTTP); assertThat(result).isSameAs(object); verify(transformerRegistry).transform(same(expanded), eq(Object.class)); @@ -68,7 +79,7 @@ void shouldTransformBody() throws IOException { void shouldThrowException_whenDeserializationDoesNotWork() throws IOException { doThrow(IOException.class).when(objectMapper).readValue(isA(InputStream.class), isA(Class.class)); - assertThatThrownBy(() -> bodyExtractor.extractBody(createResponseBody())).isInstanceOf(EdcException.class); + assertThatThrownBy(() -> bodyExtractor.extractBody(createResponseBody(), DATASPACE_PROTOCOL_HTTP)).isInstanceOf(EdcException.class); verifyNoInteractions(jsonLd, transformerRegistry); } @@ -78,8 +89,8 @@ void shouldThrowException_whenExpansionFails() throws IOException { when(objectMapper.readValue(isA(InputStream.class), isA(Class.class))).thenReturn(compacted); when(jsonLd.expand(any())).thenReturn(Result.failure("cannot expand")); - assertThatThrownBy(() -> bodyExtractor.extractBody(createResponseBody())).isInstanceOf(EdcException.class); - verifyNoInteractions(transformerRegistry); + assertThatThrownBy(() -> bodyExtractor.extractBody(createResponseBody(), DATASPACE_PROTOCOL_HTTP)).isInstanceOf(EdcException.class); + verify(transformerRegistry, times(0)).transform(any(), any()); } @Test @@ -90,7 +101,7 @@ void shouldThrowException_whenTransformationFails() throws IOException { when(jsonLd.expand(any())).thenReturn(Result.success(expanded)); when(transformerRegistry.transform(any(), any())).thenReturn(Result.failure("cannot transform")); - assertThatThrownBy(() -> bodyExtractor.extractBody(createResponseBody())).isInstanceOf(EdcException.class); + assertThatThrownBy(() -> bodyExtractor.extractBody(createResponseBody(), DATASPACE_PROTOCOL_HTTP)).isInstanceOf(EdcException.class); } @NotNull diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImplTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImplTest.java new file mode 100644 index 00000000000..7c43fb0baf7 --- /dev/null +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/transform/DspProtocolTypeTransformerRegistryImplTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.http.transform; + +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; +import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.junit.jupiter.api.Test; + +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_08; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DspProtocolTypeTransformerRegistryImplTest { + + private final TypeTransformerRegistry transformerRegistry = mock(); + private final DspProtocolParser protocolParser = mock(); + private final DspProtocolTypeTransformerRegistryImpl dspTransformerRegistry = new DspProtocolTypeTransformerRegistryImpl(transformerRegistry, DSP_TRANSFORMER_CONTEXT, protocolParser); + + @Test + void forProtocol() { + when(protocolParser.parse(DATASPACE_PROTOCOL_HTTP)).thenReturn(Result.success(DspVersions.V_08)); + when(transformerRegistry.forContext(DSP_TRANSFORMER_CONTEXT_V_08)).thenReturn(transformerRegistry); + assertThat(dspTransformerRegistry.forProtocol(DATASPACE_PROTOCOL_HTTP)).isSucceeded() + .isEqualTo(transformerRegistry); + } + +} diff --git a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/DspProtocolParser.java b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/DspProtocolParser.java new file mode 100644 index 00000000000..bfc8fa43d85 --- /dev/null +++ b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/DspProtocolParser.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.http.spi; + +import org.eclipse.edc.connector.controlplane.services.spi.protocol.ProtocolVersion; +import org.eclipse.edc.spi.result.Result; + +/** + * DSP protocol string parser + */ +public interface DspProtocolParser { + + /** + * Parses the DSP protocol string with format {@literal dataspace-protocol-http:} + * and extract the resulting {@link ProtocolVersion} + */ + Result parse(String protocol); +} diff --git a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/DspHttpRequestFactory.java b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/DspHttpRequestFactory.java index 1d0d1d72488..7346299f092 100644 --- a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/DspHttpRequestFactory.java +++ b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/DspHttpRequestFactory.java @@ -25,6 +25,13 @@ @FunctionalInterface public interface DspHttpRequestFactory { + default String removeTrailingSlash(String path) { + if (path.endsWith("/")) { + return path.substring(0, path.length() - 1); + } + return path; + } + /** * Create the request given the message and a {@link RequestPathProvider} * diff --git a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/response/DspHttpResponseBodyExtractor.java b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/response/DspHttpResponseBodyExtractor.java index 3c0da2800d7..f169b16f47f 100644 --- a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/response/DspHttpResponseBodyExtractor.java +++ b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/dispatcher/response/DspHttpResponseBodyExtractor.java @@ -24,7 +24,7 @@ @FunctionalInterface public interface DspHttpResponseBodyExtractor { - DspHttpResponseBodyExtractor NOOP = r -> null; + DspHttpResponseBodyExtractor NOOP = (r, p) -> null; /** * Extract the body from the Response @@ -32,5 +32,5 @@ public interface DspHttpResponseBodyExtractor { * @param responseBody the Response. * @return the body. */ - R extractBody(ResponseBody responseBody); + R extractBody(ResponseBody responseBody, String protocol); } diff --git a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/message/DspRequest.java b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/message/DspRequest.java index 283f4547e87..0d926115787 100644 --- a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/message/DspRequest.java +++ b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/message/DspRequest.java @@ -27,6 +27,7 @@ public class DspRequest { protected final Class inputClass; protected String token; protected String errorType; + protected String protocol; protected BiFunction> serviceCall; public DspRequest(Class inputClass, Class resultClass) { @@ -38,6 +39,10 @@ public String getToken() { return token; } + public String getProtocol() { + return protocol; + } + public Class getInputClass() { return inputClass; } @@ -67,6 +72,11 @@ public B token(String token) { return self(); } + public B protocol(String protocol) { + message.protocol = protocol; + return self(); + } + public B serviceCall(BiFunction> serviceCall) { message.serviceCall = serviceCall; return self(); @@ -80,6 +90,7 @@ public B errorType(String errorType) { public M build() { requireNonNull(message.serviceCall); requireNonNull(message.errorType); + requireNonNull(message.protocol); return message; } diff --git a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/types/HttpMessageProtocol.java b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/types/HttpMessageProtocol.java index 0b09280a305..c5e23f89bb0 100644 --- a/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/types/HttpMessageProtocol.java +++ b/data-protocols/dsp/dsp-http-spi/src/main/java/org/eclipse/edc/protocol/dsp/http/spi/types/HttpMessageProtocol.java @@ -14,11 +14,16 @@ package org.eclipse.edc.protocol.dsp.http.spi.types; +import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; + /** * Provides the name to be used as reference to the dataspace protocol in remote messages. */ public class HttpMessageProtocol { + // When not explicit the default will be v0.8 for backward compatibility public static final String DATASPACE_PROTOCOL_HTTP = "dataspace-protocol-http"; + public static final String DATASPACE_PROTOCOL_HTTP_SEPARATOR = ":"; + public static final String DATASPACE_PROTOCOL_HTTP_V_2024_1 = DATASPACE_PROTOCOL_HTTP + DATASPACE_PROTOCOL_HTTP_SEPARATOR + DspVersions.V_2024_1_VERSION; } \ No newline at end of file diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java index d0a083bef0f..22ecd0d3da1 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java @@ -39,6 +39,7 @@ import static org.eclipse.edc.protocol.dsp.spi.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_NEGOTIATION_TERMINATION_MESSAGE; import static org.eclipse.edc.protocol.dsp.spi.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_OFFER_MESSAGE; import static org.eclipse.edc.protocol.dsp.spi.type.DspNegotiationPropertyAndTypeNames.DSPACE_TYPE_CONTRACT_REQUEST_MESSAGE; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_08; import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1; /** @@ -78,5 +79,6 @@ public void initialize(ServiceExtensionContext context) { webService.registerResource(ApiContext.PROTOCOL, new DspNegotiationApiController20241(protocolService, dspRequestHandler)); versionRegistry.register(V_2024_1); + versionRegistry.register(V_08); } } diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController.java index c5a0ee3d3a5..b4867bdb30e 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController.java @@ -37,6 +37,7 @@ import org.eclipse.edc.protocol.dsp.http.spi.message.PostDspRequest; import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; import static org.eclipse.edc.protocol.dsp.negotiation.http.api.NegotiationApiPaths.AGREEMENT; import static org.eclipse.edc.protocol.dsp.negotiation.http.api.NegotiationApiPaths.BASE_PATH; import static org.eclipse.edc.protocol.dsp.negotiation.http.api.NegotiationApiPaths.CONTRACT_OFFER; @@ -64,12 +65,21 @@ public class DspNegotiationApiController { private final DspRequestHandler dspRequestHandler; + private final String protocol; private final ContractNegotiationProtocolService protocolService; public DspNegotiationApiController(ContractNegotiationProtocolService protocolService, DspRequestHandler dspRequestHandler) { + + this(protocolService, dspRequestHandler, DATASPACE_PROTOCOL_HTTP); + } + + public DspNegotiationApiController(ContractNegotiationProtocolService protocolService, + DspRequestHandler dspRequestHandler, + String protocol) { this.protocolService = protocolService; this.dspRequestHandler = dspRequestHandler; + this.protocol = protocol; } /** @@ -85,6 +95,7 @@ public Response getNegotiation(@PathParam("id") String id, @HeaderParam(AUTHORIZ var request = GetDspRequest.Builder.newInstance(ContractNegotiation.class) .id(id).token(token).serviceCall(protocolService::findById) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.getResource(request); @@ -106,6 +117,7 @@ public Response initialContractRequest(JsonObject jsonObject, @HeaderParam(AUTHO .token(token) .serviceCall(protocolService::notifyRequested) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.createResource(request); @@ -127,6 +139,7 @@ public Response initialContractOffer(JsonObject jsonObject, @HeaderParam(AUTHORI .token(token) .serviceCall(protocolService::notifyOffered) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.createResource(request); @@ -152,6 +165,7 @@ public Response contractRequest(@PathParam("id") String id, .token(token) .serviceCall(protocolService::notifyRequested) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -180,6 +194,7 @@ public Response createEvent(@PathParam("id") String id, case ACCEPTED -> protocolService.notifyAccepted(message, claimToken); }) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -205,6 +220,7 @@ public Response verifyAgreement(@PathParam("id") String id, .token(token) .serviceCall(protocolService::notifyVerified) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -230,6 +246,7 @@ public Response terminateNegotiation(@PathParam("id") String id, .token(token) .serviceCall(protocolService::notifyTerminated) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -255,6 +272,7 @@ public Response providerOffer(@PathParam("id") String id, .token(token) .serviceCall(protocolService::notifyOffered) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -280,6 +298,7 @@ public Response createAgreement(@PathParam("id") String id, .token(token) .serviceCall(protocolService::notifyAgreed) .errorType(DSPACE_TYPE_CONTRACT_NEGOTIATION_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController20241.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController20241.java index c02549e2a7a..504dd950134 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController20241.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/controller/DspNegotiationApiController20241.java @@ -22,6 +22,7 @@ import org.eclipse.edc.protocol.dsp.http.spi.message.DspRequestHandler; import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP_V_2024_1; import static org.eclipse.edc.protocol.dsp.negotiation.http.api.NegotiationApiPaths.BASE_PATH; /** @@ -33,6 +34,6 @@ public class DspNegotiationApiController20241 extends DspNegotiationApiController { public DspNegotiationApiController20241(ContractNegotiationProtocolService protocolService, DspRequestHandler dspRequestHandler) { - super(protocolService, dspRequestHandler); + super(protocolService, dspRequestHandler, DATASPACE_PROTOCOL_HTTP_V_2024_1); } } diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java index 05ebb872f1a..6af7bf789b6 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java @@ -24,14 +24,15 @@ import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.protocol.dsp.http.dispatcher.PostDspHttpRequestFactory; import org.eclipse.edc.protocol.dsp.http.serialization.JsonLdResponseBodyDeserializer; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.DspHttpRemoteMessageDispatcher; import org.eclipse.edc.protocol.dsp.http.spi.serialization.JsonLdRemoteMessageSerializer; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import static org.eclipse.edc.protocol.dsp.http.spi.dispatcher.response.DspHttpResponseBodyExtractor.NOOP; import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; @@ -51,11 +52,14 @@ public class DspNegotiationHttpDispatcherExtension implements ServiceExtension { private TypeManager typeManager; @Inject - private TypeTransformerRegistry transformerRegistry; + private DspProtocolTypeTransformerRegistry dspTransformerRegistry; @Inject private JsonLd jsonLd; + @Inject + private DspProtocolParser dspProtocolParser; + @Override public String name() { return NAME; @@ -64,31 +68,31 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { var contractNegotiationAckDeserializer = new JsonLdResponseBodyDeserializer<>( - ContractNegotiationAck.class, typeManager.getMapper(JSON_LD), jsonLd, transformerRegistry.forContext("dsp-api")); + ContractNegotiationAck.class, typeManager.getMapper(JSON_LD), jsonLd, dspTransformerRegistry); messageDispatcher.registerMessage( ContractAgreementMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.AGREEMENT), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.AGREEMENT), NOOP ); messageDispatcher.registerMessage( ContractAgreementVerificationMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.AGREEMENT + NegotiationApiPaths.VERIFICATION), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.AGREEMENT + NegotiationApiPaths.VERIFICATION), NOOP ); messageDispatcher.registerMessage( ContractNegotiationEventMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.EVENT), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.EVENT), NOOP ); messageDispatcher.registerMessage( ContractNegotiationTerminationMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.TERMINATION), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.TERMINATION), NOOP ); messageDispatcher.registerMessage( ContractRequestMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> { + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> { if (m.getType() == ContractRequestMessage.Type.INITIAL) { return NegotiationApiPaths.BASE_PATH + NegotiationApiPaths.INITIAL_CONTRACT_REQUEST; } else { @@ -99,7 +103,7 @@ public void initialize(ServiceExtensionContext context) { ); messageDispatcher.registerMessage( ContractOfferMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.CONTRACT_OFFER), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> NegotiationApiPaths.BASE_PATH + m.getProcessId() + NegotiationApiPaths.CONTRACT_OFFER), contractNegotiationAckDeserializer ); } diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationTransformExtension.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationTransformExtension.java index b6d15b7d811..ab6cc78c8d0 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationTransformExtension.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-transform/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/transform/DspNegotiationTransformExtension.java @@ -37,6 +37,9 @@ import java.util.Map; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_08; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_2024_1; + /** * Provides the transformers for negotiation message types via the {@link TypeTransformerRegistry}. */ @@ -55,9 +58,14 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_08); + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_2024_1); + } + + private void registerTransformers(String version) { var builderFactory = Json.createBuilderFactory(Map.of()); - var dspApiTransformerRegistry = registry.forContext("dsp-api"); + var dspApiTransformerRegistry = registry.forContext(version); dspApiTransformerRegistry.register(new JsonObjectFromContractAgreementMessageTransformer(builderFactory)); dspApiTransformerRegistry.register(new JsonObjectFromContractAgreementVerificationMessageTransformer(builderFactory)); dspApiTransformerRegistry.register(new JsonObjectFromContractNegotiationEventMessageTransformer(builderFactory)); @@ -74,4 +82,4 @@ public void initialize(ServiceExtensionContext context) { dspApiTransformerRegistry.register(new JsonObjectToContractOfferMessageTransformer()); dspApiTransformerRegistry.register(new JsonObjectToContractNegotiationAckTransformer()); } -} +} \ No newline at end of file diff --git a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/transform/DspProtocolTypeTransformerRegistry.java b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/transform/DspProtocolTypeTransformerRegistry.java new file mode 100644 index 00000000000..a6926c48ce0 --- /dev/null +++ b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/transform/DspProtocolTypeTransformerRegistry.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.protocol.dsp.spi.transform; + +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; + +/** + * Returns the right {@link TypeTransformerRegistry} for the provided dsp protocol {@literal dataspace-http-protocol:} + */ +public interface DspProtocolTypeTransformerRegistry { + + Result forProtocol(String protocol); +} diff --git a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/type/DspConstants.java b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/type/DspConstants.java index 54bbbb6f580..31f1e91f750 100644 --- a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/type/DspConstants.java +++ b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/type/DspConstants.java @@ -14,9 +14,17 @@ package org.eclipse.edc.protocol.dsp.spi.type; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_08_VERSION; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1_VERSION; + /** * Dataspace protocol constants. */ public interface DspConstants { + + String DSP_CONTEXT_SEPARATOR = ":"; String DSP_SCOPE = "DSP"; + String DSP_TRANSFORMER_CONTEXT = "dsp-api"; + String DSP_TRANSFORMER_CONTEXT_V_08 = DSP_TRANSFORMER_CONTEXT + DSP_CONTEXT_SEPARATOR + V_08_VERSION; + String DSP_TRANSFORMER_CONTEXT_V_2024_1 = DSP_TRANSFORMER_CONTEXT + DSP_CONTEXT_SEPARATOR + V_2024_1_VERSION; } diff --git a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/version/DspVersions.java b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/version/DspVersions.java index 75bfd38de27..f19aac3059c 100644 --- a/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/version/DspVersions.java +++ b/data-protocols/dsp/dsp-spi/src/main/java/org/eclipse/edc/protocol/dsp/spi/version/DspVersions.java @@ -22,4 +22,8 @@ public interface DspVersions { String V_2024_1_PATH = "/" + V_2024_1_VERSION; ProtocolVersion V_2024_1 = new ProtocolVersion(V_2024_1_VERSION, V_2024_1_PATH); + String V_08_VERSION = "v0.8"; + String V_08_PATH = "/"; + ProtocolVersion V_08 = new ProtocolVersion(V_08_VERSION, V_08_PATH); + } diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java index 527bb8b2dc8..696ad8f4799 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java @@ -35,6 +35,7 @@ import static org.eclipse.edc.protocol.dsp.spi.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_REQUEST_MESSAGE; import static org.eclipse.edc.protocol.dsp.spi.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_START_MESSAGE; import static org.eclipse.edc.protocol.dsp.spi.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_TERMINATION_MESSAGE; +import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_08; import static org.eclipse.edc.protocol.dsp.spi.version.DspVersions.V_2024_1; /** @@ -66,5 +67,6 @@ public void initialize(ServiceExtensionContext context) { webService.registerResource(ApiContext.PROTOCOL, new DspTransferProcessApiController20241(transferProcessProtocolService, dspRequestHandler)); versionRegistry.register(V_2024_1); + versionRegistry.register(V_08); } } diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController.java index 5050960b597..9344f14020d 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController.java @@ -36,6 +36,7 @@ import org.eclipse.edc.protocol.dsp.http.spi.message.PostDspRequest; import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; import static org.eclipse.edc.protocol.dsp.spi.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_COMPLETION_MESSAGE; import static org.eclipse.edc.protocol.dsp.spi.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_ERROR; import static org.eclipse.edc.protocol.dsp.spi.type.DspTransferProcessPropertyAndTypeNames.DSPACE_TYPE_TRANSFER_REQUEST_MESSAGE; @@ -60,10 +61,16 @@ public class DspTransferProcessApiController { private final TransferProcessProtocolService protocolService; private final DspRequestHandler dspRequestHandler; + private final String protocol; public DspTransferProcessApiController(TransferProcessProtocolService protocolService, DspRequestHandler dspRequestHandler) { + this(protocolService, dspRequestHandler, DATASPACE_PROTOCOL_HTTP); + } + + public DspTransferProcessApiController(TransferProcessProtocolService protocolService, DspRequestHandler dspRequestHandler, String protocol) { this.protocolService = protocolService; this.dspRequestHandler = dspRequestHandler; + this.protocol = protocol; } /** @@ -78,6 +85,7 @@ public Response getTransferProcess(@PathParam("id") String id, @HeaderParam(AUTH var request = GetDspRequest.Builder.newInstance(TransferProcess.class) .id(id).token(token).errorType(DSPACE_TYPE_TRANSFER_ERROR) .serviceCall(protocolService::findById) + .protocol(protocol) .build(); return dspRequestHandler.getResource(request); @@ -99,6 +107,7 @@ public Response initiateTransferProcess(JsonObject jsonObject, @HeaderParam(AUTH .expectedMessageType(DSPACE_TYPE_TRANSFER_REQUEST_MESSAGE) .serviceCall(protocolService::notifyRequested) .errorType(DSPACE_TYPE_TRANSFER_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.createResource(request); @@ -122,6 +131,7 @@ public Response transferProcessStart(@PathParam("id") String id, JsonObject json .token(token) .serviceCall(protocolService::notifyStarted) .errorType(DSPACE_TYPE_TRANSFER_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -145,6 +155,7 @@ public Response transferProcessCompletion(@PathParam("id") String id, JsonObject .token(token) .serviceCall(protocolService::notifyCompleted) .errorType(DSPACE_TYPE_TRANSFER_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -168,6 +179,7 @@ public Response transferProcessTermination(@PathParam("id") String id, JsonObjec .token(token) .serviceCall(protocolService::notifyTerminated) .errorType(DSPACE_TYPE_TRANSFER_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); @@ -191,6 +203,7 @@ public Response transferProcessSuspension(@PathParam("id") String id, JsonObject .token(token) .serviceCall(protocolService::notifySuspended) .errorType(DSPACE_TYPE_TRANSFER_ERROR) + .protocol(protocol) .build(); return dspRequestHandler.updateResource(request); diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController20241.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController20241.java index 702a6972ac9..49dd29dbd9a 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController20241.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/controller/DspTransferProcessApiController20241.java @@ -22,6 +22,7 @@ import org.eclipse.edc.protocol.dsp.http.spi.message.DspRequestHandler; import org.eclipse.edc.protocol.dsp.spi.version.DspVersions; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP_V_2024_1; import static org.eclipse.edc.protocol.dsp.transferprocess.http.api.TransferProcessApiPaths.BASE_PATH; @@ -34,6 +35,6 @@ public class DspTransferProcessApiController20241 extends DspTransferProcessApiController { public DspTransferProcessApiController20241(TransferProcessProtocolService protocolService, DspRequestHandler dspRequestHandler) { - super(protocolService, dspRequestHandler); + super(protocolService, dspRequestHandler, DATASPACE_PROTOCOL_HTTP_V_2024_1); } } diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java index ac492c88c5f..6fadce273d0 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java @@ -24,14 +24,15 @@ import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.protocol.dsp.http.dispatcher.PostDspHttpRequestFactory; import org.eclipse.edc.protocol.dsp.http.serialization.JsonLdResponseBodyDeserializer; +import org.eclipse.edc.protocol.dsp.http.spi.DspProtocolParser; import org.eclipse.edc.protocol.dsp.http.spi.dispatcher.DspHttpRemoteMessageDispatcher; import org.eclipse.edc.protocol.dsp.http.spi.serialization.JsonLdRemoteMessageSerializer; +import org.eclipse.edc.protocol.dsp.spi.transform.DspProtocolTypeTransformerRegistry; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import static org.eclipse.edc.protocol.dsp.http.spi.dispatcher.response.DspHttpResponseBodyExtractor.NOOP; import static org.eclipse.edc.protocol.dsp.transferprocess.http.dispatcher.TransferProcessApiPaths.BASE_PATH; @@ -61,11 +62,14 @@ public class DspTransferProcessDispatcherExtension implements ServiceExtension { private TypeManager typeManager; @Inject - private TypeTransformerRegistry transformerRegistry; + private DspProtocolTypeTransformerRegistry dspTransformerRegistry; @Inject private JsonLd jsonLd; + @Inject + private DspProtocolParser dspProtocolParser; + @Override public String name() { return NAME; @@ -75,27 +79,27 @@ public String name() { public void initialize(ServiceExtensionContext context) { messageDispatcher.registerMessage( TransferRequestMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> BASE_PATH + TRANSFER_INITIAL_REQUEST), - new JsonLdResponseBodyDeserializer<>(TransferProcessAck.class, typeManager.getMapper(JSON_LD), jsonLd, transformerRegistry.forContext("dsp-api")) + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> BASE_PATH + TRANSFER_INITIAL_REQUEST), + new JsonLdResponseBodyDeserializer<>(TransferProcessAck.class, typeManager.getMapper(JSON_LD), jsonLd, dspTransformerRegistry) ); messageDispatcher.registerMessage( TransferCompletionMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> BASE_PATH + m.getProcessId() + TRANSFER_COMPLETION), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> BASE_PATH + m.getProcessId() + TRANSFER_COMPLETION), NOOP ); messageDispatcher.registerMessage( TransferStartMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> BASE_PATH + m.getProcessId() + TRANSFER_START), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> BASE_PATH + m.getProcessId() + TRANSFER_START), NOOP ); messageDispatcher.registerMessage( TransferSuspensionMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> BASE_PATH + m.getProcessId() + TRANSFER_SUSPENSION), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> BASE_PATH + m.getProcessId() + TRANSFER_SUSPENSION), NOOP ); messageDispatcher.registerMessage( TransferTerminationMessage.class, - new PostDspHttpRequestFactory<>(remoteMessageSerializer, m -> BASE_PATH + m.getProcessId() + TRANSFER_TERMINATION), + new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> BASE_PATH + m.getProcessId() + TRANSFER_TERMINATION), NOOP ); } diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java index 1c9f221fb3c..af2ce91421c 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java @@ -14,6 +14,7 @@ package org.eclipse.edc.protocol.dsp.transferprocess.transform; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.Json; import org.eclipse.edc.protocol.dsp.transferprocess.transform.type.from.JsonObjectFromTransferCompletionMessageTransformer; import org.eclipse.edc.protocol.dsp.transferprocess.transform.type.from.JsonObjectFromTransferProcessTransformer; @@ -37,6 +38,8 @@ import java.util.Map; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_08; +import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_TRANSFORMER_CONTEXT_V_2024_1; import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD; /** @@ -60,10 +63,16 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var builderFactory = Json.createBuilderFactory(Map.of()); var objectMapper = typeManager.getMapper(JSON_LD); - var dspRegistry = registry.forContext("dsp-api"); + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_08, objectMapper); + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_2024_1, objectMapper); + } + + private void registerTransformers(String version, ObjectMapper objectMapper) { + var builderFactory = Json.createBuilderFactory(Map.of()); + + var dspRegistry = registry.forContext(version); dspRegistry.register(new JsonObjectFromTransferProcessTransformer(builderFactory)); dspRegistry.register(new JsonObjectFromTransferStartMessageTransformer(builderFactory)); @@ -80,4 +89,5 @@ public void initialize(ServiceExtensionContext context) { dspRegistry.register(new JsonObjectToTransferProcessAckTransformer()); dspRegistry.register(new JsonObjectToTransferSuspensionMessageTransformer(objectMapper)); } -} + +} \ No newline at end of file diff --git a/data-protocols/dsp/dsp-version/dsp-version-http-api/src/main/java/org/eclipse/edc/protocol/dsp/version/http/api/DspVersionApiController.java b/data-protocols/dsp/dsp-version/dsp-version-http-api/src/main/java/org/eclipse/edc/protocol/dsp/version/http/api/DspVersionApiController.java index 587d93061e9..6d97cce5234 100644 --- a/data-protocols/dsp/dsp-version/dsp-version-http-api/src/main/java/org/eclipse/edc/protocol/dsp/version/http/api/DspVersionApiController.java +++ b/data-protocols/dsp/dsp-version/dsp-version-http-api/src/main/java/org/eclipse/edc/protocol/dsp/version/http/api/DspVersionApiController.java @@ -26,6 +26,7 @@ import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.eclipse.edc.protocol.dsp.http.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; import static org.eclipse.edc.protocol.dsp.spi.type.DspVersionPropertyAndTypeNames.DSPACE_TYPE_VERSIONS_ERROR; @Produces(APPLICATION_JSON) @@ -46,6 +47,7 @@ public Response getProtocolVersions(@HeaderParam(AUTHORIZATION) String token) { .token(token) .errorType(DSPACE_TYPE_VERSIONS_ERROR) .serviceCall((id, tokenRepresentation) -> service.getAll(tokenRepresentation)) + .protocol(DATASPACE_PROTOCOL_HTTP) .build(); return requestHandler.getResource(request); diff --git a/extensions/control-plane/api/management-api/management-api-test-fixtures/src/testFixtures/java/org/eclipse/edc/connector/controlplane/test/system/utils/Participant.java b/extensions/control-plane/api/management-api/management-api-test-fixtures/src/testFixtures/java/org/eclipse/edc/connector/controlplane/test/system/utils/Participant.java index e175f2b64cc..0ae3e3f95a9 100644 --- a/extensions/control-plane/api/management-api/management-api-test-fixtures/src/testFixtures/java/org/eclipse/edc/connector/controlplane/test/system/utils/Participant.java +++ b/extensions/control-plane/api/management-api/management-api-test-fixtures/src/testFixtures/java/org/eclipse/edc/connector/controlplane/test/system/utils/Participant.java @@ -83,6 +83,10 @@ public String getProtocol() { return protocol; } + public void setProtocol(String protocol) { + this.protocol = protocol; + } + public Endpoint getProtocolEndpoint() { return protocolEndpoint; } diff --git a/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProcessRemoteMessage.java b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProcessRemoteMessage.java index f5d765234d9..ded34608a36 100644 --- a/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProcessRemoteMessage.java +++ b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProcessRemoteMessage.java @@ -27,13 +27,12 @@ *

* The {@link #processId} represent the ID of the process on the recipient part. */ -public abstract class ProcessRemoteMessage implements RemoteMessage { +public abstract class ProcessRemoteMessage extends ProtocolRemoteMessage { protected String id; protected String processId; protected String consumerPid; protected String providerPid; - protected String protocol = "unknown"; protected String counterPartyAddress; protected String counterPartyId; @@ -52,17 +51,7 @@ public abstract class ProcessRemoteMessage implements RemoteMessage { public @NotNull String getId() { return id; } - - @Override - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - Objects.requireNonNull(protocol); - this.protocol = protocol; - } - + /** * Returns the process id for this instance, that could be consumerPid or providerPid. * diff --git a/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProtocolRemoteMessage.java b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProtocolRemoteMessage.java new file mode 100644 index 00000000000..7d690aa7b36 --- /dev/null +++ b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/message/ProtocolRemoteMessage.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.spi.types.domain.message; + +import java.util.Objects; + +public abstract class ProtocolRemoteMessage implements RemoteMessage { + + protected String protocol = "unknown"; + + @Override + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + Objects.requireNonNull(protocol); + this.protocol = protocol; + } +} diff --git a/spi/control-plane/catalog-spi/src/main/java/org/eclipse/edc/connector/controlplane/catalog/spi/CatalogRequestMessage.java b/spi/control-plane/catalog-spi/src/main/java/org/eclipse/edc/connector/controlplane/catalog/spi/CatalogRequestMessage.java index 861816cbaf0..9011e3d032e 100644 --- a/spi/control-plane/catalog-spi/src/main/java/org/eclipse/edc/connector/controlplane/catalog/spi/CatalogRequestMessage.java +++ b/spi/control-plane/catalog-spi/src/main/java/org/eclipse/edc/connector/controlplane/catalog/spi/CatalogRequestMessage.java @@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.types.domain.message.RemoteMessage; +import org.eclipse.edc.spi.types.domain.message.ProtocolRemoteMessage; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -30,7 +30,7 @@ * A request for a participant's {@link Catalog}. */ @JsonDeserialize(builder = CatalogRequestMessage.Builder.class) -public class CatalogRequestMessage implements RemoteMessage { +public class CatalogRequestMessage extends ProtocolRemoteMessage { private final Policy policy; private List additionalScopes = new ArrayList<>(); diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java index bc5f9ea166f..4178e1ae2f3 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java @@ -351,6 +351,38 @@ protected Vault getDataplaneVault() { } } + @Nested + @EndToEndTest + class InMemoryV2024Rev1 extends Tests { + + + @RegisterExtension + static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( + Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); + @RegisterExtension + static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( + Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); + @RegisterExtension + static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( + Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); + + // TODO: replace with something better. Temporary hack + @BeforeAll + static void beforeAll() { + CONSUMER.setProtocol("dataspace-protocol-http:2024/1"); + } + + @AfterAll + static void afterAll() { + CONSUMER.setProtocol("dataspace-protocol-http"); + } + + @Override + protected Vault getDataplaneVault() { + return PROVIDER_DATA_PLANE.getService(Vault.class); + } + } + @Nested @EndToEndTest class EmbeddedDataPlane extends Tests {