Skip to content

Commit

Permalink
W-17671141: Reintroduce SOAP Service (#498)
Browse files Browse the repository at this point in the history
* Revert "W-17245993: Remove SOAP service (#491)"
  • Loading branch information
elrodro83 authored Jan 27, 2025
1 parent 75d790e commit 9370a10
Show file tree
Hide file tree
Showing 155 changed files with 61,626 additions and 0 deletions.
457 changes: 457 additions & 0 deletions pom.xml

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2023 Salesforce, Inc. All rights reserved.
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
import org.mule.api.annotation.jpms.ServiceModule;

/**
* A SOAP service based on CXF.
*
* @moduleGraph
* @since 1.5
*/
@ServiceModule
module org.mule.service.soap {

requires org.mule.runtime.metadata.model.api;
requires org.mule.runtime.api;
requires org.mule.runtime.extensions.api;
requires org.mule.runtime.extensions.soap.api;
requires org.mule.runtime.http.api;
requires org.mule.runtime.soap.api;
// lifecycle api
requires org.mule.runtime.core;

requires org.apache.cxf.binding.soap;
requires org.apache.cxf.core;
requires org.apache.cxf.frontend.simple;
requires org.apache.cxf.ws.security;
requires org.apache.cxf.wsdl;
requires org.apache.wss4j.common;
requires org.apache.wss4j.dom;

requires org.mule.wsdl.parser;
requires mule.wsdl4j;

requires com.ctc.wstx;
requires org.dom4j;
requires stax.utils;
requires Saxon.HE;

requires com.google.common;
requires org.apache.commons.io;
requires org.apache.commons.lang3;

requires jakarta.activation;
requires java.logging;
requires java.xml.soap;

// Allow invocation and injection into providers by the Mule Runtime
exports org.mule.service.soap.provider to
org.mule.runtime.service;

}
29 changes: 29 additions & 0 deletions src/main/java/org/mule/service/soap/SoapServiceImplementation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2023 Salesforce, Inc. All rights reserved.
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.service.soap;

import org.mule.runtime.soap.api.SoapService;
import org.mule.runtime.soap.api.client.SoapClientFactory;
import org.mule.service.soap.client.SoapCxfClientFactory;

/**
* Default Mule {@link SoapService} implementation.
*
* @since 1.0
*/
public class SoapServiceImplementation implements SoapService {

@Override
public String getName() {
return "SOAP Service";
}

@Override
public SoapClientFactory getClientFactory() {
return new SoapCxfClientFactory();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2023 Salesforce, Inc. All rights reserved.
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.service.soap.client;

import static java.lang.String.format;
import static java.util.Collections.emptyMap;
import static org.mule.runtime.http.api.HttpHeaders.Names.CONTENT_DISPOSITION;
import static org.mule.service.soap.util.AttachmentsUtils.toDataHandler;

import com.google.common.collect.ImmutableMap;
import org.apache.cxf.attachment.AttachmentImpl;
import org.apache.cxf.message.Attachment;
import org.mule.runtime.extension.api.soap.SoapAttachment;
import org.mule.runtime.soap.api.exception.BadRequestException;

import java.io.IOException;
import java.util.Map;

/**
* A factory for CXF {@link Attachment}s.
* <p>
* Creates the CXF {@link Attachment}s from {@link SoapAttachment}
*
* @since 1.2
*/
class CxfAttachmentsFactory {

private boolean isMtom;

CxfAttachmentsFactory(boolean isMtom) {
this.isMtom = isMtom;
}

public Map<String, Attachment> transformToCxfAttachments(Map<String, SoapAttachment> attachments) {
if (!isMtom) {
return emptyMap();
}
ImmutableMap.Builder<String, Attachment> builder = ImmutableMap.builder();
attachments.forEach((name, value) -> {
try {
AttachmentImpl attachment = new AttachmentImpl(name, toDataHandler(name, value.getContent(), value.getContentType()));
attachment.setHeader(CONTENT_DISPOSITION, "attachment; name=\"" + name + "\"");
builder.put(name, attachment);
} catch (IOException e) {
throw new BadRequestException(format("Error while preparing attachment [%s] for upload", name), e);
}
});
return builder.build();
}

}
107 changes: 107 additions & 0 deletions src/main/java/org/mule/service/soap/client/CxfClientFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2023 Salesforce, Inc. All rights reserved.
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.service.soap.client;

import static org.mule.runtime.core.api.util.ClassUtils.withContextClassLoader;

import org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean;
import org.mule.service.soap.conduit.SoapServiceConduitInitiator;

import org.apache.cxf.Bus;
import org.apache.cxf.binding.soap.SoapVersion;
import org.apache.cxf.binding.soap.SoapVersionFactory;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.databinding.stax.StaxDataBinding;
import org.apache.cxf.databinding.stax.StaxDataBindingFeature;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientFactoryBean;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.transport.ConduitInitiatorManager;

import java.lang.reflect.Method;
import java.util.Iterator;

import javax.xml.transform.Source;

/**
* A factory for CXF {@link Client}s.
* <p>
* Sets up the custom {@link SoapServiceConduitInitiator} for all the different entries used for CXF to obtain the needed
* {@link Conduit}, this occurs because we want that CXF always use our custom conduit to operate.
*
* @since 1.0
*/
class CxfClientFactory {

private final Bus bus;

CxfClientFactory() {
this.bus = withContextClassLoader(CxfClientFactory.class.getClassLoader(),
() -> new SpringBusFactory().createBus((String) null, true));
registerConduitInitiator(new SoapServiceConduitInitiator());
}

private void registerConduitInitiator(SoapServiceConduitInitiator initiator) {
ConduitInitiatorManager extension = bus.getExtension(ConduitInitiatorManager.class);
extension.registerConduitInitiator("http://cxf.apache.org/transports/http", initiator);
extension.registerConduitInitiator("http://schemas.xmlsoap.org/wsdl/soap/", initiator);
extension.registerConduitInitiator("http://schemas.xmlsoap.org/soap/http/", initiator);
extension.registerConduitInitiator("http://schemas.xmlsoap.org/wsdl/soap/http", initiator);
extension.registerConduitInitiator("http://schemas.xmlsoap.org/wsdl/http/", initiator);
extension.registerConduitInitiator("http://www.w3.org/2003/05/soap/bindings/HTTP/", initiator);
extension.registerConduitInitiator("http://cxf.apache.org/transports/http/configuration", initiator);
extension.registerConduitInitiator("http://cxf.apache.org/bindings/xformat", initiator);
extension.registerConduitInitiator("http://cxf.apache.org/transports/jms", initiator);
extension.registerConduitInitiator("http://mule.codehaus.org/ws", initiator);
}

public Client createClient(String address, String soapVersion) {
return withContextClassLoader(CxfClientFactory.class.getClassLoader(), () -> {
ReflectionServiceFactoryBean serviceFactoryBean = new ReflectionServiceFactoryBean();
serviceFactoryBean.getServiceConfigurations().add(0, new DefaultServiceConfiguration());
ClientFactoryBean factory = new ClientFactoryBean(serviceFactoryBean);
factory.setServiceClass(ProxyService.class);
factory.setDataBinding(new StaxDataBinding());
factory.getFeatures().add(new StaxDataBindingFeature());
factory.setAddress(address);
factory.setBus(bus);
factory.setBindingId(getBindingIdForSoapVersion(soapVersion));
return factory.create();
});

}

private String getBindingIdForSoapVersion(String version) {
Iterator<SoapVersion> soapVersions = SoapVersionFactory.getInstance().getVersions();
while (soapVersions.hasNext()) {
SoapVersion soapVersion = soapVersions.next();
if (Double.toString(soapVersion.getVersion()).equals(version)) {
return soapVersion.getBindingId();
}
}
throw new IllegalArgumentException("Invalid Soap version " + version);
}

/**
* Interface that describes the implementing the service.
*/
private interface ProxyService {

Source invoke(Source source);

void invokeOneWay(Source source);

}

public class DefaultServiceConfiguration extends org.apache.cxf.wsdl.service.factory.DefaultServiceConfiguration {

public Boolean hasOutMessage(Method m) {
return !m.getName().equals("invokeOneWay");
}

}
}
Loading

0 comments on commit 9370a10

Please sign in to comment.