All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.helger.phase4.cef.Phase4CEFSender Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2020 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * Licensed 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 com.helger.phase4.cef;

import java.security.cert.X509Certificate;
import java.util.Locale;
import java.util.function.Consumer;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.annotation.concurrent.Immutable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.collection.impl.CommonsArrayList;
import com.helger.commons.collection.impl.ICommonsList;
import com.helger.commons.state.ESuccess;
import com.helger.commons.string.StringHelper;
import com.helger.commons.traits.IGenericImplTrait;
import com.helger.httpclient.HttpClientFactory;
import com.helger.peppolid.IDocumentTypeIdentifier;
import com.helger.peppolid.IParticipantIdentifier;
import com.helger.peppolid.IProcessIdentifier;
import com.helger.peppolid.factory.SimpleIdentifierFactory;
import com.helger.phase4.CAS4;
import com.helger.phase4.attachment.IIncomingAttachmentFactory;
import com.helger.phase4.attachment.Phase4OutgoingAttachment;
import com.helger.phase4.attachment.WSS4JAttachment;
import com.helger.phase4.client.AS4ClientUserMessage;
import com.helger.phase4.client.IAS4ClientBuildMessageCallback;
import com.helger.phase4.client.IAS4RawResponseConsumer;
import com.helger.phase4.client.IAS4RetryCallback;
import com.helger.phase4.client.IAS4SignalMessageConsumer;
import com.helger.phase4.crypto.AS4CryptoFactoryPropertiesFile;
import com.helger.phase4.crypto.IAS4CryptoFactory;
import com.helger.phase4.dump.IAS4IncomingDumper;
import com.helger.phase4.dump.IAS4OutgoingDumper;
import com.helger.phase4.messaging.domain.MessageHelperMethods;
import com.helger.phase4.model.pmode.IPMode;
import com.helger.phase4.model.pmode.resolve.DefaultPModeResolver;
import com.helger.phase4.model.pmode.resolve.IPModeResolver;
import com.helger.phase4.servlet.AS4BidirectionalClientHelper;
import com.helger.phase4.soap.ESoapVersion;
import com.helger.phase4.util.AS4ResourceHelper;
import com.helger.smpclient.bdxr1.IBDXRServiceMetadataProvider;
import com.helger.smpclient.url.BDXLURLProvider;
import com.helger.smpclient.url.IBDXLURLProvider;

/**
 * This class contains all the specifics to send AS4 messages with the CEF
 * profile. See sendAS4Message as the main method to trigger the
 * sending, with all potential customization.
 *
 * @author Philip Helger
 * @since 0.9.15
 */
@Immutable
public final class Phase4CEFSender
{
  public static final SimpleIdentifierFactory IF = SimpleIdentifierFactory.INSTANCE;
  public static final IBDXLURLProvider URL_PROVIDER = BDXLURLProvider.INSTANCE;

  private static final Logger LOGGER = LoggerFactory.getLogger (Phase4CEFSender.class);

  private Phase4CEFSender ()
  {}

  /**
   * @return Create a new Builder for AS4 messages if the payload is present and
   *         the SBDH should be created internally. Never null.
   */
  @Nonnull
  public static Builder builder ()
  {
    return new Builder ();
  }

  /**
   * Abstract builder base class with the minimum requirements configuration
   *
   * @author Philip Helger
   * @param 
   *        The implementation type
   */
  public static abstract class AbstractBaseBuilder > implements IGenericImplTrait 
  {
    protected HttpClientFactory m_aHttpClientFactory;
    protected IAS4CryptoFactory m_aCryptoFactory;
    protected IPModeResolver m_aPModeResolver;
    protected IIncomingAttachmentFactory m_aIAF;
    protected IPMode m_aPMode;

    protected IParticipantIdentifier m_aSenderID;
    protected IParticipantIdentifier m_aReceiverID;
    protected IDocumentTypeIdentifier m_aDocTypeID;
    protected IProcessIdentifier m_aProcessID;
    protected String m_sServiceType;
    protected String m_sService;
    protected String m_sAction;
    protected String m_sAgreementRef;
    protected IParticipantIdentifier m_aFromPartyID;
    protected String m_sFromRole;
    protected IParticipantIdentifier m_aToPartyID;
    protected String m_sToRole;
    protected String m_sMessageID;
    protected String m_sConversationID;

