diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/configuration/OrdResourcesProviderConfiguration.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/configuration/OrdResourcesProviderConfiguration.java deleted file mode 100644 index dc81ce1..0000000 --- a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/configuration/OrdResourcesProviderConfiguration.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * © 2026 SAP SE or an SAP affiliate company. All rights reserved. - */ -package com.sap.cds.feature.ord.configuration; - -import static com.sap.cds.feature.ord.common.Utils.Streams.asList; -import static com.sap.cds.services.runtime.ExtendedServiceLoader.loadAll; - -import com.sap.cds.feature.ord.clients.impl.MtxSidecarClientImpl; -import com.sap.cds.feature.ord.processor.CdsOrdNodeProcessor; -import com.sap.cds.feature.ord.provider.impl.DynamicOrdResourcesProviderImpl; -import com.sap.cds.feature.ord.provider.impl.StaticOrdResourcesProviderImpl; -import com.sap.cds.services.runtime.CdsRuntime; -import com.sap.cds.services.runtime.CdsRuntimeConfiguration; -import com.sap.cds.services.runtime.CdsRuntimeConfigurer; -import com.sap.cds.services.utils.model.DynamicModelUtils; - -public class OrdResourcesProviderConfiguration implements CdsRuntimeConfiguration { - - @Override - public void providers(CdsRuntimeConfigurer configurer) { - CdsRuntime cdsRuntime = configurer.getCdsRuntime(); - DynamicModelUtils dynamicModelUtils = new DynamicModelUtils(cdsRuntime); - - configurer.provider( - new StaticOrdResourcesProviderImpl(cdsRuntime, asList(loadAll(CdsOrdNodeProcessor.class, cdsRuntime)))); - - if (dynamicModelUtils.isModelProviderEnabled()) { - configurer.provider(new DynamicOrdResourcesProviderImpl( - cdsRuntime, - new MtxSidecarClientImpl(cdsRuntime), - dynamicModelUtils, - asList(loadAll(CdsOrdNodeProcessor.class, cdsRuntime)))); - } - } -} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/OrdResourcesProvider.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/OrdResourcesProvider.java deleted file mode 100644 index 4125d58..0000000 --- a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/OrdResourcesProvider.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * © 2026 SAP SE or an SAP affiliate company. All rights reserved. - */ -package com.sap.cds.feature.ord.provider; - -import com.sap.cds.feature.ord.model.OrdDocument; -import com.sap.cds.services.runtime.CdsProvider; -import java.io.InputStream; - -public interface OrdResourcesProvider extends CdsProvider { - - /** - * Provides the {@link OrdDocument} for the given CAP service. - * - * @return InputStream - */ - InputStream read(String resource, String perspective); -} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/impl/DynamicOrdResourcesProviderImpl.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/impl/DynamicOrdResourcesProviderImpl.java deleted file mode 100644 index c1ba329..0000000 --- a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/impl/DynamicOrdResourcesProviderImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * © 2026 SAP SE or an SAP affiliate company. All rights reserved. - */ -package com.sap.cds.feature.ord.provider.impl; - -import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; -import static com.sap.cds.feature.ord.common.Utils.Resources.asOrdJsonInputStream; -import static org.apache.commons.io.FilenameUtils.getBaseName; -import static org.apache.commons.io.FilenameUtils.getExtension; - -import com.sap.cds.adapter.edmx.EdmxV4Provider; -import com.sap.cds.feature.ord.clients.MtxSidecarClient; -import com.sap.cds.feature.ord.processor.CdsOrdNodeProcessor; -import com.sap.cds.feature.ord.provider.OrdResourcesProvider; -import com.sap.cds.services.runtime.CdsRuntime; -import com.sap.cds.services.utils.model.DynamicModelUtils; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.List; -import java.util.Objects; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class DynamicOrdResourcesProviderImpl implements OrdResourcesProvider { - - private static final String EDMX_EXTENSION = "edmx"; - private static final String ORD_DOCUMENT_PATH = "documents/ord-document"; - - private final CdsRuntime cdsRuntime; - private final MtxSidecarClient mtxSidecarClient; - private final DynamicModelUtils dynamicModelUtils; - private final List cdsOrdNodeProcessors; - - private OrdResourcesProvider previous; - - @Override - public void setPrevious(OrdResourcesProvider previous) { - this.previous = previous; - } - - @Override - public InputStream read(String resource, String perspective) { - return !dynamicModelUtils.useStaticModel() && Objects.equals(PERSPECTIVE_SYSTEM_INSTANCE, perspective) - ? this.loadResource(resource) - : this.previous.read(resource, perspective); - } - - private InputStream loadResource(String resource) { - if (EDMX_EXTENSION.equalsIgnoreCase(getExtension(resource))) { - return cdsRuntime.getProvider(EdmxV4Provider.class).getEdmx(getBaseName(resource)); - } - - return this.loadFromMTXSidecar(resource); - } - - private InputStream loadFromMTXSidecar(String resource) { - return Objects.equals(ORD_DOCUMENT_PATH, resource) - ? asOrdJsonInputStream( - new ByteArrayInputStream(mtxSidecarClient.getOrdDocument()), cdsOrdNodeProcessors) - : new ByteArrayInputStream(mtxSidecarClient.getOrdResourceDefinition(resource)); - } -} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/impl/StaticOrdResourcesProviderImpl.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/impl/StaticOrdResourcesProviderImpl.java deleted file mode 100644 index 3eced42..0000000 --- a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/provider/impl/StaticOrdResourcesProviderImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * © 2026 SAP SE or an SAP affiliate company. All rights reserved. - */ -package com.sap.cds.feature.ord.provider.impl; - -import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; -import static com.sap.cds.feature.ord.common.Utils.CdsRuntimeProperties.getOrdProperties; -import static com.sap.cds.feature.ord.common.Utils.Resources.asOrdJsonInputStream; -import static com.sap.cds.feature.ord.common.Utils.Resources.getResourceAsStream; -import static java.util.Objects.nonNull; -import static org.apache.commons.io.FilenameUtils.concat; -import static org.apache.commons.io.FilenameUtils.getBaseName; -import static org.apache.commons.io.FilenameUtils.getExtension; -import static org.apache.commons.io.FilenameUtils.normalize; - -import com.sap.cds.adapter.edmx.EdmxV4Provider; -import com.sap.cds.feature.ord.processor.CdsOrdNodeProcessor; -import com.sap.cds.feature.ord.provider.OrdResourcesProvider; -import com.sap.cds.services.runtime.CdsRuntime; -import java.io.InputStream; -import java.util.List; -import java.util.Objects; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class StaticOrdResourcesProviderImpl implements OrdResourcesProvider { - - private static final String EDMX_EXTENSION = "edmx"; - - private final CdsRuntime cdsRuntime; - private final List cdsOrdNodeProcessors; - - @Override - public InputStream read(String resource, String perspective) { - if (nonNull(perspective) && !Objects.equals(PERSPECTIVE_SYSTEM_VERSION, perspective)) { - throw new IllegalArgumentException("Perspective '%s' not supported".formatted(perspective)); - } - - String normalized = normalize(resource.replace(":", "_")); - String ordResourcesRoot = getOrdProperties(cdsRuntime).getOrdResourcesRoot(); - String ordDocumentRelativePath = getOrdProperties(cdsRuntime).getOrdDocumentPath(); - String ordDocumentAbsolutePath = concat(ordResourcesRoot, ordDocumentRelativePath); - - return Objects.equals("documents/ord-document", normalized) - ? asOrdJsonInputStream(getResourceAsStream(ordDocumentAbsolutePath), cdsOrdNodeProcessors) - : loadResourceAsStream(concat(ordResourcesRoot, normalized)); - } - - private InputStream loadResourceAsStream(String path) { - if (EDMX_EXTENSION.equalsIgnoreCase(getExtension(path))) { - return cdsRuntime.getProvider(EdmxV4Provider.class).getEdmx(getBaseName(path)); - } - - return getResourceAsStream(path); - } -} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/OrdResolver.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/OrdResolver.java new file mode 100644 index 0000000..95a06a5 --- /dev/null +++ b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/OrdResolver.java @@ -0,0 +1,13 @@ +package com.sap.cds.feature.ord.resolver; + +import com.sap.cds.services.runtime.CdsRuntimeAware; +import java.io.InputStream; + +public interface OrdResolver extends CdsRuntimeAware { + + int order(); + + InputStream resolve(String resource, String perspective); + + boolean isApplicable(String resource, String perspective); +} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdDocumentResolver.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdDocumentResolver.java new file mode 100644 index 0000000..89bc2fc --- /dev/null +++ b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdDocumentResolver.java @@ -0,0 +1,57 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; +import static com.sap.cds.feature.ord.common.Utils.Resources.asOrdJsonInputStream; +import static com.sap.cds.feature.ord.common.Utils.Streams.asList; +import static com.sap.cds.services.runtime.ExtendedServiceLoader.loadAll; +import static org.apache.commons.io.FilenameUtils.normalize; + +import com.sap.cds.feature.ord.clients.MtxSidecarClient; +import com.sap.cds.feature.ord.clients.impl.MtxSidecarClientImpl; +import com.sap.cds.feature.ord.processor.CdsOrdNodeProcessor; +import com.sap.cds.feature.ord.resolver.OrdResolver; +import com.sap.cds.services.runtime.CdsRuntime; +import com.sap.cds.services.utils.model.DynamicModelUtils; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +public class DynamicOrdDocumentResolver implements OrdResolver { + + private CdsRuntime runtime; + private MtxSidecarClient mtxSidecarClient; + private DynamicModelUtils dynamicModelUtils; + + @Override + public void setCdsRuntime(CdsRuntime runtime) { + this.runtime = runtime; + this.dynamicModelUtils = new DynamicModelUtils(runtime); + this.mtxSidecarClient = new MtxSidecarClientImpl(runtime); + } + + @Override + public int order() { + return Integer.MAX_VALUE; + } + + @Override + public InputStream resolve(String resource, String perspective) { + return asOrdJsonInputStream( + new ByteArrayInputStream(mtxSidecarClient.getOrdDocument()), + asList(loadAll(CdsOrdNodeProcessor.class, runtime))); + } + + @Override + public boolean isApplicable(String resource, String perspective) { + return !dynamicModelUtils.useStaticModel() // + && Objects.equals(PERSPECTIVE_SYSTEM_INSTANCE, perspective) // + && Objects.equals("documents/ord-document", normalize(resource.replace(":", "_"))); + } +} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdResourceDefinitionResolver.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdResourceDefinitionResolver.java new file mode 100644 index 0000000..69d631a --- /dev/null +++ b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdResourceDefinitionResolver.java @@ -0,0 +1,60 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; +import static org.apache.commons.io.FilenameUtils.getBaseName; +import static org.apache.commons.io.FilenameUtils.getExtension; +import static org.apache.commons.io.FilenameUtils.normalize; + +import com.sap.cds.adapter.edmx.EdmxV4Provider; +import com.sap.cds.feature.ord.clients.MtxSidecarClient; +import com.sap.cds.feature.ord.clients.impl.MtxSidecarClientImpl; +import com.sap.cds.feature.ord.resolver.OrdResolver; +import com.sap.cds.services.runtime.CdsRuntime; +import com.sap.cds.services.utils.model.DynamicModelUtils; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +public class DynamicOrdResourceDefinitionResolver implements OrdResolver { + + private static final String EDMX_EXTENSION = "edmx"; + + private CdsRuntime runtime; + private MtxSidecarClient mtxSidecarClient; + private DynamicModelUtils dynamicModelUtils; + + @Override + public void setCdsRuntime(CdsRuntime runtime) { + this.runtime = runtime; + this.dynamicModelUtils = new DynamicModelUtils(runtime); + this.mtxSidecarClient = new MtxSidecarClientImpl(runtime); + } + + @Override + public int order() { + return Integer.MAX_VALUE; + } + + @Override + public InputStream resolve(String resource, String perspective) { + if (EDMX_EXTENSION.equalsIgnoreCase(getExtension(resource))) { + return runtime.getProvider(EdmxV4Provider.class).getEdmx(getBaseName(resource)); + } + + return new ByteArrayInputStream(mtxSidecarClient.getOrdResourceDefinition(resource)); + } + + @Override + public boolean isApplicable(String resource, String perspective) { + return !dynamicModelUtils.useStaticModel() // + && Objects.equals(PERSPECTIVE_SYSTEM_INSTANCE, perspective) // + && !Objects.equals("documents/ord-document", normalize(resource.replace(":", "_"))); + } +} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdDocumentResolver.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdDocumentResolver.java new file mode 100644 index 0000000..43d62fe --- /dev/null +++ b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdDocumentResolver.java @@ -0,0 +1,54 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; +import static com.sap.cds.feature.ord.common.Utils.CdsRuntimeProperties.getOrdProperties; +import static com.sap.cds.feature.ord.common.Utils.Resources.asOrdJsonInputStream; +import static com.sap.cds.feature.ord.common.Utils.Resources.getResourceAsStream; +import static com.sap.cds.feature.ord.common.Utils.Streams.asList; +import static com.sap.cds.services.runtime.ExtendedServiceLoader.loadAll; +import static org.apache.commons.io.FilenameUtils.concat; +import static org.apache.commons.io.FilenameUtils.normalize; + +import com.sap.cds.feature.ord.processor.CdsOrdNodeProcessor; +import com.sap.cds.feature.ord.resolver.OrdResolver; +import com.sap.cds.services.environment.CdsProperties.OpenResourceDiscovery; +import com.sap.cds.services.runtime.CdsRuntime; +import java.io.InputStream; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +public class StaticOrdDocumentResolver implements OrdResolver { + + private CdsRuntime runtime; + + @Override + public void setCdsRuntime(CdsRuntime runtime) { + this.runtime = runtime; + } + + @Override + public int order() { + return Integer.MAX_VALUE; + } + + @Override + public InputStream resolve(String resource, String perspective) { + OpenResourceDiscovery properties = getOrdProperties(runtime); + + return asOrdJsonInputStream( + getResourceAsStream(concat(properties.getOrdResourcesRoot(), properties.getOrdDocumentPath())), + asList(loadAll(CdsOrdNodeProcessor.class, runtime))); + } + + @Override + public boolean isApplicable(String resource, String perspective) { + return Objects.equals(PERSPECTIVE_SYSTEM_VERSION, perspective) + && Objects.equals("documents/ord-document", normalize(resource.replace(":", "_"))); + } +} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdResourceDefinitionResolver.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdResourceDefinitionResolver.java new file mode 100644 index 0000000..bcd1d04 --- /dev/null +++ b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdResourceDefinitionResolver.java @@ -0,0 +1,63 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; +import static com.sap.cds.feature.ord.common.Utils.CdsRuntimeProperties.getOrdProperties; +import static com.sap.cds.feature.ord.common.Utils.Resources.getResourceAsStream; +import static com.sap.cds.feature.ord.common.Utils.Resources.resourceExists; +import static org.apache.commons.io.FilenameUtils.concat; +import static org.apache.commons.io.FilenameUtils.getBaseName; +import static org.apache.commons.io.FilenameUtils.getExtension; +import static org.apache.commons.io.FilenameUtils.normalize; +import static org.apache.commons.lang3.StringUtils.isEmpty; + +import com.sap.cds.adapter.edmx.EdmxV4Provider; +import com.sap.cds.feature.ord.resolver.OrdResolver; +import com.sap.cds.services.runtime.CdsRuntime; +import java.io.InputStream; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +public class StaticOrdResourceDefinitionResolver implements OrdResolver { + + private static final String EDMX_EXTENSION = "edmx"; + + private CdsRuntime runtime; + + @Override + public void setCdsRuntime(CdsRuntime runtime) { + this.runtime = runtime; + } + + @Override + public int order() { + return Integer.MAX_VALUE; + } + + @Override + public InputStream resolve(String resource, String perspective) { + String path = resolveResourcePath(resource); + + if (EDMX_EXTENSION.equalsIgnoreCase(getExtension(path))) { + return runtime.getProvider(EdmxV4Provider.class).getEdmx(getBaseName(path)); + } + + return getResourceAsStream(path); + } + + @Override + public boolean isApplicable(String resource, String perspective) { + return resourceExists(resolveResourcePath(resource)) + && (isEmpty(perspective) || Objects.equals(PERSPECTIVE_SYSTEM_VERSION, perspective)) + && !Objects.equals("documents/ord-document", normalize(resource.replace(":", "_"))); + } + + private String resolveResourcePath(String resource) { + return concat(getOrdProperties(runtime).getOrdResourcesRoot(), normalize(resource.replace(":", "_"))); + } +} diff --git a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/servlet/DocumentsServlet.java b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/servlet/DocumentsServlet.java index 64df3f0..322946c 100644 --- a/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/servlet/DocumentsServlet.java +++ b/cds-feature-ord/src/main/java/com/sap/cds/feature/ord/servlet/DocumentsServlet.java @@ -4,17 +4,23 @@ package com.sap.cds.feature.ord.servlet; import static com.sap.cds.feature.ord.common.Constants.HEADER_LOCAL_TENANT_ID; +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; import static com.sap.cds.feature.ord.common.Utils.Http.handleException; import static com.sap.cds.feature.ord.common.Utils.Http.header; -import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; +import static com.sap.cds.feature.ord.common.Utils.Streams.asList; +import static com.sap.cds.services.ErrorStatuses.NOT_FOUND; +import static com.sap.cds.services.runtime.ExtendedServiceLoader.loadAll; import static jakarta.servlet.http.HttpServletResponse.SC_OK; +import static java.util.Comparator.comparingInt; import static org.apache.commons.io.FilenameUtils.getExtension; +import static org.apache.commons.lang3.StringUtils.firstNonEmpty; import static org.apache.http.entity.ContentType.APPLICATION_JSON; import static org.apache.http.entity.ContentType.APPLICATION_XML; import static org.apache.http.entity.ContentType.TEXT_PLAIN; import com.sap.cds.feature.ord.provider.AuthenticationManagerProvider; -import com.sap.cds.feature.ord.provider.OrdResourcesProvider; +import com.sap.cds.feature.ord.resolver.OrdResolver; +import com.sap.cds.services.ServiceException; import com.sap.cds.services.runtime.CdsRuntime; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; @@ -60,16 +66,14 @@ private void process(HttpServletRequest request, HttpServletResponse response) { private void processDocument(HttpServletRequest request, HttpServletResponse response) throws IOException { String path = normalize(request.getPathInfo()); - String perspective = request.getParameter("perspective"); ContentType contentType = determineContentType(request.getPathInfo()); - OrdResourcesProvider ordResourcesProvider = cdsRuntime.getProvider(OrdResourcesProvider.class); - - try (InputStream stream = ordResourcesProvider.read(path, perspective)) { - if (stream == null) { - response.setStatus(SC_NOT_FOUND); - return; - } + String perspective = firstNonEmpty(request.getParameter("perspective"), PERSPECTIVE_SYSTEM_VERSION); + OrdResolver resolver = asList(loadAll(OrdResolver.class, cdsRuntime)).stream() + .filter(provider -> provider.isApplicable(path, perspective)) + .min(comparingInt(OrdResolver::order)) + .orElseThrow(() -> new ServiceException(NOT_FOUND, "Not Found")); + try (InputStream stream = resolver.resolve(path, perspective)) { response.setStatus(SC_OK); response.setContentType(contentType.getMimeType()); response.setCharacterEncoding(contentType.getCharset().toString()); diff --git a/cds-feature-ord/src/main/resources/META-INF/services/com.sap.cds.feature.ord.resolver.OrdResolver b/cds-feature-ord/src/main/resources/META-INF/services/com.sap.cds.feature.ord.resolver.OrdResolver new file mode 100644 index 0000000..683793d --- /dev/null +++ b/cds-feature-ord/src/main/resources/META-INF/services/com.sap.cds.feature.ord.resolver.OrdResolver @@ -0,0 +1,4 @@ +com.sap.cds.feature.ord.resolver.impl.StaticOrdDocumentResolver +com.sap.cds.feature.ord.resolver.impl.DynamicOrdDocumentResolver +com.sap.cds.feature.ord.resolver.impl.StaticOrdResourceDefinitionResolver +com.sap.cds.feature.ord.resolver.impl.DynamicOrdResourceDefinitionResolver \ No newline at end of file diff --git a/cds-feature-ord/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration b/cds-feature-ord/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration index e0ac634..3ef5396 100644 --- a/cds-feature-ord/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration +++ b/cds-feature-ord/src/main/resources/META-INF/services/com.sap.cds.services.runtime.CdsRuntimeConfiguration @@ -1,2 +1 @@ -com.sap.cds.feature.ord.configuration.OrdResourcesProviderConfiguration com.sap.cds.feature.ord.configuration.AuthenticationManagerProviderConfiguration \ No newline at end of file diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/common/OrdJsonInputStreamTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/common/OrdJsonInputStreamTest.java index 1f95631..fdad7c1 100644 --- a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/common/OrdJsonInputStreamTest.java +++ b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/common/OrdJsonInputStreamTest.java @@ -6,8 +6,6 @@ import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; import static com.sap.cds.feature.ord.common.Utils.CdsRuntimeProperties.getOrdProperties; import static com.sap.cds.feature.ord.common.Utils.Resources.getResourceAsStream; -import static com.sap.cds.feature.ord.common.Utils.Streams.asList; -import static com.sap.cds.services.runtime.ExtendedServiceLoader.loadAll; import static com.sap.cds.services.utils.cert.UclAuthUtils.AccessStrategy.MTLS; import static org.apache.commons.io.FilenameUtils.concat; import static org.apache.commons.io.FilenameUtils.getBaseName; @@ -15,9 +13,8 @@ import static org.mockito.Mockito.mock; import com.fasterxml.jackson.databind.JsonNode; -import com.sap.cds.feature.ord.processor.CdsOrdNodeProcessor; import com.sap.cds.feature.ord.provider.AuthenticationManagerProvider; -import com.sap.cds.feature.ord.provider.impl.StaticOrdResourcesProviderImpl; +import com.sap.cds.feature.ord.resolver.impl.StaticOrdDocumentResolver; import com.sap.cds.impl.parser.JsonParser; import com.sap.cds.services.runtime.CdsRuntime; import com.sap.cds.services.runtime.CdsRuntimeConfigurer; @@ -48,10 +45,9 @@ void setUp() { void processingOrdDocumentIsSuccessful() throws IOException { String ordDocumentPath = getOrdProperties(cdsRuntime).getOrdDocumentPath(); String document = concat("documents", getBaseName(ordDocumentPath)); - StaticOrdResourcesProviderImpl provider = - new StaticOrdResourcesProviderImpl(cdsRuntime, asList(loadAll(CdsOrdNodeProcessor.class, cdsRuntime))); + StaticOrdDocumentResolver resolver = new StaticOrdDocumentResolver(cdsRuntime); - try (InputStream is = provider.read(document, PERSPECTIVE_SYSTEM_VERSION)) { + try (InputStream is = resolver.resolve(document, PERSPECTIVE_SYSTEM_VERSION)) { JsonNode actual = JsonParser.parseJson(new String(is.readAllBytes())); JsonNode expected = load("ord/ord-document-target.json"); diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/configuration/OrdResourcesProviderConfigurationTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/configuration/OrdResourcesProviderConfigurationTest.java deleted file mode 100644 index b247589..0000000 --- a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/configuration/OrdResourcesProviderConfigurationTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * © 2026 SAP SE or an SAP affiliate company. All rights reserved. - */ -package com.sap.cds.feature.ord.configuration; - -import static com.sap.cds.services.runtime.ExtendedServiceLoader.loadAll; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import com.sap.cds.feature.ord.processor.CdsOrdNodeProcessor; -import com.sap.cds.feature.ord.provider.impl.DynamicOrdResourcesProviderImpl; -import com.sap.cds.feature.ord.provider.impl.StaticOrdResourcesProviderImpl; -import com.sap.cds.services.environment.CdsEnvironment; -import com.sap.cds.services.environment.CdsProperties; -import com.sap.cds.services.environment.CdsProperties.Model; -import com.sap.cds.services.environment.CdsProperties.Model.Provider; -import com.sap.cds.services.environment.CdsProperties.MultiTenancy; -import com.sap.cds.services.environment.CdsProperties.MultiTenancy.Sidecar; -import com.sap.cds.services.runtime.CdsRuntime; -import com.sap.cds.services.runtime.CdsRuntimeConfigurer; -import com.sap.cds.services.runtime.ExtendedServiceLoader; -import java.util.Collections; -import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; - -class OrdResourcesProviderConfigurationTest { - - private Model model; - private Sidecar sidecar; - private Provider provider; - private CdsRuntime cdsRuntime; - private MultiTenancy multiTenancy; - private CdsProperties cdsProperties; - private CdsEnvironment cdsEnvironment; - private CdsRuntimeConfigurer cdsRuntimeConfigurer; - - private OrdResourcesProviderConfiguration classUnderTest; - - @BeforeEach - void setUp() { - model = mock(Model.class); - sidecar = mock(Sidecar.class); - provider = mock(Provider.class); - cdsRuntime = mock(CdsRuntime.class); - multiTenancy = mock(MultiTenancy.class); - cdsProperties = mock(CdsProperties.class); - cdsEnvironment = mock(CdsEnvironment.class); - cdsRuntimeConfigurer = mock(CdsRuntimeConfigurer.class); - - classUnderTest = new OrdResourcesProviderConfiguration(); - - doReturn(provider).when(model).getProvider(); - doReturn(model).when(cdsProperties).getModel(); - doReturn(sidecar).when(multiTenancy).getSidecar(); - doReturn(cdsEnvironment).when(cdsRuntime).getEnvironment(); - doReturn(multiTenancy).when(cdsProperties).getMultiTenancy(); - doReturn(cdsRuntime).when(cdsRuntimeConfigurer).getCdsRuntime(); - doReturn(cdsProperties).when(cdsEnvironment).getCdsProperties(); - } - - @Test - void givenDynamicModelsNotSupported_whenProvidersIsCalled_thenNoOrdResourceProviderIsRegistered() { - try (MockedStatic extendedServiceLoader = mockStatic(ExtendedServiceLoader.class)) { - extendedServiceLoader - .when(() -> loadAll(CdsOrdNodeProcessor.class, cdsRuntime)) - .thenReturn(Collections.emptyIterator()); - - classUnderTest.providers(cdsRuntimeConfigurer); - } - - verify(sidecar).getUrl(); - verify(provider).getUrl(); - verify(model).getProvider(); - verify(cdsProperties).getModel(); - verify(multiTenancy).getSidecar(); - verify(cdsProperties).getMultiTenancy(); - verify(cdsRuntimeConfigurer).getCdsRuntime(); - verify(cdsRuntime, times(2)).getEnvironment(); - verify(cdsEnvironment, times(2)).getCdsProperties(); - verify(cdsRuntimeConfigurer).provider(any(StaticOrdResourcesProviderImpl.class)); - verifyNoMoreInteractions( - model, - sidecar, - provider, - cdsRuntime, - multiTenancy, - cdsProperties, - cdsEnvironment, - cdsRuntimeConfigurer); - } - - @Test - void givenDynamicModelsAreSupported_whenProvidersIsCalled_thenCorrectProvidersAreRegistered() { - doReturn(Boolean.TRUE).when(provider).isExtensibility(); - doReturn("https://dummy.provider.sap.com/").when(provider).getUrl(); - - try (MockedStatic extendedServiceLoader = mockStatic(ExtendedServiceLoader.class)) { - extendedServiceLoader - .when(() -> loadAll(CdsOrdNodeProcessor.class, cdsRuntime)) - .thenAnswer(in -> List.of(mock(CdsOrdNodeProcessor.class)).iterator()); - - classUnderTest.providers(cdsRuntimeConfigurer); - } - - verify(model).getProvider(); - verify(cdsProperties).getModel(); - verify(multiTenancy).getSidecar(); - verify(provider).isExtensibility(); - verify(cdsProperties).getMultiTenancy(); - verify(cdsRuntimeConfigurer).getCdsRuntime(); - verify(provider, times(2)).getUrl(); - verify(cdsRuntime, times(2)).getEnvironment(); - verify(cdsEnvironment, times(2)).getCdsProperties(); - verify(cdsRuntimeConfigurer).provider(any(StaticOrdResourcesProviderImpl.class)); - verify(cdsRuntimeConfigurer).provider(any(DynamicOrdResourcesProviderImpl.class)); - verifyNoMoreInteractions( - model, - sidecar, - provider, - cdsRuntime, - multiTenancy, - cdsProperties, - cdsEnvironment, - cdsRuntimeConfigurer); - } -} diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/provider/impl/DynamicOrdResourcesProviderImplTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/provider/impl/DynamicOrdResourcesProviderImplTest.java deleted file mode 100644 index 3aa4ae7..0000000 --- a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/provider/impl/DynamicOrdResourcesProviderImplTest.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * © 2026 SAP SE or an SAP affiliate company. All rights reserved. - */ -package com.sap.cds.feature.ord.provider.impl; - -import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; -import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.commons.io.IOUtils.toInputStream; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import com.sap.cds.adapter.edmx.EdmxV4Provider; -import com.sap.cds.feature.ord.clients.MtxSidecarClient; -import com.sap.cds.feature.ord.provider.OrdResourcesProvider; -import com.sap.cds.services.environment.CdsEnvironment; -import com.sap.cds.services.environment.CdsProperties; -import com.sap.cds.services.environment.CdsProperties.OpenResourceDiscovery; -import com.sap.cds.services.runtime.CdsRuntime; -import com.sap.cds.services.utils.model.DynamicModelUtils; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.List; -import org.apache.commons.io.IOUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class DynamicOrdResourcesProviderImplTest { - - private CdsRuntime cdsRuntime; - private CdsProperties cdsProperties; - private CdsEnvironment cdsEnvironment; - private EdmxV4Provider edmxV4Provider; - private MtxSidecarClient mtxSidecarClient; - private DynamicModelUtils dynamicModelUtils; - private OrdResourcesProvider ordResourcesProvider; - private OpenResourceDiscovery openResourceDiscovery; - - private DynamicOrdResourcesProviderImpl classUnderTest; - - @BeforeEach - void setUp() { - cdsRuntime = mock(CdsRuntime.class); - cdsProperties = mock(CdsProperties.class); - cdsEnvironment = mock(CdsEnvironment.class); - edmxV4Provider = mock(EdmxV4Provider.class); - mtxSidecarClient = mock(MtxSidecarClient.class); - dynamicModelUtils = mock(DynamicModelUtils.class); - ordResourcesProvider = mock(OrdResourcesProvider.class); - openResourceDiscovery = mock(OpenResourceDiscovery.class); - classUnderTest = - new DynamicOrdResourcesProviderImpl(cdsRuntime, mtxSidecarClient, dynamicModelUtils, List.of()); - - classUnderTest.setPrevious(ordResourcesProvider); - doReturn(cdsEnvironment).when(cdsRuntime).getEnvironment(); - doReturn(openResourceDiscovery).when(cdsProperties).getOrd(); - doReturn(cdsProperties).when(cdsEnvironment).getCdsProperties(); - doReturn(edmxV4Provider).when(cdsRuntime).getProvider(EdmxV4Provider.class); - } - - @Test - void givenThatStaticModelShouldBeUsed_and_perspectiveIsSystemVersion_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn(true).when(dynamicModelUtils).useStaticModel(); - doReturn(new ByteArrayInputStream("{}".getBytes())) - .when(ordResourcesProvider) - .read("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); - - assertEquals( - "{}", - IOUtils.toString(classUnderTest.read("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(ordResourcesProvider).read("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void givenThatStaticModelShouldBeUsed_and_perspectiveIsSystemInstance_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn(true).when(dynamicModelUtils).useStaticModel(); - doReturn(new ByteArrayInputStream("{}".getBytes())) - .when(ordResourcesProvider) - .read("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE); - - assertEquals( - "{}", - IOUtils.toString(classUnderTest.read("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(ordResourcesProvider).read("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void - givenThatDynamicModelShouldBeUsed_and_perspectiveIsSystemVersion_and_ordDocumentIsRequested_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn(false).when(dynamicModelUtils).useStaticModel(); - doReturn(new ByteArrayInputStream("{}".getBytes())) - .when(ordResourcesProvider) - .read("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); - - assertEquals( - "{}", - IOUtils.toString(classUnderTest.read("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(ordResourcesProvider).read("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void - givenThatDynamicModelShouldBeUsed_and_perspectiveIsSystemInstance_and_ordDocumentIsRequested_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn(false).when(dynamicModelUtils).useStaticModel(); - doReturn("{}".getBytes(UTF_8)).when(mtxSidecarClient).getOrdDocument(); - - assertEquals( - "{}", - IOUtils.toString(classUnderTest.read("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE), UTF_8)); - - verify(mtxSidecarClient).getOrdDocument(); - verify(dynamicModelUtils).useStaticModel(); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void - givenThatStaticModelShouldBeUsed_and_perspectiveIsSystemVersion_and_resourceDefinitionIsRequested_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn(true).when(dynamicModelUtils).useStaticModel(); - doReturn("ord/").when(openResourceDiscovery).getOrdResourcesRoot(); - doReturn(new ByteArrayInputStream("{}".getBytes())) - .when(ordResourcesProvider) - .read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION); - - assertEquals( - "{}", - IOUtils.toString( - classUnderTest.read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(ordResourcesProvider).read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void - givenThatStaticModelShouldBeUsed_and_perspectiveIsSystemInstance_and_resourceDefinitionIsRequested_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn(true).when(dynamicModelUtils).useStaticModel(); - doReturn("ord/").when(openResourceDiscovery).getOrdResourcesRoot(); - doReturn(new ByteArrayInputStream("{}".getBytes())) - .when(ordResourcesProvider) - .read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE); - - assertEquals( - "{}", - IOUtils.toString( - classUnderTest.read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(ordResourcesProvider).read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void - givenThatDynamicModelShouldBeUsed_and_perspectiveIsSystemInstance_and_resourceDefinitionIsRequested_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn("ord/").when(openResourceDiscovery).getOrdResourcesRoot(); - doReturn(false).when(dynamicModelUtils).useStaticModel(); - doReturn("{}".getBytes(UTF_8)) - .when(mtxSidecarClient) - .getOrdResourceDefinition("test:ord:service/test.oas3.json"); - - assertEquals( - "{}", - IOUtils.toString( - classUnderTest.read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(mtxSidecarClient).getOrdResourceDefinition("test:ord:service/test.oas3.json"); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void - givenThatDynamicModelShouldBeUsed_and_perspectiveIsSystemVersion_and_resourceDefinitionIsRequested_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn("ord/").when(openResourceDiscovery).getOrdResourcesRoot(); - doReturn(false).when(dynamicModelUtils).useStaticModel(); - doReturn(new ByteArrayInputStream("{}".getBytes())) - .when(ordResourcesProvider) - .read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION); - - assertEquals( - "{}", - IOUtils.toString( - classUnderTest.read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(ordResourcesProvider).read("test:ord:service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } - - @Test - void - givenThatDynamicModelShouldBeUsed_and_perspectiveIsSystemInstance_and_edmxResourceDefinitionIsRequested_whenReadIsCalled_thenCorrectResultIsReturned() - throws IOException { - doReturn(false).when(dynamicModelUtils).useStaticModel(); - doReturn(toInputStream("", UTF_8)).when(edmxV4Provider).getEdmx("test"); - doReturn("ord/").when(openResourceDiscovery).getOrdResourcesRoot(); - - assertEquals( - "", - IOUtils.toString( - classUnderTest.read("test:ord:service/test.edmx", PERSPECTIVE_SYSTEM_INSTANCE), UTF_8)); - - verify(dynamicModelUtils).useStaticModel(); - verify(edmxV4Provider).getEdmx("test"); - verify(cdsRuntime).getProvider(EdmxV4Provider.class); - verifyNoMoreInteractions( - cdsRuntime, - cdsProperties, - cdsEnvironment, - edmxV4Provider, - mtxSidecarClient, - dynamicModelUtils, - ordResourcesProvider, - openResourceDiscovery); - } -} diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/provider/impl/StaticOrdResourcesProviderImplTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/provider/impl/StaticOrdResourcesProviderImplTest.java deleted file mode 100644 index eecc4ba..0000000 --- a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/provider/impl/StaticOrdResourcesProviderImplTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * © 2026 SAP SE or an SAP affiliate company. All rights reserved. - */ -package com.sap.cds.feature.ord.provider.impl; - -import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; -import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; -import static com.sap.cds.feature.ord.common.Utils.CdsRuntimeProperties.getOrdProperties; -import static com.sap.cds.services.runtime.CdsRuntimeConfigurer.create; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.commons.io.FilenameUtils.concat; -import static org.apache.commons.io.FilenameUtils.getBaseName; -import static org.apache.commons.io.IOUtils.toInputStream; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import com.sap.cds.adapter.edmx.EdmxV4Provider; -import com.sap.cds.impl.parser.JsonParser; -import com.sap.cds.services.runtime.CdsRuntime; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.List; -import java.util.Map; -import org.apache.commons.io.IOUtils; -import org.junit.jupiter.api.Test; - -@SuppressWarnings("unchecked") -class StaticOrdResourcesProviderImplTest { - - @Test - void givenPerspectiveIsNull_whenGetDocumentIsCalled_thenCorrectResultIsReturned() { - CdsRuntime runtime = create().complete(); - String document = - concat("documents", getBaseName(getOrdProperties(runtime).getOrdDocumentPath())); - InputStream is = new StaticOrdResourcesProviderImpl(runtime, List.of()).read(document, null); - - assertNotNull(is); - - Map ord = (Map) JsonParser.map(new InputStreamReader(is)); - // just test a few properties to ensure it´s the right document - assertEquals("1.9", ord.get("openResourceDiscovery")); - assertEquals("this is an application description", ord.get("description")); - - List> integrationDependencies = - (List>) ord.get("integrationDependencies"); - assertEquals(1, integrationDependencies.size()); - - Map integrationDependency = integrationDependencies.get(0); - assertEquals("sap.cdsjavacpoc:integrationDependency:RawEvent:v1", integrationDependency.get("ordId")); - } - - @Test - void givenPerspectiveIsSystemVersion_whenGetDocumentIsCalled_thenCorrectResultIsReturned() { - CdsRuntime runtime = create().complete(); - String document = - concat("documents", getBaseName(getOrdProperties(runtime).getOrdDocumentPath())); - InputStream is = - new StaticOrdResourcesProviderImpl(runtime, List.of()).read(document, PERSPECTIVE_SYSTEM_VERSION); - - assertNotNull(is); - - Map ord = (Map) JsonParser.map(new InputStreamReader(is)); - // just test a few properties to ensure it´s the right document - assertEquals("1.9", ord.get("openResourceDiscovery")); - assertEquals("this is an application description", ord.get("description")); - - List> integrationDependencies = - (List>) ord.get("integrationDependencies"); - assertEquals(1, integrationDependencies.size()); - - Map integrationDependency = integrationDependencies.get(0); - assertEquals("sap.cdsjavacpoc:integrationDependency:RawEvent:v1", integrationDependency.get("ordId")); - } - - @Test - void givenPerspectiveIsSystemInstance_whenGetDocumentIsCalled_thenCorrectResultIsReturned() { - CdsRuntime runtime = create().complete(); - String document = - concat("documents", getBaseName(getOrdProperties(runtime).getOrdDocumentPath())); - - assertThrows( - IllegalArgumentException.class, - () -> new StaticOrdResourcesProviderImpl(runtime, List.of()) - .read(document, PERSPECTIVE_SYSTEM_INSTANCE)); - } - - @Test - void givenThatDocumentDoesNotExist_whenGetDocumentIsCalled_thenNullIsReturned() { - assertNull(new StaticOrdResourcesProviderImpl(create().complete(), List.of()) - .read("no-such-ord-document.json", null)); - } - - @Test - void givenPerspectiveIsSystemVersion_and_edmxResource_whenGetDocumentIsCalled_thenCorrectResultIsReturned() - throws IOException { - EdmxV4Provider edmxV4Provider = mock(EdmxV4Provider.class); - doReturn(toInputStream("", UTF_8)).when(edmxV4Provider).getEdmx("test"); - - assertEquals( - "", - IOUtils.toString( - new StaticOrdResourcesProviderImpl( - create().provider(edmxV4Provider).complete(), List.of()) - .read("documents/test_ord_service/test.edmx", PERSPECTIVE_SYSTEM_VERSION), - UTF_8)); - - verify(edmxV4Provider).setPrevious(null); - verify(edmxV4Provider).getEdmx("test"); - verifyNoMoreInteractions(edmxV4Provider); - } -} diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdDocumentResolverTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdDocumentResolverTest.java new file mode 100644 index 0000000..36c0f79 --- /dev/null +++ b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdDocumentResolverTest.java @@ -0,0 +1,60 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import com.sap.cds.feature.ord.clients.MtxSidecarClient; +import com.sap.cds.services.runtime.CdsRuntimeConfigurer; +import com.sap.cds.services.utils.model.DynamicModelUtils; +import java.io.IOException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class DynamicOrdDocumentResolverTest { + + private MtxSidecarClient client; + private DynamicModelUtils dynamicModelUtils; + private DynamicOrdDocumentResolver classUnderTest; + + @BeforeEach + void setUp() { + client = mock(MtxSidecarClient.class); + dynamicModelUtils = mock(DynamicModelUtils.class); + classUnderTest = + new DynamicOrdDocumentResolver(CdsRuntimeConfigurer.create().complete(), client, dynamicModelUtils); + } + + @Test + void resolvesDocumentReturnedBySidecar() throws IOException { + doReturn("{}".getBytes(UTF_8)).when(client).getOrdDocument(); + + assertEquals(Integer.MAX_VALUE, classUnderTest.order()); + try (var result = classUnderTest.resolve("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE)) { + assertNotNull(result); + } + + verify(client).getOrdDocument(); + } + + @Test + void appliesOnlyToDynamicInstanceDocument() { + doReturn(false).when(dynamicModelUtils).useStaticModel(); + + assertTrue(classUnderTest.isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE)); + assertFalse(classUnderTest.isApplicable("api:service.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE)); + assertFalse(classUnderTest.isApplicable("documents/ord-document", "system-version")); + + doReturn(true).when(dynamicModelUtils).useStaticModel(); + assertFalse(classUnderTest.isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE)); + } +} diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdResourceDefinitionResolverTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdResourceDefinitionResolverTest.java new file mode 100644 index 0000000..95f5112 --- /dev/null +++ b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/DynamicOrdResourceDefinitionResolverTest.java @@ -0,0 +1,74 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; + +import com.sap.cds.adapter.edmx.EdmxV4Provider; +import com.sap.cds.feature.ord.clients.MtxSidecarClient; +import com.sap.cds.services.runtime.CdsRuntime; +import com.sap.cds.services.utils.model.DynamicModelUtils; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class DynamicOrdResourceDefinitionResolverTest { + + private MtxSidecarClient client; + private CdsRuntime runtime; + private DynamicModelUtils dynamicModelUtils; + private DynamicOrdResourceDefinitionResolver classUnderTest; + + @BeforeEach + void setUp() { + client = mock(MtxSidecarClient.class); + runtime = mock(CdsRuntime.class); + dynamicModelUtils = mock(DynamicModelUtils.class); + classUnderTest = new DynamicOrdResourceDefinitionResolver(runtime, client, dynamicModelUtils); + } + + @Test + void resolvesDefinitionReturnedBySidecar() throws IOException { + doReturn("definition".getBytes(UTF_8)).when(client).getOrdResourceDefinition("api:service.oas3.json"); + + assertEquals(Integer.MAX_VALUE, classUnderTest.order()); + try (var result = classUnderTest.resolve("api:service.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE)) { + assertEquals("definition", new String(result.readAllBytes(), UTF_8)); + } + verifyNoInteractions(runtime); + } + + @Test + void delegatesEdmxResourcesToProvider() { + EdmxV4Provider provider = mock(EdmxV4Provider.class); + var expected = new ByteArrayInputStream("edmx".getBytes(UTF_8)); + doReturn(provider).when(runtime).getProvider(EdmxV4Provider.class); + doReturn(expected).when(provider).getEdmx("AdminService"); + + assertEquals(expected, classUnderTest.resolve("api/AdminService.EDMX", PERSPECTIVE_SYSTEM_INSTANCE)); + verify(provider).getEdmx("AdminService"); + verifyNoInteractions(client); + } + + @Test + void appliesOnlyToDynamicInstanceResourcesOtherThanTheDocument() { + doReturn(false).when(dynamicModelUtils).useStaticModel(); + + assertTrue(classUnderTest.isApplicable("api:service.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE)); + assertFalse(classUnderTest.isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_INSTANCE)); + assertFalse(classUnderTest.isApplicable("api:service.oas3.json", "system-version")); + + doReturn(true).when(dynamicModelUtils).useStaticModel(); + assertFalse(classUnderTest.isApplicable("api:service.oas3.json", PERSPECTIVE_SYSTEM_INSTANCE)); + } +} diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdDocumentResolverTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdDocumentResolverTest.java new file mode 100644 index 0000000..f4d9c24 --- /dev/null +++ b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdDocumentResolverTest.java @@ -0,0 +1,38 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.sap.cds.services.runtime.CdsRuntimeConfigurer; +import java.io.IOException; +import org.junit.jupiter.api.Test; + +class StaticOrdDocumentResolverTest { + + @Test + void resolvesConfiguredOrdDocument() throws IOException { + var classUnderTest = + new StaticOrdDocumentResolver(CdsRuntimeConfigurer.create().complete()); + + assertEquals(Integer.MAX_VALUE, classUnderTest.order()); + try (var result = classUnderTest.resolve("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION)) { + assertNotNull(result); + assertTrue(result.read() >= 0); + } + } + + @Test + void appliesOnlyToSystemVersionDocument() { + var resolver = new StaticOrdDocumentResolver(); + + assertTrue(resolver.isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION)); + assertFalse(resolver.isApplicable("documents/other", PERSPECTIVE_SYSTEM_VERSION)); + assertFalse(resolver.isApplicable("documents/ord-document", "system-instance")); + } +} diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdResourceDefinitionResolverTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdResourceDefinitionResolverTest.java new file mode 100644 index 0000000..1169c90 --- /dev/null +++ b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/resolver/impl/StaticOrdResourceDefinitionResolverTest.java @@ -0,0 +1,60 @@ +/* + * © 2026 SAP SE or an SAP affiliate company. All rights reserved. + */ +package com.sap.cds.feature.ord.resolver.impl; + +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import com.sap.cds.adapter.edmx.EdmxV4Provider; +import com.sap.cds.services.runtime.CdsRuntimeConfigurer; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class StaticOrdResourceDefinitionResolverTest { + + private StaticOrdResourceDefinitionResolver classUnderTest; + + @BeforeEach + void setUp() { + classUnderTest = new StaticOrdResourceDefinitionResolver( + CdsRuntimeConfigurer.create().complete()); + } + + @Test + void resolvesClasspathResource() throws IOException { + assertEquals(Integer.MAX_VALUE, classUnderTest.order()); + try (var result = classUnderTest.resolve("test_ord_service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION)) { + assertEquals("{}", new String(result.readAllBytes(), UTF_8)); + } + } + + @Test + void delegatesEdmxResourcesToProvider() throws IOException { + EdmxV4Provider provider = mock(EdmxV4Provider.class); + var expected = new ByteArrayInputStream("edmx".getBytes(UTF_8)); + doReturn(expected).when(provider).getEdmx("AdminService"); + classUnderTest.setCdsRuntime( + CdsRuntimeConfigurer.create().provider(provider).complete()); + + assertEquals(expected, classUnderTest.resolve("AdminService.edmx", PERSPECTIVE_SYSTEM_VERSION)); + verify(provider).getEdmx("AdminService"); + } + + @Test + void appliesToExistingNonDocumentResourcesForSupportedPerspectives() { + assertTrue(classUnderTest.isApplicable("test_ord_service/test.oas3.json", PERSPECTIVE_SYSTEM_VERSION)); + assertTrue(classUnderTest.isApplicable("test_ord_service/test.oas3.json", null)); + assertFalse(classUnderTest.isApplicable("missing.json", PERSPECTIVE_SYSTEM_VERSION)); + assertFalse(classUnderTest.isApplicable("test_ord_service/test.oas3.json", "system-instance")); + assertFalse(classUnderTest.isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION)); + } +} diff --git a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/servlet/DocumentsServletTest.java b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/servlet/DocumentsServletTest.java index bbb257f..c9a6f78 100644 --- a/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/servlet/DocumentsServletTest.java +++ b/cds-feature-ord/src/test/java/com/sap/cds/feature/ord/servlet/DocumentsServletTest.java @@ -5,9 +5,12 @@ import static com.sap.cds.feature.ord.common.Constants.HEADER_LOCAL_TENANT_ID; import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_INSTANCE; +import static com.sap.cds.feature.ord.common.Constants.PERSPECTIVE_SYSTEM_VERSION; import static com.sap.cds.feature.ord.common.Utils.CdsRuntimeProperties.getAuthenticationProperties; import static com.sap.cds.services.ErrorStatuses.UNAUTHORIZED; +import static com.sap.cds.services.runtime.ExtendedServiceLoader.loadAll; import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.http.entity.ContentType.APPLICATION_JSON; import static org.apache.http.entity.ContentType.APPLICATION_XML; import static org.apache.http.entity.ContentType.TEXT_PLAIN; @@ -16,31 +19,36 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import com.sap.cds.feature.ord.provider.AuthenticationManagerProvider; -import com.sap.cds.feature.ord.provider.OrdResourcesProvider; +import com.sap.cds.feature.ord.resolver.OrdResolver; import com.sap.cds.services.runtime.CdsRuntime; import com.sap.cds.services.runtime.CdsRuntimeConfigurer; +import com.sap.cds.services.runtime.ExtendedServiceLoader; import com.sap.cds.services.utils.ErrorStatusException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.PrintWriter; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; class DocumentsServletTest { private CdsRuntime cdsRuntime; + private OrdResolver ordResolver; private PrintWriter printWriter; private HttpServletRequest request; private HttpServletResponse response; private ServletOutputStream servletOutputStream; - private OrdResourcesProvider ordResourcesProvider; private AuthenticationManagerProvider authenticationManagerProvider; private DocumentsServlet classUnderTest; @@ -48,13 +56,12 @@ class DocumentsServletTest { @BeforeEach void setUp() { printWriter = mock(PrintWriter.class); + ordResolver = mock(OrdResolver.class); request = mock(HttpServletRequest.class); response = mock(HttpServletResponse.class); servletOutputStream = mock(ServletOutputStream.class); - ordResourcesProvider = mock(OrdResourcesProvider.class); authenticationManagerProvider = mock(AuthenticationManagerProvider.class); cdsRuntime = CdsRuntimeConfigurer.create() - .provider(ordResourcesProvider) .provider(authenticationManagerProvider) .complete(); @@ -70,193 +77,198 @@ void givenRequestForUnsupportedResourceDefinitionExtension_whenDoGetIsCalled_the classUnderTest.doGet(request, response); verify(request).getRequestURI(); - verify(ordResourcesProvider).setPrevious(null); verify(request).getHeader(HEADER_LOCAL_TENANT_ID); - verify(request).getParameter("perspective"); verify(authenticationManagerProvider).setPrevious(null); verify(request, times(2)).getPathInfo(); verify(response).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.unsupported"); verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); } @Test void givenRequestForDynamicPerspectiveForResourceDefinition_whenDoGetIsCalled_thenCorrectResponseIsReturned() throws Exception { - doReturn(servletOutputStream).when(response).getOutputStream(); - getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); - doReturn("/dummy:service:v1/Dummy.graphql").when(request).getPathInfo(); - doReturn("/ord/v1/dummy:service:v1/Dummy.graphql").when(request).getRequestURI(); - doReturn("system-instance").when(request).getParameter("perspective"); - doReturn(new ByteArrayInputStream("test-document".getBytes())) - .when(ordResourcesProvider) - .read("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_INSTANCE); + try (MockedStatic extendedServiceLoaderMockedStatic = + mockStatic(ExtendedServiceLoader.class)) { + doReturn(servletOutputStream).when(response).getOutputStream(); + getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); + doReturn("/dummy:service:v1/Dummy.graphql").when(request).getPathInfo(); + doReturn(PERSPECTIVE_SYSTEM_INSTANCE).when(request).getParameter("perspective"); + doReturn("/ord/v1/dummy:service:v1/Dummy.graphql").when(request).getRequestURI(); + doReturn(true) + .when(ordResolver) + .isApplicable("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_INSTANCE); + extendedServiceLoaderMockedStatic + .when(() -> loadAll(OrdResolver.class, cdsRuntime)) + .thenReturn(List.of(ordResolver).iterator()); + doReturn(new ByteArrayInputStream("test-document".getBytes(UTF_8))) + .when(ordResolver) + .resolve("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_INSTANCE); - classUnderTest.doGet(request, response); + classUnderTest.doGet(request, response); - verify(request).getRequestURI(); - verify(response).getOutputStream(); - verify(ordResourcesProvider).setPrevious(null); - verify(request).getHeader(HEADER_LOCAL_TENANT_ID); - verify(request).getParameter("perspective"); - verify(response).setStatus(HttpServletResponse.SC_OK); - verify(authenticationManagerProvider).setPrevious(null); - verify(response).setContentType(TEXT_PLAIN.getMimeType()); - verify(request, times(2)).getPathInfo(); - verify(response).setCharacterEncoding(TEXT_PLAIN.getCharset().toString()); - verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.graphql"); - verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); - verify(ordResourcesProvider).read("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_INSTANCE); - verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + verify(request).getRequestURI(); + verify(response).getOutputStream(); + verify(request).getHeader(HEADER_LOCAL_TENANT_ID); + verify(request).getParameter("perspective"); + verify(response).setStatus(HttpServletResponse.SC_OK); + verify(authenticationManagerProvider).setPrevious(null); + verify(response).setContentType(TEXT_PLAIN.getMimeType()); + verify(request, times(2)).getPathInfo(); + verify(response).setCharacterEncoding(TEXT_PLAIN.getCharset().toString()); + verify(ordResolver).resolve("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_INSTANCE); + verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.graphql"); + verify(ordResolver).isApplicable("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_INSTANCE); + verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); + verifyNoMoreInteractions( + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); + } } @Test void givenRequestForGraphqlResourceDefinition_whenDoGetIsCalled_thenCorrectResponseIsReturned() throws Exception { - doReturn(servletOutputStream).when(response).getOutputStream(); - getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); - doReturn("/dummy:service:v1/Dummy.graphql").when(request).getPathInfo(); - doReturn("/ord/v1/dummy:service:v1/Dummy.graphql").when(request).getRequestURI(); - doReturn(new ByteArrayInputStream("test-document".getBytes())) - .when(ordResourcesProvider) - .read("dummy:service:v1/Dummy.graphql", null); + try (MockedStatic extendedServiceLoaderMockedStatic = + mockStatic(ExtendedServiceLoader.class)) { + doReturn(servletOutputStream).when(response).getOutputStream(); + getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); + doReturn("/dummy:service:v1/Dummy.graphql").when(request).getPathInfo(); + doReturn("/ord/v1/dummy:service:v1/Dummy.graphql").when(request).getRequestURI(); + doReturn(true).when(ordResolver).isApplicable("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_VERSION); + extendedServiceLoaderMockedStatic + .when(() -> loadAll(OrdResolver.class, cdsRuntime)) + .thenReturn(List.of(ordResolver).iterator()); + doReturn(new ByteArrayInputStream("test-document".getBytes(UTF_8))) + .when(ordResolver) + .resolve("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_VERSION); - classUnderTest.doGet(request, response); + classUnderTest.doGet(request, response); - verify(request).getRequestURI(); - verify(response).getOutputStream(); - verify(ordResourcesProvider).setPrevious(null); - verify(request).getParameter("perspective"); - verify(request).getHeader("Local-Tenant-Id"); - verify(response).setStatus(HttpServletResponse.SC_OK); - verify(authenticationManagerProvider).setPrevious(null); - verify(response).setContentType(TEXT_PLAIN.getMimeType()); - verify(request, times(2)).getPathInfo(); - verify(response).setCharacterEncoding(TEXT_PLAIN.getCharset().toString()); - verify(ordResourcesProvider).read("dummy:service:v1/Dummy.graphql", null); - verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); - verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.graphql"); - verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + verify(request).getRequestURI(); + verify(response).getOutputStream(); + verify(request).getParameter("perspective"); + verify(request).getHeader("Local-Tenant-Id"); + verify(response).setStatus(HttpServletResponse.SC_OK); + verify(authenticationManagerProvider).setPrevious(null); + verify(response).setContentType(TEXT_PLAIN.getMimeType()); + verify(request, times(2)).getPathInfo(); + verify(response).setCharacterEncoding(TEXT_PLAIN.getCharset().toString()); + verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); + verify(ordResolver).resolve("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_VERSION); + verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.graphql"); + verify(ordResolver).isApplicable("dummy:service:v1/Dummy.graphql", PERSPECTIVE_SYSTEM_VERSION); + verifyNoMoreInteractions( + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); + } } @Test void givenRequestForEdmxResourceDefinition_whenDoGetIsCalled_thenCorrectResponseIsReturned() throws Exception { - doReturn(servletOutputStream).when(response).getOutputStream(); - getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); - doReturn("/dummy:service:v1/Dummy.edmx").when(request).getPathInfo(); - doReturn("/ord/v1/dummy:service:v1/Dummy.edmx").when(request).getRequestURI(); - doReturn(new ByteArrayInputStream("test-document".getBytes())) - .when(ordResourcesProvider) - .read("dummy:service:v1/Dummy.edmx", null); + try (MockedStatic extendedServiceLoaderMockedStatic = + mockStatic(ExtendedServiceLoader.class)) { + doReturn(servletOutputStream).when(response).getOutputStream(); + getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); + doReturn("/dummy:service:v1/Dummy.edmx").when(request).getPathInfo(); + doReturn("/ord/v1/dummy:service:v1/Dummy.edmx").when(request).getRequestURI(); + doReturn(true).when(ordResolver).isApplicable("dummy:service:v1/Dummy.edmx", PERSPECTIVE_SYSTEM_VERSION); + extendedServiceLoaderMockedStatic + .when(() -> loadAll(OrdResolver.class, cdsRuntime)) + .thenReturn(List.of(ordResolver).iterator()); + doReturn(new ByteArrayInputStream("test-document".getBytes(UTF_8))) + .when(ordResolver) + .resolve("dummy:service:v1/Dummy.edmx", PERSPECTIVE_SYSTEM_VERSION); - classUnderTest.doGet(request, response); + classUnderTest.doGet(request, response); - verify(request).getRequestURI(); - verify(response).getOutputStream(); - verify(ordResourcesProvider).setPrevious(null); - verify(request).getParameter("perspective"); - verify(request).getHeader("Local-Tenant-Id"); - verify(response).setStatus(HttpServletResponse.SC_OK); - verify(authenticationManagerProvider).setPrevious(null); - verify(response).setContentType(APPLICATION_XML.getMimeType()); - verify(request, times(2)).getPathInfo(); - verify(response).setCharacterEncoding(APPLICATION_XML.getCharset().toString()); - verify(ordResourcesProvider).read("dummy:service:v1/Dummy.edmx", null); - verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); - verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.edmx"); - verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + verify(request).getRequestURI(); + verify(response).getOutputStream(); + verify(request).getParameter("perspective"); + verify(request).getHeader("Local-Tenant-Id"); + verify(response).setStatus(HttpServletResponse.SC_OK); + verify(authenticationManagerProvider).setPrevious(null); + verify(response).setContentType(APPLICATION_XML.getMimeType()); + verify(request, times(2)).getPathInfo(); + verify(response).setCharacterEncoding(APPLICATION_XML.getCharset().toString()); + verify(ordResolver).resolve("dummy:service:v1/Dummy.edmx", PERSPECTIVE_SYSTEM_VERSION); + verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); + verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.edmx"); + verify(ordResolver).isApplicable("dummy:service:v1/Dummy.edmx", PERSPECTIVE_SYSTEM_VERSION); + verifyNoMoreInteractions( + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); + } } @Test void givenRequestForJsonResourceDefinition_whenDoGetIsCalled_thenCorrectResponseIsReturned() throws Exception { - doReturn(servletOutputStream).when(response).getOutputStream(); - getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); - doReturn("/dummy:service:v1/Dummy.json").when(request).getPathInfo(); - doReturn("/ord/v1/dummy:service:v1/Dummy.json").when(request).getRequestURI(); - doReturn(new ByteArrayInputStream("test-document".getBytes())) - .when(ordResourcesProvider) - .read("dummy:service:v1/Dummy.json", null); + try (MockedStatic extendedServiceLoaderMockedStatic = + mockStatic(ExtendedServiceLoader.class)) { + doReturn(servletOutputStream).when(response).getOutputStream(); + getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(false); + doReturn("/dummy:service:v1/Dummy.json").when(request).getPathInfo(); + doReturn("/ord/v1/dummy:service:v1/Dummy.json").when(request).getRequestURI(); + doReturn(true).when(ordResolver).isApplicable("dummy:service:v1/Dummy.json", PERSPECTIVE_SYSTEM_VERSION); + extendedServiceLoaderMockedStatic + .when(() -> loadAll(OrdResolver.class, cdsRuntime)) + .thenReturn(List.of(ordResolver).iterator()); + doReturn(new ByteArrayInputStream("test-document".getBytes(UTF_8))) + .when(ordResolver) + .resolve("dummy:service:v1/Dummy.json", PERSPECTIVE_SYSTEM_VERSION); - classUnderTest.doGet(request, response); + classUnderTest.doGet(request, response); - verify(request).getRequestURI(); - verify(response).getOutputStream(); - verify(ordResourcesProvider).setPrevious(null); - verify(request).getParameter("perspective"); - verify(request).getHeader("Local-Tenant-Id"); - verify(response).setStatus(HttpServletResponse.SC_OK); - verify(authenticationManagerProvider).setPrevious(null); - verify(request, times(2)).getPathInfo(); - verify(response).setContentType(APPLICATION_JSON.getMimeType()); - verify(response).setCharacterEncoding(APPLICATION_JSON.getCharset().toString()); - verify(ordResourcesProvider).read("dummy:service:v1/Dummy.json", null); - verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); - verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.json"); - verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + verify(request).getRequestURI(); + verify(response).getOutputStream(); + verify(request).getParameter("perspective"); + verify(request).getHeader("Local-Tenant-Id"); + verify(response).setStatus(HttpServletResponse.SC_OK); + verify(authenticationManagerProvider).setPrevious(null); + verify(request, times(2)).getPathInfo(); + verify(response).setContentType(APPLICATION_JSON.getMimeType()); + verify(response).setCharacterEncoding(APPLICATION_JSON.getCharset().toString()); + verify(ordResolver).resolve("dummy:service:v1/Dummy.json", PERSPECTIVE_SYSTEM_VERSION); + verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); + verify(authenticationManagerProvider).checkAuthorization("/ord/v1/dummy:service:v1/Dummy.json"); + verify(ordResolver).isApplicable("dummy:service:v1/Dummy.json", PERSPECTIVE_SYSTEM_VERSION); + verifyNoMoreInteractions( + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); + } } @Test void givenMtlsAuth_whenDoGetIsCalled_thenCorrectResponseIsReturned() throws Exception { - doReturn(servletOutputStream).when(response).getOutputStream(); - doReturn("/documents/ord-document").when(request).getPathInfo(); - doNothing().when(authenticationManagerProvider).checkAuthorization(anyString()); - getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(true); - doReturn("/ord/v1/documents/ord-document").when(request).getRequestURI(); - doReturn(new ByteArrayInputStream("test-document".getBytes())) - .when(ordResourcesProvider) - .read("documents/ord-document", null); + try (MockedStatic extendedServiceLoaderMockedStatic = + mockStatic(ExtendedServiceLoader.class)) { + doReturn(servletOutputStream).when(response).getOutputStream(); + doReturn("/documents/ord-document").when(request).getPathInfo(); + doNothing().when(authenticationManagerProvider).checkAuthorization(anyString()); + getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(true); + doReturn("/ord/v1/documents/ord-document").when(request).getRequestURI(); + doReturn(true).when(ordResolver).isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); + extendedServiceLoaderMockedStatic + .when(() -> loadAll(OrdResolver.class, cdsRuntime)) + .thenReturn(List.of(ordResolver).iterator()); + doReturn(new ByteArrayInputStream("test-document".getBytes(UTF_8))) + .when(ordResolver) + .resolve("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); - classUnderTest.doGet(request, response); + classUnderTest.doGet(request, response); - verify(request).getRequestURI(); - verify(response).getOutputStream(); - verify(ordResourcesProvider).setPrevious(null); - verify(request).getParameter("perspective"); - verify(request).getHeader("Local-Tenant-Id"); - verify(response).setStatus(HttpServletResponse.SC_OK); - verify(authenticationManagerProvider).setPrevious(null); - verify(request, times(2)).getPathInfo(); - verify(response).setContentType(APPLICATION_JSON.getMimeType()); - verify(response).setCharacterEncoding(APPLICATION_JSON.getCharset().toString()); - verify(ordResourcesProvider).read("documents/ord-document", null); - verify(authenticationManagerProvider).checkAuthorization("/ord/v1/documents/ord-document"); - verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); - verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + verify(request).getRequestURI(); + verify(response).getOutputStream(); + verify(request).getParameter("perspective"); + verify(request).getHeader("Local-Tenant-Id"); + verify(response).setStatus(HttpServletResponse.SC_OK); + verify(authenticationManagerProvider).setPrevious(null); + verify(request, times(2)).getPathInfo(); + verify(response).setContentType(APPLICATION_JSON.getMimeType()); + verify(response).setCharacterEncoding(APPLICATION_JSON.getCharset().toString()); + verify(ordResolver).resolve("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); + verify(authenticationManagerProvider).checkAuthorization("/ord/v1/documents/ord-document"); + verify(servletOutputStream).write("test-document".getBytes(), 0, "test-document".length()); + verify(ordResolver).isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); + verifyNoMoreInteractions( + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); + } } @Test @@ -274,45 +286,43 @@ void givenMtlsAuth_and_authorizationFails_whenDoGetIsCalled_thenCorrectResponseI verify(printWriter).close(); verify(response).getWriter(); verify(request).getRequestURI(); - verify(ordResourcesProvider).setPrevious(null); verify(printWriter).write("No authentication"); verify(authenticationManagerProvider).setPrevious(null); verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED); verify(authenticationManagerProvider).checkAuthorization("/ord/v1"); verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); } @Test - void givenFileIsNotFound_whenDoGetIsCalled_thenCorrectResponseIsReturned() { - doReturn("/documents/ord-document").when(request).getPathInfo(); - doNothing().when(authenticationManagerProvider).checkAuthorization(anyString()); - getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(true); - doReturn("/ord/v1/documents/ord-document").when(request).getRequestURI(); - doReturn(null).when(ordResourcesProvider).read("documents/ord-document", null); + void givenFileIsNotFound_whenDoGetIsCalled_thenCorrectResponseIsReturned() throws IOException { + try (MockedStatic extendedServiceLoaderMockedStatic = + mockStatic(ExtendedServiceLoader.class)) { + doReturn(printWriter).when(response).getWriter(); + doReturn("/documents/ord-document").when(request).getPathInfo(); + doNothing().when(authenticationManagerProvider).checkAuthorization(anyString()); + getAuthenticationProperties(cdsRuntime).setAuthenticateMetadataEndpoints(true); + doReturn("/ord/v1/documents/ord-document").when(request).getRequestURI(); + doReturn(false).when(ordResolver).isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); + extendedServiceLoaderMockedStatic + .when(() -> loadAll(OrdResolver.class, cdsRuntime)) + .thenReturn(List.of(ordResolver).iterator()); - classUnderTest.doGet(request, response); + classUnderTest.doGet(request, response); - verify(request).getRequestURI(); - verify(response).setStatus(SC_NOT_FOUND); - verify(ordResourcesProvider).setPrevious(null); - verify(request).getParameter("perspective"); - verify(request).getHeader("Local-Tenant-Id"); - verify(authenticationManagerProvider).setPrevious(null); - verify(request, times(2)).getPathInfo(); - verify(ordResourcesProvider).read("documents/ord-document", null); - verify(authenticationManagerProvider).checkAuthorization("/ord/v1/documents/ord-document"); - verifyNoMoreInteractions( - request, - response, - printWriter, - servletOutputStream, - ordResourcesProvider, - authenticationManagerProvider); + verify(printWriter).close(); + verify(response).getWriter(); + verify(request).getRequestURI(); + verify(response).setStatus(SC_NOT_FOUND); + verify(printWriter).write("Not Found"); + verify(request).getParameter("perspective"); + verify(request).getHeader("Local-Tenant-Id"); + verify(authenticationManagerProvider).setPrevious(null); + verify(request, times(2)).getPathInfo(); + verify(authenticationManagerProvider).checkAuthorization("/ord/v1/documents/ord-document"); + verify(ordResolver).isApplicable("documents/ord-document", PERSPECTIVE_SYSTEM_VERSION); + verifyNoMoreInteractions( + request, response, printWriter, ordResolver, servletOutputStream, authenticationManagerProvider); + } } }