network.oxalis.as4.outbound.As4MessageSender Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oxalis-as4 Show documentation
Show all versions of oxalis-as4 Show documentation
Extension adding AS4 support to Oxalis
package network.oxalis.as4.outbound;
import com.google.inject.Inject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import network.oxalis.as4.api.MessageIdGenerator;
import network.oxalis.as4.common.AS4Constants;
import network.oxalis.as4.common.MerlinProvider;
import network.oxalis.as4.config.As4Conf;
import network.oxalis.as4.lang.OxalisAs4TransmissionException;
import network.oxalis.as4.util.CompressionUtil;
import network.oxalis.as4.util.Constants;
import network.oxalis.as4.util.PolicyService;
import network.oxalis.api.outbound.TransmissionRequest;
import network.oxalis.api.outbound.TransmissionResponse;
import network.oxalis.api.settings.Settings;
import network.oxalis.commons.http.HttpConf;
import network.oxalis.commons.security.KeyStoreConf;
import org.apache.cxf.attachment.AttachmentUtil;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.ext.logging.LoggingFeature;
import org.apache.cxf.headers.Header;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.jaxws.DispatchImpl;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.apache.cxf.ws.policy.WSPolicyFeature;
import org.apache.wss4j.common.crypto.Merlin;
import org.oasis_open.docs.ebxml_msg.ebms.v3_0.ns.core._200704.Messaging;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import static org.apache.cxf.rt.security.SecurityConstants.*;
import static org.apache.cxf.ws.security.SecurityConstants.USE_ATTACHMENT_ENCRYPTION_CONTENT_ONLY_TRANSFORM;
@Slf4j
public class As4MessageSender {
public static final QName SERVICE_NAME = new QName("oxalis.network/", "outbound-service");
public static final QName PORT_NAME = new QName("oxalis.network/", "port");
private final MessagingProvider messagingProvider;
private final MessageIdGenerator messageIdGenerator;
private final Settings settings;
private final Settings as4settings;
private final CompressionUtil compressionUtil;
private final Settings httpConfSettings;
private final TransmissionResponseConverter transmissionResponseConverter;
private final MerlinProvider merlinProvider;
private final PolicyService policyService;
private final String browserType;
@Inject
public As4MessageSender(MessagingProvider messagingProvider, MessageIdGenerator messageIdGenerator, Settings settings, Settings as4settings, CompressionUtil compressionUtil, Settings httpConfSettings, TransmissionResponseConverter transmissionResponseConverter, MerlinProvider merlinProvider, PolicyService policyService, BrowserTypeProvider browserTypeProvider) {
this.messagingProvider = messagingProvider;
this.messageIdGenerator = messageIdGenerator;
this.settings = settings;
this.as4settings = as4settings;
this.compressionUtil = compressionUtil;
this.httpConfSettings = httpConfSettings;
this.transmissionResponseConverter = transmissionResponseConverter;
this.merlinProvider = merlinProvider;
this.policyService = policyService;
this.browserType = browserTypeProvider.getBrowserType();
}
public TransmissionResponse send(TransmissionRequest request) throws OxalisAs4TransmissionException {
AttachmentHolder attachmentHolder = null;
try (DispatchImpl dispatch = createDispatch(request)) {
attachmentHolder = prepareAttachment(request);
ArrayList attachments = new ArrayList<>(Collections.singletonList(attachmentHolder.attachment));
dispatch.getRequestContext().put(Message.ATTACHMENTS, attachments);
Messaging messaging = messagingProvider.createMessagingHeader(request, attachments);
SoapHeader header = getSoapHeader(messaging);
dispatch.getRequestContext().put(Header.HEADER_LIST, new ArrayList<>(Collections.singletonList(header)));
return invoke(request, dispatch);
} catch (IOException e) {
throw new OxalisAs4TransmissionException("Failed to send message", e);
} finally {
if (attachmentHolder != null) {
try {
attachmentHolder.inputStream.close();
} catch (IOException e) {
log.error("Couldn't close attachment input stream", e);
}
}
}
}
private TransmissionResponse invoke(TransmissionRequest request, DispatchImpl dispatch) throws OxalisAs4TransmissionException {
try {
SOAPMessage response = dispatch.invoke(null);
return transmissionResponseConverter.convert(request, response);
} catch (Exception e) {
throw new OxalisAs4TransmissionException("Failed to send message", e);
}
}
private SoapHeader getSoapHeader(Messaging messaging) throws OxalisAs4TransmissionException {
try {
JAXBDataBinding binding = new JAXBDataBinding(Messaging.class);
return new SoapHeader(
Constants.MESSAGING_QNAME,
messaging,
binding,
true);
} catch (JAXBException e) {
throw new OxalisAs4TransmissionException("Unable to marshal AS4 header", e);
}
}
private void configureSecurity(TransmissionRequest request, Dispatch dispatch) {
Merlin merlin = merlinProvider.getMerlin();
dispatch.getRequestContext().put(SIGNATURE_CRYPTO, merlin);
dispatch.getRequestContext().put(SIGNATURE_PASSWORD, settings.getString(KeyStoreConf.KEY_PASSWORD));
dispatch.getRequestContext().put(SIGNATURE_USERNAME, settings.getString(KeyStoreConf.KEY_ALIAS));
dispatch.getRequestContext().put(ENCRYPT_CERT, request.getEndpoint().getCertificate());
dispatch.getRequestContext().put(USE_ATTACHMENT_ENCRYPTION_CONTENT_ONLY_TRANSFORM, true);
}
public AttachmentHolder prepareAttachment(TransmissionRequest request) throws OxalisAs4TransmissionException {
Map> headers = new HashMap<>();
headers.put("Content-ID", Collections.singletonList(getContentID(request)));
headers.put("CompressionType", Collections.singletonList("application/gzip"));
headers.put("MimeType", Collections.singletonList("application/xml"));
try {
InputStream compressedStream = compressionUtil.getCompressedStream(request.getPayload());
Attachment attachment = AttachmentUtil.createAttachment(compressedStream, headers);
return new AttachmentHolder(compressedStream, attachment);
} catch (IOException e) {
throw new OxalisAs4TransmissionException("Unable to compress payload", e);
}
}
private String getContentID(TransmissionRequest request) {
if (request instanceof As4TransmissionRequest) {
As4TransmissionRequest as4request = (As4TransmissionRequest) request;
return as4request.getPayloadHref();
}
return messageIdGenerator.generate();
}
private DispatchImpl createDispatch(TransmissionRequest request) throws OxalisAs4TransmissionException {
DispatchImpl dispatch = (DispatchImpl) getService(request)
.createDispatch(PORT_NAME, SOAPMessage.class, Service.Mode.MESSAGE);
dispatch.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, request.getEndpoint().getAddress().toString());
configureSecurity(request, dispatch);
final Client client = dispatch.getClient();
if (AS4Constants.CEF_CONFORMANCE.equalsIgnoreCase(as4settings.getString(As4Conf.TYPE))) {
client.getInInterceptors().add(getLoggingBeforeSecurityInInterceptor());
}
final HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
final HTTPClientPolicy httpClientPolicy = httpConduit.getClient();
httpClientPolicy.setConnectionTimeout(httpConfSettings.getInt(HttpConf.TIMEOUT_CONNECT));
httpClientPolicy.setReceiveTimeout(httpConfSettings.getInt(HttpConf.TIMEOUT_READ));
httpClientPolicy.setAllowChunking(true);
httpClientPolicy.setChunkLength(8192);
httpClientPolicy.setBrowserType(browserType);
return dispatch;
}
private LoggingBeforeSecurityInInterceptor getLoggingBeforeSecurityInInterceptor() {
LoggingBeforeSecurityInInterceptor interceptor = new LoggingBeforeSecurityInInterceptor();
interceptor.setPrettyLogging(true);
interceptor.setLogMultipart(true);
return interceptor;
}
private Service getService(TransmissionRequest request) throws OxalisAs4TransmissionException {
Service service = Service.create(SERVICE_NAME, new LoggingFeature(), new WSPolicyFeature(policyService.getPolicy(request)));
service.addPort(PORT_NAME, SOAPBinding.SOAP12HTTP_BINDING, request.getEndpoint().getAddress().toString());
return service;
}
@RequiredArgsConstructor
private static class AttachmentHolder {
private final InputStream inputStream;
private final Attachment attachment;
}
}