    protected IPhase4CEFEndpointDetailProvider m_aEndpointDetailProvider;

    protected IAS4ClientBuildMessageCallback m_aBuildMessageCallback;
    protected IAS4OutgoingDumper m_aOutgoingDumper;
    protected IAS4IncomingDumper m_aIncomingDumper;
    protected IAS4RetryCallback m_aRetryCallback;
    protected IAS4RawResponseConsumer m_aResponseConsumer;
    protected IAS4SignalMessageConsumer m_aSignalMsgConsumer;

    /**
     * Create a new builder, with the following fields already set:
* {@link #setHttpClientFactory(HttpClientFactory)}
* {@link #setCryptoFactory(IAS4CryptoFactory)}
* {@link #setPModeResolver(IPModeResolver)}
* {@link #setIncomingAttachmentFactory(IIncomingAttachmentFactory)}
* {@link #setPMode(IPMode)}
*/ protected AbstractBaseBuilder () { // Set default values try { setHttpClientFactory (new HttpClientFactory (new Phase4CEFHttpClientSettings ())); setCryptoFactory (AS4CryptoFactoryPropertiesFile.getDefaultInstance ()); final IPModeResolver aPModeResolver = DefaultPModeResolver.DEFAULT_PMODE_RESOLVER; setPModeResolver (aPModeResolver); setIncomingAttachmentFactory (IIncomingAttachmentFactory.DEFAULT_INSTANCE); setPMode (aPModeResolver.getPModeOfID (null, "s", "a", "i", "r", null)); } catch (final Exception ex) { throw new IllegalStateException ("Failed to init AS4 Client builder", ex); } } /** * Set the HTTP client factory to be used. By default an instance of * {@link HttpClientFactory} is used and there is no need to invoke this * method. * * @param aHttpClientFactory * The new HTTP client factory to be used. May not be * null. * @return this for chaining */ @Nonnull public final IMPLTYPE setHttpClientFactory (@Nonnull final HttpClientFactory aHttpClientFactory) { ValueEnforcer.notNull (aHttpClientFactory, "HttpClientFactory"); m_aHttpClientFactory = aHttpClientFactory; return thisAsT (); } /** * Set the crypto factory to be used. The default crypto factory uses the * properties from the file "crypto.properties". * * @param aCryptoFactory * The crypto factory to be used. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setCryptoFactory (@Nonnull final IAS4CryptoFactory aCryptoFactory) { ValueEnforcer.notNull (aCryptoFactory, "CryptoFactory"); m_aCryptoFactory = aCryptoFactory; return thisAsT (); } /** * Set the PMode resolver to be used. * * @param aPModeResolver * The PMode resolver to be used. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setPModeResolver (@Nonnull final IPModeResolver aPModeResolver) { ValueEnforcer.notNull (aPModeResolver, "aPModeResolver"); m_aPModeResolver = aPModeResolver; return thisAsT (); } /** * Set the incoming attachment factory to be used. * * @param aIAF * The incoming attachment factory to be used. May not be * null. * @return this for chaining */ @Nonnull public final IMPLTYPE setIncomingAttachmentFactory (@Nonnull final IIncomingAttachmentFactory aIAF) { ValueEnforcer.notNull (aIAF, "IAF"); m_aIAF = aIAF; return thisAsT (); } /** * @return The used P-Mode. Never null. */ @Nonnull public final IPMode getPMode () { return m_aPMode; } /** * Set the PMode to be used. By default a generic PMode for CEF purposes is * used so there is no need to invoke this method. * * @param aPMode * The PMode to be used. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setPMode (@Nonnull final IPMode aPMode) { ValueEnforcer.notNull (aPMode, "PMode"); m_aPMode = aPMode; return thisAsT (); } /** * Set the sender participant ID of the message. The participant ID must be * provided prior to sending. This ends up in the "originalSender" * UserMessage property. * * @param aSenderID * The sender participant ID. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setSenderParticipantID (@Nonnull final IParticipantIdentifier aSenderID) { ValueEnforcer.notNull (aSenderID, "SenderID"); m_aSenderID = aSenderID; return thisAsT (); } /** * Set the receiver participant ID of the message. The participant ID must * be provided prior to sending. This ends up in the "finalRecipient" * UserMessage property. * * @param aReceiverID * The receiver participant ID. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setReceiverParticipantID (@Nonnull final IParticipantIdentifier aReceiverID) { ValueEnforcer.notNull (aReceiverID, "ReceiverID"); m_aReceiverID = aReceiverID; return thisAsT (); } /** * Set the document type ID to be send. The document type must be provided * prior to sending. * * @param aDocTypeID * The document type ID to be used. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setDocumentTypeID (@Nonnull final IDocumentTypeIdentifier aDocTypeID) { ValueEnforcer.notNull (aDocTypeID, "DocTypeID"); m_aDocTypeID = aDocTypeID; return thisAsT (); } /** * Set the process ID to be send. The process ID must be provided prior to * sending. * * @param aProcessID * The process ID to be used. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setProcessID (@Nonnull final IProcessIdentifier aProcessID) { ValueEnforcer.notNull (aProcessID, "ProcessID"); m_aProcessID = aProcessID; return thisAsT (); } /** * Set the "Service" value consisting of type and value. It's optional. If * the "Service" value is not set, it the "service type" defaults to the * "process identifier scheme" and the "service value" defaults to the * "process identifier value". * * @param sServiceType * Service type. May be null. * @param sServiceValue * Service value. May be null. * @return this for chaining. */ @Nonnull public final IMPLTYPE setService (@Nullable final String sServiceType, @Nullable final String sServiceValue) { m_sServiceType = sServiceType; m_sService = sServiceValue; return thisAsT (); } /** * Set the "Action" value. It's optional. If the "Action" value is not set, * it defaults to the "document type identifier value" (URI encoded). * * @param sAction * Action value. May be null. * @return this for chaining. */ @Nonnull public final IMPLTYPE setAction (@Nullable final String sAction) { m_sAction = sAction; return thisAsT (); } /** * Set the "AgreementRef" value. It's optional. * * @param sAgreementRef * Agreement reference. May be null. * @return this for chaining. */ @Nonnull public final IMPLTYPE setAgreementRef (@Nullable final String sAgreementRef) { m_sAgreementRef = sAgreementRef; return thisAsT (); } /** * Set the "from party ID". This is mandatory * * @param aFromPartyID * The from party ID. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setFromPartyID (@Nonnull @Nonempty final IParticipantIdentifier aFromPartyID) { ValueEnforcer.notNull (aFromPartyID, "FromPartyID"); m_aFromPartyID = aFromPartyID; return thisAsT (); } /** * Set the "from party role". This is optional * * @param sFromRole * The from role. May be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setFromRole (@Nullable final String sFromRole) { m_sFromRole = sFromRole; return thisAsT (); } /** * Set the "to party ID". This is mandatory * * @param aToPartyID * The to party ID. May not be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setToPartyID (@Nonnull @Nonempty final IParticipantIdentifier aToPartyID) { ValueEnforcer.notNull (aToPartyID, "ToPartyID"); m_aToPartyID = aToPartyID; return thisAsT (); } /** * Set the "to party role". This is optional * * @param sToRole * The to role. May be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setToRole (@Nullable final String sToRole) { m_sToRole = sToRole; return thisAsT (); } /** * Set the optional AS4 message ID. If this field is not set, a random * message ID is created. * * @param sMessageID * The optional AS4 message ID to be used. May be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setMessageID (@Nullable final String sMessageID) { m_sMessageID = sMessageID; return thisAsT (); } /** * Set the optional AS4 conversation ID. If this field is not set, a random * conversation ID is created. * * @param sConversationID * The optional AS4 conversation ID to be used. May be * null. * @return this for chaining */ @Nonnull public final IMPLTYPE setConversationID (@Nullable final String sConversationID) { m_sConversationID = sConversationID; return thisAsT (); } /** * Set the abstract endpoint detail provider to be used. This can be an SMP * lookup routine or in certain test cases a predefined certificate and * endpoint URL. * * @param aEndpointDetailProvider * The endpoint detail provider to be used. May not be * null. * @return this for chaining * @see #setSMPClient(IBDXRServiceMetadataProvider) */ @Nonnull public final IMPLTYPE setEndpointDetailProvider (@Nonnull final IPhase4CEFEndpointDetailProvider aEndpointDetailProvider) { ValueEnforcer.notNull (aEndpointDetailProvider, "EndpointDetailProvider"); m_aEndpointDetailProvider = aEndpointDetailProvider; return thisAsT (); } /** * Set the SMP client to be used. This is the point where e.g. the * differentiation between SMK and SML can be done. This must be set prior * to sending. * * @param aSMPClient * The SMP client to be used. May not be null. * @return this for chaining * @see #setEndpointDetailProvider(IPhase4CEFEndpointDetailProvider) */ @Nonnull public final IMPLTYPE setSMPClient (@Nonnull final IBDXRServiceMetadataProvider aSMPClient) { return setEndpointDetailProvider (new Phase4CEFEndpointDetailProviderBDXR (aSMPClient)); } @Nonnull public final IMPLTYPE setReceiverEndpointDetails (@Nonnull final X509Certificate aCert, @Nonnull @Nonempty final String sDestURL) { return setEndpointDetailProvider (new Phase4CEFEndpointDetailProviderConstant (aCert, sDestURL)); } /** * Set a internal message callback. Usually this method is NOT needed. Use * only when you know what you are doing. * * @param aBuildMessageCallback * An internal to be used for the created message. Maybe * null. * @return this for chaining */ @Nonnull public final IMPLTYPE setBuildMessageCallback (@Nullable final IAS4ClientBuildMessageCallback aBuildMessageCallback) { m_aBuildMessageCallback = aBuildMessageCallback; return thisAsT (); } /** * Set a specific outgoing dumper for this builder. * * @param aOutgoingDumper * An outgoing dumper to be used. Maybe null. If * null the global outgoing dumper is used. * @return this for chaining */ @Nonnull public final IMPLTYPE setOutgoingDumper (@Nullable final IAS4OutgoingDumper aOutgoingDumper) { m_aOutgoingDumper = aOutgoingDumper; return thisAsT (); } /** * Set a specific incoming dumper for this builder. * * @param aIncomingDumper * An incoming dumper to be used. Maybe null. If * null the global incoming dumper is used. * @return this for chaining */ @Nonnull public final IMPLTYPE setIncomingDumper (@Nullable final IAS4IncomingDumper aIncomingDumper) { m_aIncomingDumper = aIncomingDumper; return thisAsT (); } /** * Set an optional handler that is notified if an http sending will be * retried. This method is optional and must not be called prior to sending. * * @param aRetryCallback * The optional retry callback. May be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setRetryCallback (@Nullable final IAS4RetryCallback aRetryCallback) { m_aRetryCallback = aRetryCallback; return thisAsT (); } /** * Set an optional handler for the synchronous result message received from * the other side. This method is optional and must not be called prior to * sending. * * @param aResponseConsumer * The optional response consumer. May be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setRawResponseConsumer (@Nullable final IAS4RawResponseConsumer aResponseConsumer) { m_aResponseConsumer = aResponseConsumer; return thisAsT (); } /** * Set an optional Ebms3 Signal Message Consumer. If this consumer is set, * the response is trying to be parsed as a Signal Message. This method is * optional and must not be called prior to sending. * * @param aSignalMsgConsumer * The optional signal message consumer. May be null. * @return this for chaining */ @Nonnull public final IMPLTYPE setSignalMsgConsumer (@Nullable final IAS4SignalMessageConsumer aSignalMsgConsumer) { m_aSignalMsgConsumer = aSignalMsgConsumer; return thisAsT (); } @OverridingMethodsMustInvokeSuper public boolean isEveryRequiredFieldSet () { if (m_aHttpClientFactory == null) return false; // m_aCryptoFactory may be null if (m_aPMode == null) return false; if (m_aSenderID == null) return false; if (m_aReceiverID == null) return false; if (m_aDocTypeID == null) return false; if (m_aProcessID == null) return false; // m_sServiceType may be null // m_sService may be null // m_sAction may be null if (m_aFromPartyID == null) return false; // m_sFromRole may be null if (m_aToPartyID == null) return false; // m_sToRole may be null // m_sMessageID is optional // m_sConversationID is optional if (m_aEndpointDetailProvider == null) return false; // m_aBuildMessageCallback may be null // m_aOutgoingDumper may be null // m_aIncomingDumper may be null // m_aResponseConsumer may be null // m_aSignalMsgConsumer may be null return true; } /** * Synchronously send the AS4 message. Before sending, * {@link #isEveryRequiredFieldSet()} is called to check that the mandatory * elements are set. * * @return {@link ESuccess#FAILURE} if not all mandatory parameters are set * or if sending failed, {@link ESuccess#SUCCESS} upon success. * Never null. * @throws Phase4CEFException * In case of any error * @see #isEveryRequiredFieldSet() */ @Nonnull public abstract ESuccess sendMessage () throws Phase4CEFException; } /** * The builder class for sending AS4 messages using CEF profile specifics. Use * {@link #sendMessage()} to trigger the main transmission.
* This builder class assumes, that only the payload (e.g. the Invoice) is * present, and that both validation and SBDH creation happens inside. * * @author Philip Helger */ public static class Builder extends AbstractBaseBuilder { private Phase4OutgoingAttachment m_aPayload; private final ICommonsList m_aAttachments = new CommonsArrayList <> (); private Consumer m_aCertificateConsumer; private Consumer m_aAPEndointURLConsumer; /** * Create a new builder, with the following fields already set:
* {@link #setHttpClientFactory(HttpClientFactory)}
* {@link #setCryptoFactory(IAS4CryptoFactory)}
* {@link #setPModeResolver(IPModeResolver)}
* {@link #setIncomingAttachmentFactory(IIncomingAttachmentFactory)}
* {@link #setPMode(IPMode)}
*/ public Builder () {} /** * Set the payload to be send out. * * @param aBuilder * The payload builder to be used. May not be null. * @return this for chaining */ @Nonnull public Builder setPayload (@Nonnull final Phase4OutgoingAttachment.Builder aBuilder) { return setPayload (aBuilder.build ()); } /** * Set the payload to be send out. * * @param aPayload * The payload to be used. May not be null. * @return this for chaining */ @Nonnull public Builder setPayload (@Nonnull final Phase4OutgoingAttachment aPayload) { ValueEnforcer.notNull (aPayload, "Payload"); m_aPayload = aPayload; return this; } /** * Add an optional attachment * * @param a * The attachment to be added. May be null. * @return this for chaining */ @Nonnull public Builder addAttachment (@Nullable final Phase4OutgoingAttachment.Builder a) { return addAttachment (a == null ? null : a.build ()); } /** * Add an optional attachment * * @param a * The attachment to be added. May be null. * @return this for chaining */ @Nonnull public Builder addAttachment (@Nullable final Phase4OutgoingAttachment a) { if (a != null) m_aAttachments.add (a); return this; } /** * Set optional attachments. All existing attachments are overridden. * * @param a * The attachment to be set. May be null. * @return this for chaining */ @Nonnull public Builder setAttachments (@Nullable final Phase4OutgoingAttachment... a) { m_aAttachments.setAll (a); return this; } /** * Set optional attachments. All existing attachments are overridden. * * @param a * The attachment to be set. May be null. * @return this for chaining */ @Nonnull public Builder setAttachments (@Nullable final Iterable a) { m_aAttachments.setAll (a); return this; } /** * Set an optional Consumer for the retrieved certificate, independent of * its usability. * * @param aCertificateConsumer * The consumer to be used. May be null. * @return this for chaining */ @Nonnull public Builder setCertificateConsumer (@Nullable final Consumer aCertificateConsumer) { m_aCertificateConsumer = aCertificateConsumer; return this; } /** * Set an optional Consumer for the destination AP address, independent of * its usability. * * @param aAPEndointURLConsumer * The consumer to be used. May be null. * @return this for chaining */ @Nonnull public Builder setAPEndointURLConsumer (@Nullable final Consumer aAPEndointURLConsumer) { m_aAPEndointURLConsumer = aAPEndointURLConsumer; return this; } @Override public boolean isEveryRequiredFieldSet () { if (!super.isEveryRequiredFieldSet ()) return false; if (m_aPayload == null) return false; // m_aAttachments may be empty // m_aCertificateConsumer is optional // m_aAPEndointURLConsumer is optional // All valid return true; } @Override @Nonnull public ESuccess sendMessage () throws Phase4CEFException { if (!isEveryRequiredFieldSet ()) { LOGGER.error ("At least one mandatory field is not set and therefore the AS4 message cannot be send."); return ESuccess.FAILURE; } // e.g. SMP lookup (may throw an exception) m_aEndpointDetailProvider.init (m_aDocTypeID, m_aProcessID, m_aReceiverID); // Certificate from e.g. SMP lookup (may throw an exception) final X509Certificate aReceiverCert = m_aEndpointDetailProvider.getReceiverAPCertificate (); if (m_aCertificateConsumer != null) m_aCertificateConsumer.accept (aReceiverCert); // URL from e.g. SMP lookup (may throw an exception) final String sReceiverEndpointURL = m_aEndpointDetailProvider.getReceiverAPEndpointURL (); if (m_aAPEndointURLConsumer != null) m_aAPEndointURLConsumer.accept (sReceiverEndpointURL); // Temporary file manager try (final AS4ResourceHelper aResHelper = new AS4ResourceHelper ()) { // Start building AS4 User Message final AS4ClientUserMessage aUserMsg = new AS4ClientUserMessage (aResHelper); aUserMsg.setHttpClientFactory (m_aHttpClientFactory); // Otherwise Oxalis dies aUserMsg.setQuoteHttpHeaders (false); aUserMsg.setSoapVersion (ESoapVersion.SOAP_12); // Set the keystore/truststore parameters aUserMsg.setAS4CryptoFactory (m_aCryptoFactory); aUserMsg.setPMode (m_aPMode, true); // Set after PMode aUserMsg.cryptParams ().setCertificate (aReceiverCert); // Explicit parameters have precedence over PMode aUserMsg.setAgreementRefValue (m_sAgreementRef); // The eb3:AgreementRef element also includes an optional attribute // pmode // which can be used to include the PMode.ID. This attribute MUST NOT be // used as Access Points may use just one generic P-Mode for receiving // messages. aUserMsg.setPModeIDFactory (x -> null); if (StringHelper.hasText (m_sService)) { aUserMsg.setServiceType (m_sServiceType); aUserMsg.setServiceValue (m_sService); } else { // Default: Process ID aUserMsg.setServiceType (m_aProcessID.getScheme ()); aUserMsg.setServiceValue (m_aProcessID.getValue ()); } if (StringHelper.hasText (m_sAction)) { aUserMsg.setAction (m_sAction); } else { // Default: DocumentType ID aUserMsg.setAction (m_aDocTypeID.getURIEncoded ()); } if (StringHelper.hasText (m_sMessageID)) aUserMsg.setMessageID (m_sMessageID); aUserMsg.setConversationID (StringHelper.hasText (m_sConversationID) ? m_sConversationID : MessageHelperMethods.createRandomConversationID ()); aUserMsg.setFromPartyIDType (m_aFromPartyID.getScheme ()); aUserMsg.setFromPartyID (m_aFromPartyID.getValue ()); aUserMsg.setFromRole (m_sFromRole); aUserMsg.setToPartyIDType (m_aToPartyID.getScheme ()); aUserMsg.setToPartyID (m_aToPartyID.getValue ()); aUserMsg.setToRole (m_sToRole); aUserMsg.ebms3Properties () .add (MessageHelperMethods.createEbms3Property (CAS4.ORIGINAL_SENDER, m_aSenderID.getScheme (), m_aSenderID.getValue ())); aUserMsg.ebms3Properties () .add (MessageHelperMethods.createEbms3Property (CAS4.FINAL_RECIPIENT, m_aReceiverID.getScheme (), m_aReceiverID.getValue ())); // No payload - only one attachment aUserMsg.setPayload (null); // Add main attachment aUserMsg.addAttachment (WSS4JAttachment.createOutgoingFileAttachment (m_aPayload, aResHelper)); // Add other attachments for (final Phase4OutgoingAttachment aAttachment : m_aAttachments) aUserMsg.addAttachment (WSS4JAttachment.createOutgoingFileAttachment (aAttachment, aResHelper)); // Main sending AS4BidirectionalClientHelper.sendAS4AndReceiveAS4 (m_aCryptoFactory, m_aPModeResolver, m_aIAF, aUserMsg, Locale.US, sReceiverEndpointURL, m_aBuildMessageCallback, m_aOutgoingDumper, m_aIncomingDumper, m_aRetryCallback, m_aResponseConsumer, m_aSignalMsgConsumer); } catch (final Phase4CEFException ex) { // Re-throw throw ex; } catch (final Exception ex) { // wrap throw new Phase4CEFException ("Wrapped Phase4CEFException", ex); } return ESuccess.SUCCESS; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy