This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch 2.13.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit d7ce39e28867f1f100348fd436a9f2d098eae04f Author: Lukas Lowinger <[email protected]> AuthorDate: Thu Oct 20 13:31:42 2022 +0200 [closes #4203] Add tests for CXF SOAP MTOM --- .../cxf/soap/deployment/CxfSoapProcessor.java | 20 ++- .../cxf-soap/cxf-soap-mtom/README.adoc | 4 + .../cxf-soap/cxf-soap-mtom/pom.xml | 150 +++++++++++++++++++++ .../cxf/soap/mtom/it/CxfSoapMtomResource.java | 88 ++++++++++++ .../cxf/soap/mtom/it/CxfSoapMtomRoutes.java | 141 +++++++++++++++++++ .../component/cxf/soap/mtom/it/IImageService.java | 33 +++++ .../component/cxf/soap/mtom/it/ImageService.java | 63 +++++++++ .../cxf/soap/mtom/it/MtomAttachmentChecker.java | 96 +++++++++++++ .../src/main/resources/application.properties | 19 +++ .../component/cxf/soap/mtom/it/CxfSoapMtomIT.java | 23 ++++ .../cxf/soap/mtom/it/CxfSoapMtomTest.java | 83 ++++++++++++ .../src/test/resources/linux-image.png | Bin 0 -> 38982 bytes integration-test-groups/cxf-soap/pom.xml | 1 + integration-tests/cxf-soap-grouped/pom.xml | 16 ++- 14 files changed, 732 insertions(+), 5 deletions(-) diff --git a/extensions/cxf-soap/deployment/src/main/java/org/apache/camel/quarkus/component/cxf/soap/deployment/CxfSoapProcessor.java b/extensions/cxf-soap/deployment/src/main/java/org/apache/camel/quarkus/component/cxf/soap/deployment/CxfSoapProcessor.java index 17f76a9365..0e9985491f 100644 --- a/extensions/cxf-soap/deployment/src/main/java/org/apache/camel/quarkus/component/cxf/soap/deployment/CxfSoapProcessor.java +++ b/extensions/cxf-soap/deployment/src/main/java/org/apache/camel/quarkus/component/cxf/soap/deployment/CxfSoapProcessor.java @@ -25,6 +25,8 @@ import io.quarkus.deployment.builditem.CombinedIndexBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.SystemPropertyBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem; +import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; import org.jboss.jandex.DotName; import org.jboss.jandex.IndexView; @@ -43,7 +45,10 @@ class CxfSoapProcessor { } @BuildStep - void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, CombinedIndexBuildItem combinedIndex) { + void registerForReflection( + CombinedIndexBuildItem combinedIndex, + BuildProducer<ReflectiveClassBuildItem> reflectiveClass, + BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods) { IndexView index = combinedIndex.getIndex(); @@ -55,6 +60,19 @@ class CxfSoapProcessor { .map(className -> new ReflectiveClassBuildItem(false, false, className)) .forEach(reflectiveClass::produce); + reflectiveMethods.produce(new ReflectiveMethodBuildItem("org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory", + "getServiceFactory", new String[0])); + + } + + @BuildStep + void registerForReflection( + BuildProducer<RuntimeInitializedClassBuildItem> runtimeInitializedClasses) { + + // TODO: Move to quarkus-cxf + runtimeInitializedClasses + .produce(new RuntimeInitializedClassBuildItem("com.sun.xml.messaging.saaj.soap.StringDataContentHandler")); + } @BuildStep diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/README.adoc b/integration-test-groups/cxf-soap/cxf-soap-mtom/README.adoc new file mode 100644 index 0000000000..dac25bdb6f --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/README.adoc @@ -0,0 +1,4 @@ += Camel Quarkus CXF SOAP MTOM tests + +Tests are not using any external SOAP services (eg. via testcontainers). They purely test if Camel Quarkus is able to send and consume messages with attachments with both MTOM enabled/disabled. + diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/pom.xml b/integration-test-groups/cxf-soap/cxf-soap-mtom/pom.xml new file mode 100644 index 0000000000..ef3aea6031 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/pom.xml @@ -0,0 +1,150 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-build-parent-it</artifactId> + <version>2.13.1-SNAPSHOT</version> + <relativePath>../../../poms/build-parent-it/pom.xml</relativePath> + </parent> + + <artifactId>camel-quarkus-integration-test-cxf-soap-mtom</artifactId> + <name>Camel Quarkus :: Integration Tests :: Cxf Soap Mtom</name> + <description>Integration tests for Camel Quarkus CXF extension Mtom</description> + + <dependencies> + <dependency><!-- for java.awt.Image --> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-awt</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-cxf-soap</artifactId> + </dependency> + + + <!-- test dependencies --> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>virtualDependencies</id> + <activation> + <property> + <name>!noVirtualDependencies</name> + </property> + </activation> + <dependencies> + <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-cxf-soap-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + </profile> + </profiles> + +</project> diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomResource.java b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomResource.java new file mode 100644 index 0000000000..4a4b08ed08 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomResource.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.cxf.soap.mtom.it; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.net.URI; + +import javax.enterprise.context.ApplicationScoped; +import javax.imageio.ImageIO; +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.camel.ProducerTemplate; + +import static org.apache.camel.component.cxf.common.message.CxfConstants.OPERATION_NAME; + +@Path("/cxf-soap/mtom") +@ApplicationScoped +public class CxfSoapMtomResource { + + @Inject + ProducerTemplate producerTemplate; + + @Path("/upload") + @POST + @Produces(MediaType.TEXT_PLAIN) + public Response upload(@QueryParam("imageName") String imageName, @QueryParam("mtomEnabled") boolean mtomEnabled, + byte[] image) throws Exception { + try (ByteArrayInputStream bais = new ByteArrayInputStream(image)) { + final String response = producerTemplate.requestBodyAndHeader( + "direct:" + mtomEndpoint(mtomEnabled), + new Object[] { ImageIO.read(bais), imageName }, + OPERATION_NAME, "uploadImage", String.class); + return Response + .created(new URI("https://camel.apache.org/")) + .entity(response) + .build(); + } + } + + @Path("/download") + @POST + @Consumes(MediaType.TEXT_PLAIN) + public Response download(@QueryParam("imageName") String imageName, @QueryParam("mtomEnabled") boolean mtomEnabled) + throws Exception { + final BufferedImage response = (BufferedImage) producerTemplate.requestBodyAndHeader( + "direct:" + mtomEndpoint(mtomEnabled), + imageName, + OPERATION_NAME, + "downloadImage", Image.class); + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + ImageIO.write(response, "png", baos); + byte[] bytes = baos.toByteArray(); + return Response + .created(new URI("https://camel.apache.org/")) + .entity(bytes) + .build(); + } + } + + private String mtomEndpoint(boolean mtomEnabled) { + return mtomEnabled ? "mtomEnabledInvoker" : "mtomDisabledInvoker"; + } + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomRoutes.java b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomRoutes.java new file mode 100644 index 0000000000..a7f454a035 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomRoutes.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.cxf.soap.mtom.it; + +import java.util.ArrayList; +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.inject.Named; +import javax.xml.ws.handler.Handler; + +import io.quarkus.runtime.LaunchMode; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.cxf.jaxws.CxfEndpoint; +import org.apache.cxf.ext.logging.LoggingFeature; +import org.apache.cxf.message.MessageContentsList; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; + +@ApplicationScoped +public class CxfSoapMtomRoutes extends RouteBuilder { + + @Inject + @Named("loggingMtomFeatureClient") + LoggingFeature loggingFeature; + + @Override + public void configure() { + + from("direct:mtomEnabledInvoker") + .to("cxf:bean:soapMtomEnabledClientEndpoint?dataFormat=POJO"); + + from("direct:mtomDisabledInvoker") + .to("cxf:bean:soapMtomDisabledClientEndpoint?dataFormat=POJO"); + + from("cxf:bean:soapMtomEnabledServerEndpoint?dataFormat=POJO") + .to("direct:processImage"); + + from("cxf:bean:soapMtomDisabledServerEndpoint?dataFormat=POJO") + .to("direct:processImage"); + + from("direct:processImage") + .process("imageServiceProcessor") + .recipientList((simple("bean:imageService?method=${header.operationName}"))); + + } + + @ApplicationScoped + @Named("imageServiceProcessor") + static class ImageServiceProcessor implements Processor { + @Override + public void process(Exchange exchange) throws Exception { + String operationName = (String) exchange.getIn().getHeaders().get("operationName"); + MessageContentsList list = (MessageContentsList) exchange.getIn().getBody(); + if ("uploadImage".equals(operationName)) { + exchange.getIn().getHeaders().put("image", list.get(0)); + exchange.getIn().getHeaders().put("imageName", list.get(1)); + exchange.getIn().getHeaders() + .put("operationName", "uploadImage(${header.image},${header.imageName})"); + } else if ("downloadImage".equals(operationName)) { + exchange.getIn().setBody(list.get(0)); + } + } + + } + + @Produces + @ApplicationScoped + @Named("loggingMtomFeatureClient") + public LoggingFeature loggingFeature() { + final LoggingFeature result = new LoggingFeature(); + result.setPrettyLogging(true); + return result; + } + + @Produces + @ApplicationScoped + @Named + CxfEndpoint soapMtomEnabledClientEndpoint() { + return commonCxfEndpoint(true, getServerUrl() + "/soapservice/mtom-enabled-image-service"); + } + + @Produces + @ApplicationScoped + @Named + CxfEndpoint soapMtomDisabledClientEndpoint() { + return commonCxfEndpoint(false, getServerUrl() + "/soapservice/mtom-disabled-image-service"); + } + + @Produces + @ApplicationScoped + @Named + CxfEndpoint soapMtomEnabledServerEndpoint() { + return commonCxfEndpoint(true, "/mtom-enabled-image-service"); + } + + @Produces + @ApplicationScoped + @Named + CxfEndpoint soapMtomDisabledServerEndpoint() { + return commonCxfEndpoint(false, "/mtom-disabled-image-service"); + } + + CxfEndpoint commonCxfEndpoint(boolean mtomEnabled, String address) { + final CxfEndpoint result = new CxfEndpoint(); + result.getFeatures().add(loggingFeature); + result.setServiceClass(IImageService.class); + result.setMtomEnabled(mtomEnabled); + result.setAddress(address); + List<Handler> handlers = new ArrayList<>(); + handlers.add(new MtomAttachmentChecker(mtomEnabled)); + result.setHandlers(handlers); + return result; + } + + private static String getServerUrl() { + Config config = ConfigProvider.getConfig(); + final int port = LaunchMode.current().equals(LaunchMode.TEST) ? config.getValue("quarkus.http.test-port", Integer.class) + : config.getValue("quarkus.http.port", Integer.class); + return String.format("http://localhost:%d", port); + } + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/IImageService.java b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/IImageService.java new file mode 100644 index 0000000000..3340c2cfbf --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/IImageService.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.cxf.soap.mtom.it; + +import java.awt.*; + +import javax.jws.WebMethod; +import javax.jws.WebService; + +@WebService +public interface IImageService { + + @WebMethod + Image downloadImage(String name); + + @WebMethod + String uploadImage(Image image, String name); + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/ImageService.java b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/ImageService.java new file mode 100644 index 0000000000..93ec42986d --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/ImageService.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.cxf.soap.mtom.it; + +import java.awt.*; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Named; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ApplicationScoped +@Named("imageService") +public class ImageService implements IImageService { + + public static final String MSG_SUCCESS = "Upload Successful"; + private static final Logger log = LoggerFactory.getLogger(ImageService.class); + + private final Map<String, Image> imageRepository; + + public ImageService() { + imageRepository = new ConcurrentHashMap<>(); + } + + @Override + public Image downloadImage(String name) { + final Image image = imageRepository.get(name); + if (image == null) { + throw new IllegalStateException("Image with name " + name + " does not exist."); + } + return image; + } + + @Override + public String uploadImage(Image image, String name) { + + log.info("Upload image: " + image + " with name: " + name); + + if (image != null && name != null && !"".equals(name)) { + imageRepository.put(name, image); + return MSG_SUCCESS; + } + throw new IllegalStateException("Illegal Data Format."); + } + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/MtomAttachmentChecker.java b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/MtomAttachmentChecker.java new file mode 100644 index 0000000000..d8eefeafce --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/MtomAttachmentChecker.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.cxf.soap.mtom.it; + +import java.util.Collections; +import java.util.Set; + +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPEnvelope; +import javax.xml.soap.SOAPException; +import javax.xml.ws.WebServiceException; +import javax.xml.ws.handler.MessageContext; +import javax.xml.ws.handler.soap.SOAPHandler; +import javax.xml.ws.handler.soap.SOAPMessageContext; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Asserts whether the attachment is present where expected (inline or multipart body) throws an IllegalStateException + * to signal that something is wrong. + */ +public class MtomAttachmentChecker implements SOAPHandler<SOAPMessageContext> { + boolean mtomEnabled; + + public MtomAttachmentChecker(boolean mtomEnabled) { + this.mtomEnabled = mtomEnabled; + } + + static boolean walk(String localName, NodeList nodes) { + boolean found = false; + for (int i = 0; i < nodes.getLength(); i++) { + Node n = nodes.item(i); + if (localName.equals(n.getLocalName())) { + found = true; + break; + } else if (!found) { + found = walk(localName, n.getChildNodes()); + } + } + + return found; + } + + @Override + public boolean handleMessage(SOAPMessageContext msgContext) { + try { + SOAPEnvelope envelope = msgContext.getMessage().getSOAPPart().getEnvelope(); + SOAPBody body = envelope.getBody(); + boolean found = walk("Include", body.getChildNodes()); + if (mtomEnabled) { + // skip those messages which don't have attachments + boolean skip = walk("uploadImageResponse", body.getChildNodes()) || walk("downloadImage", body.getChildNodes()); + if (!skip && !found) { + throw new IllegalStateException("The SOAP message should contain an <xop:Include> element"); + } + } else if (found) { + throw new IllegalStateException("The SOAP message shouldn't contain an <xop:Include> element"); + } + + } catch (SOAPException ex) { + throw new WebServiceException(ex); + } + + return true; + } + + @Override + public boolean handleFault(SOAPMessageContext context) { + return true; + } + + @Override + public void close(MessageContext context) { + } + + @Override + public Set<QName> getHeaders() { + return Collections.emptySet(); + } +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/resources/application.properties b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/resources/application.properties new file mode 100644 index 0000000000..574727024a --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/main/resources/application.properties @@ -0,0 +1,19 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- + +quarkus.cxf.path=/soapservice +quarkus.native.resources.includes = wsdl/*.wsdl diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomIT.java b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomIT.java new file mode 100644 index 0000000000..6da4ad90da --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomIT.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.cxf.soap.mtom.it; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class CxfSoapMtomIT extends CxfSoapMtomTest { +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomTest.java b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomTest.java new file mode 100644 index 0000000000..9fdc27c1f8 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/it/CxfSoapMtomTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.cxf.soap.mtom.it; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import io.quarkus.test.junit.DisabledOnIntegrationTest; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@QuarkusTest +class CxfSoapMtomTest { + + @DisabledOnIntegrationTest("https://github.com/apache/camel-quarkus/issues/4208") + @ParameterizedTest + @ValueSource(booleans = { true, false }) + public void uploadDownloadMtom(boolean mtomEnabled) throws IOException { + byte[] imageBytes = CxfSoapMtomTest.class.getClassLoader().getResourceAsStream("linux-image.png").readAllBytes(); + String imageName = "linux-image-name"; + RestAssured.given() + .contentType(ContentType.BINARY) + .queryParam("imageName", imageName) + .queryParam("mtomEnabled", mtomEnabled) + .body(imageBytes) + .post("/cxf-soap/mtom/upload") + .then() + .statusCode(201) + .body(CoreMatchers.equalTo(ImageService.MSG_SUCCESS)); + byte[] downloadedImageBytes = RestAssured.given() + .contentType(ContentType.TEXT) + .queryParam("imageName", imageName) + .queryParam("mtomEnabled", mtomEnabled) + .post("/cxf-soap/mtom/download") + .then() + .statusCode(201) + .extract().asByteArray(); + + try (ByteArrayInputStream imageBais = new ByteArrayInputStream( + imageBytes); ByteArrayInputStream downloadedImageBais = new ByteArrayInputStream(downloadedImageBytes)) { + Assertions.assertTrue(bufferedImagesEqual(ImageIO.read(imageBais), + ImageIO.read(downloadedImageBais)), "Uploaded image should match downloaded"); + } + } + + // copied from https://stackoverflow.com/a/15305092 + boolean bufferedImagesEqual(BufferedImage img1, BufferedImage img2) { + if (img1.getWidth() == img2.getWidth() && img1.getHeight() == img2.getHeight()) { + for (int x = 0; x < img1.getWidth(); x++) { + for (int y = 0; y < img1.getHeight(); y++) { + if (img1.getRGB(x, y) != img2.getRGB(x, y)) + return false; + } + } + } else { + return false; + } + return true; + } + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/resources/linux-image.png b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/resources/linux-image.png new file mode 100644 index 0000000000..17d7bfef0d Binary files /dev/null and b/integration-test-groups/cxf-soap/cxf-soap-mtom/src/test/resources/linux-image.png differ diff --git a/integration-test-groups/cxf-soap/pom.xml b/integration-test-groups/cxf-soap/pom.xml index d5f1c22d43..bfb960c740 100644 --- a/integration-test-groups/cxf-soap/pom.xml +++ b/integration-test-groups/cxf-soap/pom.xml @@ -38,6 +38,7 @@ <modules> <!-- extensions a..z; do not remove this comment, it is important when sorting via mvn process-resources -Pformat --> <module>cxf-soap-client</module> + <module>cxf-soap-mtom</module> <module>cxf-soap-server</module> <module>cxf-soap-ws-security-client</module> </modules> diff --git a/integration-tests/cxf-soap-grouped/pom.xml b/integration-tests/cxf-soap-grouped/pom.xml index ca70eea4f2..6b809b1b6e 100644 --- a/integration-tests/cxf-soap-grouped/pom.xml +++ b/integration-tests/cxf-soap-grouped/pom.xml @@ -32,6 +32,14 @@ <!-- Regenerate the dependencies via `mvn process-resources -Pformat -N` from the source tree root directory --> <dependencies> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct</artifactId> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-cxf-soap</artifactId> @@ -48,13 +56,13 @@ <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> - <dependency> + <dependency><!-- for java.awt.Image --> <groupId>io.quarkus</groupId> - <artifactId>quarkus-resteasy</artifactId> + <artifactId>quarkus-awt</artifactId> </dependency> <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-direct</artifactId> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy</artifactId> </dependency> <!-- test dependencies -->
