Search in sources :

Example 6 with Ebms3Error

use of com.helger.phase4.ebms3header.Ebms3Error in project phase4 by phax.

the class MockMessages method createErrorMessageSigned.

@Nonnull
public static Document createErrorMessageSigned(@Nonnull final ESoapVersion eSOAPVersion, @Nullable final ICommonsList<WSS4JAttachment> aAttachments, @Nonnull final AS4ResourceHelper aResMgr) throws WSSecurityException {
    final ICommonsList<Ebms3Error> aEbms3ErrorList = new CommonsArrayList<>(EEbmsError.EBMS_INVALID_HEADER.getAsEbms3Error(Locale.US, null));
    final AS4ErrorMessage aErrorMsg = AS4ErrorMessage.create(eSOAPVersion, "srcmsgid", aEbms3ErrorList).setMustUnderstand(true);
    return AS4Signer.createSignedMessage(AS4CryptoFactoryProperties.getDefaultInstance(), aErrorMsg.getAsSoapDocument(), eSOAPVersion, aErrorMsg.getMessagingID(), aAttachments, aResMgr, false, AS4SigningParams.createDefault());
}
Also used : Ebms3Error(com.helger.phase4.ebms3header.Ebms3Error) CommonsArrayList(com.helger.commons.collection.impl.CommonsArrayList) AS4ErrorMessage(com.helger.phase4.messaging.domain.AS4ErrorMessage) Nonnull(javax.annotation.Nonnull)

Example 7 with Ebms3Error

use of com.helger.phase4.ebms3header.Ebms3Error in project phase4 by phax.

the class AS4RequestHandler method handleRequest.

/**
 * This is the main handling routine when called from an abstract
 * (non-Servlet) API
 *
 * @param aServletRequestIS
 *        The input stream with the request data. May not be
 *        <code>null</code>.
 * @param aRequestHttpHeaders
 *        The HTTP headers of the request. May not be <code>null</code>.
 * @param aHttpResponse
 *        The HTTP response to be filled. May not be <code>null</code>.
 * @throws Phase4Exception
 *         in case the request is missing certain prerequisites. Since 0.9.11
 * @throws IOException
 *         In case of IO errors
 * @throws MessagingException
 *         MIME related errors
 * @throws WSSecurityException
 *         In case of WSS4J errors
 * @see #handleRequest(InputStream, HttpHeaderMap, IAS4ResponseAbstraction)
 *      for a more generic API
 */
public void handleRequest(@Nonnull @WillClose final InputStream aServletRequestIS, @Nonnull final HttpHeaderMap aRequestHttpHeaders, @Nonnull final IAS4ResponseAbstraction aHttpResponse) throws Phase4Exception, IOException, MessagingException, WSSecurityException {
    final IAS4ParsedMessageCallback aCallback = (aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments) -> {
        // SOAP document and SOAP version are determined
        // Collect all runtime errors
        final ICommonsList<Ebms3Error> aErrorMessages = new CommonsArrayList<>();
        final IAS4ResponseFactory aResponder = _handleSoapMessage(aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments, aErrorMessages);
        if (aResponder != null) {
            // Response present -> send back
            final IAS4OutgoingDumper aRealOutgoingDumper = m_aOutgoingDumper != null ? m_aOutgoingDumper : AS4DumpManager.getOutgoingDumper();
            aResponder.applyToResponse(aHttpResponse, aRealOutgoingDumper);
        } else {
            // Success, HTTP No Content
            aHttpResponse.setStatus(CHttp.HTTP_NO_CONTENT);
        }
        AS4HttpDebug.debug(() -> "RECEIVE-END with " + (aResponder != null ? "EBMS message" : "no content"));
    };
    AS4IncomingHandler.parseAS4Message(m_aIAF, m_aResHelper, m_aMessageMetadata, aServletRequestIS, aRequestHttpHeaders, aCallback, m_aIncomingDumper);
}
Also used : AS4DecompressException(com.helger.phase4.attachment.AS4DecompressException) StreamHelper(com.helger.commons.io.stream.StreamHelper) BasicHttpPoster(com.helger.phase4.http.BasicHttpPoster) EMimeContentType(com.helger.commons.mime.EMimeContentType) ESoapVersion(com.helger.phase4.soap.ESoapVersion) HttpHeaderMap(com.helger.commons.http.HttpHeaderMap) HttpXMLEntity(com.helger.phase4.http.HttpXMLEntity) LoggerFactory(org.slf4j.LoggerFactory) Ebms3PayloadInfo(com.helger.phase4.ebms3header.Ebms3PayloadInfo) MessagingException(javax.mail.MessagingException) EPModeSendReceiptReplyPattern(com.helger.phase4.model.pmode.leg.EPModeSendReceiptReplyPattern) AS4CryptParams(com.helger.phase4.crypto.AS4CryptParams) NonBlockingByteArrayOutputStream(com.helger.commons.io.stream.NonBlockingByteArrayOutputStream) EAS4MessageType(com.helger.phase4.messaging.domain.EAS4MessageType) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) Nonempty(com.helger.commons.annotation.Nonempty) Locale(java.util.Locale) Document(org.w3c.dom.Document) IAS4IncomingMessageMetadata(com.helger.phase4.messaging.IAS4IncomingMessageMetadata) IAS4RetryCallback(com.helger.phase4.client.IAS4RetryCallback) PModeLeg(com.helger.phase4.model.pmode.leg.PModeLeg) IAS4IncomingAttachmentFactory(com.helger.phase4.attachment.IAS4IncomingAttachmentFactory) IAS4OutgoingDumper(com.helger.phase4.dump.IAS4OutgoingDumper) CGlobal(com.helger.commons.CGlobal) AS4SigningParams(com.helger.phase4.crypto.AS4SigningParams) IAS4ServletMessageProcessorSPI(com.helger.phase4.servlet.spi.IAS4ServletMessageProcessorSPI) HttpEntity(org.apache.http.HttpEntity) Ebms3CollaborationInfo(com.helger.phase4.ebms3header.Ebms3CollaborationInfo) IThrowingRunnable(com.helger.commons.callback.IThrowingRunnable) IAS4ParsedMessageCallback(com.helger.phase4.servlet.AS4IncomingHandler.IAS4ParsedMessageCallback) SOAPHeaderElementProcessorRegistry(com.helger.phase4.servlet.soap.SOAPHeaderElementProcessorRegistry) ISuccessIndicator(com.helger.commons.state.ISuccessIndicator) AS4SignalMessageProcessorResult(com.helger.phase4.servlet.spi.AS4SignalMessageProcessorResult) AS4DumpManager(com.helger.phase4.dump.AS4DumpManager) HttpRetrySettings(com.helger.phase4.http.HttpRetrySettings) Ebms3Error(com.helger.phase4.ebms3header.Ebms3Error) AS4ErrorMessage(com.helger.phase4.messaging.domain.AS4ErrorMessage) ICommonsList(com.helger.commons.collection.impl.ICommonsList) Ebms3PartyInfo(com.helger.phase4.ebms3header.Ebms3PartyInfo) HttpMimeMessageEntity(com.helger.phase4.http.HttpMimeMessageEntity) CHttp(com.helger.commons.http.CHttp) PhotonWorkerPool(com.helger.photon.app.PhotonWorkerPool) Ebms3SignalMessage(com.helger.phase4.ebms3header.Ebms3SignalMessage) MessageHelperMethods(com.helger.phase4.messaging.domain.MessageHelperMethods) ResponseHandlerXml(com.helger.httpclient.response.ResponseHandlerXml) AS4Signer(com.helger.phase4.messaging.crypto.AS4Signer) AS4ServletMessageProcessorManager(com.helger.phase4.servlet.mgr.AS4ServletMessageProcessorManager) WillClose(javax.annotation.WillClose) ServletInputStream(javax.servlet.ServletInputStream) AS4MessageProcessorResult(com.helger.phase4.servlet.spi.AS4MessageProcessorResult) AS4HttpDebug(com.helger.phase4.http.AS4HttpDebug) MetaAS4Manager(com.helger.phase4.mgr.MetaAS4Manager) CompletableFuture(java.util.concurrent.CompletableFuture) IAS4CryptoFactory(com.helger.phase4.crypto.IAS4CryptoFactory) Supplier(java.util.function.Supplier) Ebms3MessageProperties(com.helger.phase4.ebms3header.Ebms3MessageProperties) AS4Encryptor(com.helger.phase4.messaging.crypto.AS4Encryptor) Charset(java.nio.charset.Charset) EAS4MessageMode(com.helger.phase4.messaging.EAS4MessageMode) Node(org.w3c.dom.Node) IAS4IncomingDumper(com.helger.phase4.dump.IAS4IncomingDumper) AS4ResourceHelper(com.helger.phase4.util.AS4ResourceHelper) Ebms3MessageInfo(com.helger.phase4.ebms3header.Ebms3MessageInfo) AS4ReceiptMessage(com.helger.phase4.messaging.domain.AS4ReceiptMessage) Nonnull(javax.annotation.Nonnull) Phase4Exception(com.helger.phase4.util.Phase4Exception) Nullable(javax.annotation.Nullable) EEbmsError(com.helger.phase4.error.EEbmsError) Ebms3Property(com.helger.phase4.ebms3header.Ebms3Property) MimeMessageCreator(com.helger.phase4.messaging.mime.MimeMessageCreator) OutputStream(java.io.OutputStream) IRequestWebScopeWithoutResponse(com.helger.web.scope.IRequestWebScopeWithoutResponse) Ebms3UserMessage(com.helger.phase4.ebms3header.Ebms3UserMessage) Logger(org.slf4j.Logger) CommonsArrayList(com.helger.commons.collection.impl.CommonsArrayList) HasInputStream(com.helger.commons.io.stream.HasInputStream) IPMode(com.helger.phase4.model.pmode.IPMode) StringHelper(com.helger.commons.string.StringHelper) IPModeResolver(com.helger.phase4.model.pmode.resolve.IPModeResolver) AS4MimeMessage(com.helger.phase4.messaging.mime.AS4MimeMessage) EMEPBinding(com.helger.phase4.model.EMEPBinding) IOException(java.io.IOException) WSS4JAttachment(com.helger.phase4.attachment.WSS4JAttachment) XMLWriter(com.helger.xml.serialize.write.XMLWriter) ValueEnforcer(com.helger.commons.ValueEnforcer) AS4UserMessage(com.helger.phase4.messaging.domain.AS4UserMessage) IHasInputStream(com.helger.commons.io.IHasInputStream) MEPHelper(com.helger.phase4.model.MEPHelper) IMimeType(com.helger.commons.mime.IMimeType) CAS4(com.helger.phase4.CAS4) AS4XMLHelper(com.helger.phase4.util.AS4XMLHelper) InputStream(java.io.InputStream) IAS4ParsedMessageCallback(com.helger.phase4.servlet.AS4IncomingHandler.IAS4ParsedMessageCallback) IAS4OutgoingDumper(com.helger.phase4.dump.IAS4OutgoingDumper) ICommonsList(com.helger.commons.collection.impl.ICommonsList)

Example 8 with Ebms3Error

use of com.helger.phase4.ebms3header.Ebms3Error in project phase4 by phax.

the class AS4RequestHandler method _invokeSPIsForIncoming.

/**
 * Invoke custom SPI message processors
 *
 * @param aHttpHeaders
 *        The received HTTP headers. Never <code>null</code>.
 * @param aEbmsUserMessage
 *        Current user message. Either this OR signal message must be
 *        non-<code>null</code>.
 * @param aEbmsSignalMessage
 *        The signal message to use. Either this OR user message must be
 *        non-<code>null</code>.
 * @param aPayloadNode
 *        Optional SOAP body payload (only if direct SOAP msg, not for MIME).
 *        May be <code>null</code>.
 * @param aDecryptedAttachments
 *        Original attachments from source message. May be <code>null</code>.
 * @param aPMode
 *        PMode to be used - may be <code>null</code> for Receipt messages.
 * @param aState
 *        The current state. Never <code>null</<code></code>.
 * @param aErrorMessagesTarget
 *        The list of error messages to be filled if something goes wrong.
 *        Never <code>null</code>.
 * @param aResponseAttachmentsTarget
 *        The list of attachments to be added to the response. Never
 *        <code>null</code>.
 * @param aSPIResult
 *        The result object to be filled. May not be <code>null</code>.
 */
private void _invokeSPIsForIncoming(@Nonnull final HttpHeaderMap aHttpHeaders, @Nullable final Ebms3UserMessage aEbmsUserMessage, @Nullable final Ebms3SignalMessage aEbmsSignalMessage, @Nullable final Node aPayloadNode, @Nullable final ICommonsList<WSS4JAttachment> aDecryptedAttachments, @Nullable final IPMode aPMode, @Nonnull final IAS4MessageState aState, @Nonnull final ICommonsList<Ebms3Error> aErrorMessagesTarget, @Nonnull final ICommonsList<WSS4JAttachment> aResponseAttachmentsTarget, @Nonnull final SPIInvocationResult aSPIResult) {
    ValueEnforcer.isTrue(aEbmsUserMessage != null || aEbmsSignalMessage != null, "User OR Signal Message must be present");
    ValueEnforcer.isFalse(aEbmsUserMessage != null && aEbmsSignalMessage != null, "Only one of User OR Signal Message may be present");
    final boolean bIsUserMessage = aEbmsUserMessage != null;
    final String sMessageID = bIsUserMessage ? aEbmsUserMessage.getMessageInfo().getMessageId() : aEbmsSignalMessage.getMessageInfo().getMessageId();
    // Get all processors
    final ICommonsList<IAS4ServletMessageProcessorSPI> aAllProcessors = m_aProcessorSupplier.get();
    if (LOGGER.isDebugEnabled())
        LOGGER.debug("Trying to invoke the following " + aAllProcessors.size() + " SPIs on message ID '" + sMessageID + "': " + aAllProcessors);
    if (aAllProcessors.isEmpty())
        LOGGER.error("No IAS4ServletMessageProcessorSPI is available to process an incoming message");
    // Invoke ALL non-null SPIs
    for (final IAS4ServletMessageProcessorSPI aProcessor : aAllProcessors) if (aProcessor != null)
        try {
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Invoking AS4 message processor " + aProcessor + " for incoming message");
            // Main processing
            final AS4MessageProcessorResult aResult;
            final ICommonsList<Ebms3Error> aProcessingErrorMessages = new CommonsArrayList<>();
            if (bIsUserMessage) {
                aResult = aProcessor.processAS4UserMessage(m_aMessageMetadata, aHttpHeaders, aEbmsUserMessage, aPMode, aPayloadNode, aDecryptedAttachments, aState, aProcessingErrorMessages);
            } else {
                aResult = aProcessor.processAS4SignalMessage(m_aMessageMetadata, aHttpHeaders, aEbmsSignalMessage, aPMode, aState, aProcessingErrorMessages);
            }
            // Result returned?
            if (aResult == null)
                throw new IllegalStateException("No result object present from AS4 message processor " + aProcessor + " - this is a programming error");
            if (aProcessingErrorMessages.isNotEmpty() || aResult.isFailure()) {
                if (aProcessingErrorMessages.isNotEmpty()) {
                    if (LOGGER.isDebugEnabled())
                        LOGGER.debug("AS4 message processor " + aProcessor + " had processing errors - breaking. Details: " + aProcessingErrorMessages);
                    if (aResult.isSuccess())
                        LOGGER.warn("Processing errors are present but success was returned by a previous AS4 message processor " + aProcessor + " - considering the whole processing to be failed instead");
                    aErrorMessagesTarget.addAll(aProcessingErrorMessages);
                }
                if (aResult.isFailure() && aResult.hasErrorMessage()) {
                    aErrorMessagesTarget.add(EEbmsError.EBMS_OTHER.getAsEbms3Error(m_aLocale, sMessageID, "Invoked AS4 message processor SPI " + aProcessor + " on '" + sMessageID + "' returned a failure: " + aResult.getErrorMessage()));
                }
                // Stop processing
                return;
            }
            // SPI invocation returned success and no errors
            {
                final String sAsyncResultURL = aResult.getAsyncResponseURL();
                if (StringHelper.hasText(sAsyncResultURL)) {
                    // URL present
                    if (aSPIResult.hasAsyncResponseURL()) {
                        // A second processor returned a response URL - not allowed
                        final String sErrorMsg = "Invoked AS4 message processor SPI " + aProcessor + " on '" + sMessageID + "' failed: the previous processor already returned an async response URL; it is not possible to handle two URLs. Please check your SPI implementations.";
                        LOGGER.error(sErrorMsg);
                        aErrorMessagesTarget.add(EEbmsError.EBMS_VALUE_INCONSISTENT.getAsEbms3Error(m_aLocale, sMessageID, sErrorMsg));
                        // Stop processing
                        return;
                    }
                    aSPIResult.setAsyncResponseURL(sAsyncResultURL);
                    LOGGER.info("Using asynchronous response URL '" + sAsyncResultURL + "' for message ID '" + sMessageID + "'");
                }
            }
            if (bIsUserMessage) {
            // User message specific processing result handling
            // empty
            } else {
                // Signal message specific processing result handling
                assert aResult instanceof AS4SignalMessageProcessorResult;
                if (aEbmsSignalMessage.getReceipt() == null) {
                    final Ebms3UserMessage aPullReturnUserMsg = ((AS4SignalMessageProcessorResult) aResult).getPullReturnUserMessage();
                    if (aSPIResult.hasPullReturnUserMsg()) {
                        // to the pullrequest initiator
                        if (aPullReturnUserMsg != null) {
                            final String sErrorMsg = "Invoked AS4 message processor SPI " + aProcessor + " on '" + sMessageID + "' failed: the previous processor already returned a usermessage; it is not possible to return two usermessage. Please check your SPI implementations.";
                            LOGGER.warn(sErrorMsg);
                            aErrorMessagesTarget.add(EEbmsError.EBMS_VALUE_INCONSISTENT.getAsEbms3Error(m_aLocale, sMessageID, sErrorMsg));
                            // Stop processing
                            return;
                        }
                    } else {
                        // Initial return user msg
                        if (aPullReturnUserMsg == null) {
                            // No message contained in the MPC
                            final String sErrorMsg = "Invoked AS4 message processor SPI " + aProcessor + " on '" + sMessageID + "' returned a failure: no UserMessage contained in the MPC";
                            LOGGER.warn(sErrorMsg);
                            aErrorMessagesTarget.add(EEbmsError.EBMS_EMPTY_MESSAGE_PARTITION_CHANNEL.getAsEbms3Error(m_aLocale, sMessageID, sErrorMsg));
                            // Stop processing
                            return;
                        }
                        // We have something :)
                        aSPIResult.setPullReturnUserMsg(aPullReturnUserMsg);
                    }
                } else {
                    if (LOGGER.isDebugEnabled())
                        LOGGER.debug("The AS4 EbmsSignalMessage already has a Receipt");
                }
            }
            // Add response attachments, payloads
            aResult.addAllAttachmentsTo(aResponseAttachmentsTarget);
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Successfully invoked AS4 message processor " + aProcessor);
        } catch (final AS4DecompressException ex) {
            LOGGER.error("Failed to decompress AS4 payload", ex);
            // Hack for invalid GZip content from WSS4JAttachment.getSourceStream
            aErrorMessagesTarget.add(EEbmsError.EBMS_DECOMPRESSION_FAILURE.getAsEbms3Error(m_aLocale, sMessageID));
            return;
        } catch (final RuntimeException ex) {
            // Re-throw
            throw ex;
        } catch (final Exception ex) {
            throw new IllegalStateException("Error processing incoming AS4 message with processor " + aProcessor, ex);
        }
    // Remember success
    aSPIResult.setSuccess(true);
}
Also used : AS4DecompressException(com.helger.phase4.attachment.AS4DecompressException) IAS4ServletMessageProcessorSPI(com.helger.phase4.servlet.spi.IAS4ServletMessageProcessorSPI) Ebms3Error(com.helger.phase4.ebms3header.Ebms3Error) AS4DecompressException(com.helger.phase4.attachment.AS4DecompressException) MessagingException(javax.mail.MessagingException) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) Phase4Exception(com.helger.phase4.util.Phase4Exception) IOException(java.io.IOException) AS4MessageProcessorResult(com.helger.phase4.servlet.spi.AS4MessageProcessorResult) Ebms3UserMessage(com.helger.phase4.ebms3header.Ebms3UserMessage) AS4SignalMessageProcessorResult(com.helger.phase4.servlet.spi.AS4SignalMessageProcessorResult) CommonsArrayList(com.helger.commons.collection.impl.CommonsArrayList)

Example 9 with Ebms3Error

use of com.helger.phase4.ebms3header.Ebms3Error in project phase4 by phax.

the class AS4RequestHandler method _handleSoapMessage.

@Nullable
private IAS4ResponseFactory _handleSoapMessage(@Nonnull final HttpHeaderMap aHttpHeaders, @Nonnull final Document aSoapDocument, @Nonnull final ESoapVersion eSoapVersion, @Nonnull final ICommonsList<WSS4JAttachment> aIncomingAttachments, @Nonnull final ICommonsList<Ebms3Error> aErrorMessagesTarget) throws WSSecurityException, MessagingException, Phase4Exception {
    final SOAPHeaderElementProcessorRegistry aRegistry = SOAPHeaderElementProcessorRegistry.createDefault(m_aPModeResolver, m_aCryptoFactory, (IPMode) null);
    final IAS4MessageState aState = AS4IncomingHandler.processEbmsMessage(m_aResHelper, m_aLocale, aRegistry, aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments, m_aIncomingProfileSelector, aErrorMessagesTarget);
    final IPMode aPMode = aState.getPMode();
    final PModeLeg aEffectiveLeg = aState.getEffectivePModeLeg();
    final String sMessageID = aState.getMessageID();
    final ICommonsList<WSS4JAttachment> aDecryptedAttachments = aState.hasDecryptedAttachments() ? aState.getDecryptedAttachments() : aState.getOriginalAttachments();
    final Node aPayloadNode = aState.getSoapBodyPayloadNode();
    final Ebms3UserMessage aEbmsUserMessage = aState.getEbmsUserMessage();
    final Ebms3SignalMessage aEbmsSignalMessage = aState.getEbmsSignalMessage();
    if (aState.isSoapHeaderElementProcessingSuccessful()) {
        final String sProfileID = aState.getProfileID();
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("No checking for duplicate message with message ID '" + sMessageID + "' and profile ID '" + sProfileID + "'");
        final boolean bIsDuplicate = MetaAS4Manager.getIncomingDuplicateMgr().registerAndCheck(sMessageID, sProfileID, aPMode == null ? null : aPMode.getID()).isBreak();
        if (bIsDuplicate) {
            LOGGER.error("Not invoking SPIs, because message with Message ID '" + sMessageID + "' was already handled!");
            aErrorMessagesTarget.add(EEbmsError.EBMS_OTHER.getAsEbms3Error(m_aLocale, sMessageID, "Another message with the same Message ID '" + sMessageID + "' was already received!"));
        } else {
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Message is not a duplicate");
        }
    }
    final SPIInvocationResult aSPIResult = new SPIInvocationResult();
    // Storing for two-way response messages
    final ICommonsList<WSS4JAttachment> aResponseAttachments = new CommonsArrayList<>();
    // Invoke SPIs if
    // * No errors so far (sign, encrypt, ...)
    // * Valid PMode
    // * Exactly one UserMessage or SignalMessage
    // * No ping/test message
    // * No Duplicate message ID
    final boolean bCanInvokeSPIs = aErrorMessagesTarget.isEmpty() && !aState.isPingMessage();
    if (bCanInvokeSPIs) {
        // PMode may be null for receipts
        if (aPMode == null || aPMode.getMEPBinding().isSynchronous() || aPMode.getMEPBinding().isAsynchronousInitiator() || aState.getEffectivePModeLegNumber() != 1) {
            // Call synchronous
            // Might add to aErrorMessages
            // Might add to aResponseAttachments
            // Might add to m_aPullReturnUserMsg
            _invokeSPIsForIncoming(aHttpHeaders, aEbmsUserMessage, aEbmsSignalMessage, aPayloadNode, aDecryptedAttachments, aPMode, aState, aErrorMessagesTarget, aResponseAttachments, aSPIResult);
            if (aSPIResult.isFailure())
                LOGGER.warn("Error invoking synchronous SPIs");
            else if (LOGGER.isDebugEnabled())
                LOGGER.debug("Successfully invoked synchronous SPIs");
            if (m_aSoapProcessingFinalizedCB != null)
                m_aSoapProcessingFinalizedCB.onProcessingFinalized(true);
        } else {
            // Call asynchronous
            // Only leg1 can be async!
            final IThrowingRunnable<Exception> r = () -> {
                // Start async
                final ICommonsList<Ebms3Error> aLocalErrorMessages = new CommonsArrayList<>();
                final ICommonsList<WSS4JAttachment> aLocalResponseAttachments = new CommonsArrayList<>();
                final SPIInvocationResult aAsyncSPIResult = new SPIInvocationResult();
                _invokeSPIsForIncoming(aHttpHeaders, aEbmsUserMessage, aEbmsSignalMessage, aPayloadNode, aDecryptedAttachments, aPMode, aState, aLocalErrorMessages, aLocalResponseAttachments, aAsyncSPIResult);
                final IAS4ResponseFactory aAsyncResponseFactory;
                final String sResponseMessageID;
                if (aAsyncSPIResult.isSuccess()) {
                    // SPI processing succeeded
                    assert aLocalErrorMessages.isEmpty();
                    // The response user message has no explicit payload. All data of
                    // the response user message is in the local attachments
                    sResponseMessageID = MessageHelperMethods.createRandomMessageID();
                    final AS4UserMessage aResponseUserMsg = _createReversedUserMessage(eSoapVersion, sResponseMessageID, aEbmsUserMessage, aLocalResponseAttachments);
                    // Send UserMessage
                    final AS4SigningParams aSigningParams = new AS4SigningParams().setFromPMode(aEffectiveLeg.getSecurity());
                    // Use the original receiver ID as the alias into the keystore for
                    // encrypting the response message
                    final String sEncryptionAlias = aEbmsUserMessage.getPartyInfo().getTo().getPartyIdAtIndex(0).getValue();
                    final AS4CryptParams aCryptParams = new AS4CryptParams().setFromPMode(aEffectiveLeg.getSecurity()).setAlias(sEncryptionAlias);
                    aAsyncResponseFactory = _createResponseUserMessage(aState, aEffectiveLeg.getProtocol().getSoapVersion(), aResponseUserMsg, aResponseAttachments, aSigningParams, aCryptParams);
                } else {
                    // SPI processing failed
                    // Send ErrorMessage Undefined - see
                    // https://github.com/phax/phase4/issues/4
                    final AS4ErrorMessage aResponseErrorMsg = AS4ErrorMessage.create(eSoapVersion, aState.getMessageID(), aLocalErrorMessages);
                    sResponseMessageID = aResponseErrorMsg.getEbms3SignalMessage().getMessageInfo().getMessageId();
                    // Pass error messages to the outside
                    if (m_aErrorConsumer != null && aLocalErrorMessages.isNotEmpty())
                        m_aErrorConsumer.onAS4ErrorMessage(aState, aLocalErrorMessages, aResponseErrorMsg);
                    aAsyncResponseFactory = new AS4ResponseFactoryXML(m_aMessageMetadata, aState, sResponseMessageID, aResponseErrorMsg.getAsSoapDocument(), eSoapVersion.getMimeType());
                }
                // where to send it back (must be determined by SPI!)
                final String sAsyncResponseURL = aAsyncSPIResult.getAsyncResponseURL();
                if (StringHelper.hasNoText(sAsyncResponseURL))
                    throw new IllegalStateException("No asynchronous response URL present - please check your SPI implementation");
                if (LOGGER.isDebugEnabled())
                    LOGGER.debug("Responding asynchronous to: " + sAsyncResponseURL);
                // Ensure HttpEntity is repeatable
                HttpEntity aHttpEntity = aAsyncResponseFactory.getHttpEntityForSending(eSoapVersion.getMimeType());
                aHttpEntity = m_aResHelper.createRepeatableHttpEntity(aHttpEntity);
                // Use the prebuilt entity for dumping
                _invokeSPIsForResponse(aState, aAsyncResponseFactory, aHttpEntity, eSoapVersion.getMimeType(), sResponseMessageID);
                // invoke client with new document
                final BasicHttpPoster aSender = new BasicHttpPoster();
                final Document aAsyncResponse;
                if (true) {
                    final HttpHeaderMap aResponseHttpHeaders = null;
                    // TODO make async send parameters customizable
                    final HttpRetrySettings aRetrySettings = new HttpRetrySettings();
                    aAsyncResponse = aSender.sendGenericMessageWithRetries(sAsyncResponseURL, aResponseHttpHeaders, aHttpEntity, sMessageID, aRetrySettings, new ResponseHandlerXml(), m_aOutgoingDumper, m_aRetryCallback);
                } else {
                    aAsyncResponse = aSender.sendGenericMessage(sAsyncResponseURL, null, aHttpEntity, new ResponseHandlerXml());
                }
                AS4HttpDebug.debug(() -> "SEND-RESPONSE [async sent] received: " + XMLWriter.getNodeAsString(aAsyncResponse, AS4HttpDebug.getDebugXMLWriterSettings()));
            };
            final CompletableFuture<Void> aFuture = PhotonWorkerPool.getInstance().runThrowing(CAS4.LIB_NAME + " async processing", r);
            if (m_aSoapProcessingFinalizedCB != null) {
                // Give the outside world the possibility to get notified when the
                // processing is done
                aFuture.thenRun(() -> m_aSoapProcessingFinalizedCB.onProcessingFinalized(false));
            }
        }
    }
    // Try building error message
    final String sResponseMessageID;
    final IAS4ResponseFactory ret;
    if (!aState.isSoapHeaderElementProcessingSuccessful() || aState.getEbmsError() == null) {
        // Not an incoming Ebms Error Message
        if (aErrorMessagesTarget.isNotEmpty()) {
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Creating AS4 error message with these " + aErrorMessagesTarget.size() + " errors: " + aErrorMessagesTarget.getAllMapped(Ebms3Error::getDescriptionValue));
            final AS4ErrorMessage aResponseErrorMsg = AS4ErrorMessage.create(eSoapVersion, aState.getMessageID(), aErrorMessagesTarget);
            // Call optional consumer
            if (m_aErrorConsumer != null)
                m_aErrorConsumer.onAS4ErrorMessage(aState, aErrorMessagesTarget, aResponseErrorMsg);
            // When aLeg == null, the response is true
            if (_isSendErrorAsResponse(aEffectiveLeg)) {
                sResponseMessageID = aResponseErrorMsg.getEbms3SignalMessage().getMessageInfo().getMessageId();
                ret = new AS4ResponseFactoryXML(m_aMessageMetadata, aState, sResponseMessageID, aResponseErrorMsg.getAsSoapDocument(), eSoapVersion.getMimeType());
            } else {
                LOGGER.warn("Not sending back the error, because sending error response is prohibited in PMode");
                sResponseMessageID = null;
                ret = null;
            }
        } else {
            // Do not respond to receipt (except with error message - see above)
            if (aEbmsSignalMessage == null || aEbmsSignalMessage.getReceipt() == null) {
                // So now the incoming message is a user message or a pull request
                if (aPMode.getMEP().isOneWay() || aPMode.getMEPBinding().isAsynchronous()) {
                    // the pull phase
                    if (aPMode.getMEPBinding().equals(EMEPBinding.PULL) || (aPMode.getMEPBinding().equals(EMEPBinding.PULL_PUSH) && aSPIResult.hasPullReturnUserMsg()) || (aPMode.getMEPBinding().equals(EMEPBinding.PUSH_PULL) && aSPIResult.hasPullReturnUserMsg())) {
                        // TODO would be nice to have attachments here I guess
                        final AS4UserMessage aResponseUserMsg = new AS4UserMessage(eSoapVersion, aSPIResult.getPullReturnUserMsg());
                        sResponseMessageID = aResponseUserMsg.getEbms3UserMessage().getMessageInfo().getMessageId();
                        ret = new AS4ResponseFactoryXML(m_aMessageMetadata, aState, sResponseMessageID, aResponseUserMsg.getAsSoapDocument(), eSoapVersion.getMimeType());
                    } else if (aEbmsUserMessage != null) {
                        // We received an incoming user message and no errors occurred
                        final boolean bSendReceiptAsResponse = _isSendReceiptAsResponse(aEffectiveLeg);
                        if (bSendReceiptAsResponse) {
                            sResponseMessageID = MessageHelperMethods.createRandomMessageID();
                            ret = _createResponseReceiptMessage(aState, aSoapDocument, eSoapVersion, sResponseMessageID, aEffectiveLeg, aEbmsUserMessage, aResponseAttachments);
                        } else {
                            // TODO what shall we send back here?
                            LOGGER.info("Not sending back the Receipt response, because sending Receipt response is prohibited in PMode");
                            sResponseMessageID = null;
                            ret = null;
                        }
                    } else {
                        sResponseMessageID = null;
                        ret = null;
                    }
                } else {
                    // synchronous TWO - WAY (= "SYNC")
                    final PModeLeg aLeg2 = aPMode.getLeg2();
                    if (aLeg2 == null)
                        throw new Phase4Exception("PMode has no leg2!");
                    if (MEPHelper.isValidResponseTypeLeg2(aPMode.getMEP(), aPMode.getMEPBinding(), EAS4MessageType.USER_MESSAGE)) {
                        sResponseMessageID = MessageHelperMethods.createRandomMessageID();
                        final AS4UserMessage aResponseUserMsg = _createReversedUserMessage(eSoapVersion, sResponseMessageID, aEbmsUserMessage, aResponseAttachments);
                        final AS4SigningParams aSigningParams = new AS4SigningParams().setFromPMode(aLeg2.getSecurity());
                        final String sEncryptionAlias = aEbmsUserMessage.getPartyInfo().getTo().getPartyIdAtIndex(0).getValue();
                        final AS4CryptParams aCryptParams = new AS4CryptParams().setFromPMode(aLeg2.getSecurity()).setAlias(sEncryptionAlias);
                        ret = _createResponseUserMessage(aState, aLeg2.getProtocol().getSoapVersion(), aResponseUserMsg, aResponseAttachments, aSigningParams, aCryptParams);
                    } else {
                        sResponseMessageID = null;
                        ret = null;
                    }
                }
            } else {
                sResponseMessageID = null;
                ret = null;
            }
        }
    } else {
        sResponseMessageID = null;
        ret = null;
    }
    // Create the HttpEntity on demand
    _invokeSPIsForResponse(aState, ret, null, eSoapVersion.getMimeType(), sResponseMessageID);
    return ret;
}
Also used : Ebms3SignalMessage(com.helger.phase4.ebms3header.Ebms3SignalMessage) ICommonsList(com.helger.commons.collection.impl.ICommonsList) PModeLeg(com.helger.phase4.model.pmode.leg.PModeLeg) HttpEntity(org.apache.http.HttpEntity) SOAPHeaderElementProcessorRegistry(com.helger.phase4.servlet.soap.SOAPHeaderElementProcessorRegistry) Node(org.w3c.dom.Node) Document(org.w3c.dom.Document) HttpRetrySettings(com.helger.phase4.http.HttpRetrySettings) HttpHeaderMap(com.helger.commons.http.HttpHeaderMap) Phase4Exception(com.helger.phase4.util.Phase4Exception) AS4CryptParams(com.helger.phase4.crypto.AS4CryptParams) AS4SigningParams(com.helger.phase4.crypto.AS4SigningParams) BasicHttpPoster(com.helger.phase4.http.BasicHttpPoster) AS4UserMessage(com.helger.phase4.messaging.domain.AS4UserMessage) AS4DecompressException(com.helger.phase4.attachment.AS4DecompressException) MessagingException(javax.mail.MessagingException) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) Phase4Exception(com.helger.phase4.util.Phase4Exception) IOException(java.io.IOException) IPMode(com.helger.phase4.model.pmode.IPMode) ResponseHandlerXml(com.helger.httpclient.response.ResponseHandlerXml) Ebms3UserMessage(com.helger.phase4.ebms3header.Ebms3UserMessage) CommonsArrayList(com.helger.commons.collection.impl.CommonsArrayList) WSS4JAttachment(com.helger.phase4.attachment.WSS4JAttachment) AS4ErrorMessage(com.helger.phase4.messaging.domain.AS4ErrorMessage) Nullable(javax.annotation.Nullable)

Example 10 with Ebms3Error

use of com.helger.phase4.ebms3header.Ebms3Error in project phase4 by phax.

the class AS4IncomingHandler method _processSoapHeaderElements.

private static void _processSoapHeaderElements(@Nonnull final SOAPHeaderElementProcessorRegistry aRegistry, @Nonnull final Document aSoapDocument, @Nonnull final ICommonsList<WSS4JAttachment> aIncomingAttachments, @Nonnull final AS4MessageState aState, @Nonnull final ICommonsList<Ebms3Error> aErrorMessages) throws Phase4Exception {
    final ESoapVersion eSoapVersion = aState.getSoapVersion();
    final ICommonsList<AS4SingleSOAPHeader> aHeaders = new CommonsArrayList<>();
    {
        // Find SOAP header
        final Node aHeaderNode = XMLHelper.getFirstChildElementOfName(aSoapDocument.getDocumentElement(), eSoapVersion.getNamespaceURI(), eSoapVersion.getHeaderElementName());
        if (aHeaderNode == null)
            throw new Phase4Exception("SOAP document is missing a Header element {" + eSoapVersion.getNamespaceURI() + "}" + eSoapVersion.getHeaderElementName());
        // Extract all header elements including their "mustUnderstand" value
        for (final Element aHeaderChild : new ChildElementIterator(aHeaderNode)) {
            final QName aQName = XMLHelper.getQName(aHeaderChild);
            final String sMustUnderstand = aHeaderChild.getAttributeNS(eSoapVersion.getNamespaceURI(), "mustUnderstand");
            final boolean bIsMustUnderstand = eSoapVersion.getMustUnderstandValue(true).equals(sMustUnderstand);
            aHeaders.add(new AS4SingleSOAPHeader(aHeaderChild, aQName, bIsMustUnderstand));
        }
    }
    final ICommonsOrderedMap<QName, ISOAPHeaderElementProcessor> aAllProcessors = aRegistry.getAllElementProcessors();
    if (aAllProcessors.isEmpty())
        LOGGER.error("No SOAP Header element processor is registered");
    // handle all headers in the order of the registered handlers!
    for (final Map.Entry<QName, ISOAPHeaderElementProcessor> aEntry : aAllProcessors.entrySet()) {
        final QName aQName = aEntry.getKey();
        // Check if this message contains a header for the current handler
        final AS4SingleSOAPHeader aHeader = aHeaders.findFirst(x -> aQName.equals(x.getQName()));
        if (aHeader == null) {
            // no header element for current processor
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Message contains no SOAP header element with QName " + aQName.toString());
            continue;
        }
        final ISOAPHeaderElementProcessor aProcessor = aEntry.getValue();
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("Processing SOAP header element " + aQName.toString() + " with processor " + aProcessor);
        // Error list for this processor
        final ErrorList aErrorList = new ErrorList();
        try {
            // Process element
            if (aProcessor.processHeaderElement(aSoapDocument, aHeader.getNode(), aIncomingAttachments, aState, aErrorList).isSuccess()) {
                // Mark header as processed (for mustUnderstand check)
                aHeader.setProcessed(true);
            } else {
                // upon failure, the element stays unprocessed and sends back a signal
                // message with the errors
                LOGGER.error("Failed to process SOAP header element " + aQName.toString() + " with processor " + aProcessor + "; error details: " + aErrorList);
                final String sRefToMessageID = aState.getMessageID();
                final Locale aLocale = aState.getLocale();
                for (final IError aError : aErrorList) {
                    final EEbmsError ePredefinedError = EEbmsError.getFromErrorCodeOrNull(aError.getErrorID());
                    if (ePredefinedError != null)
                        aErrorMessages.add(ePredefinedError.getAsEbms3Error(aLocale, sRefToMessageID));
                    else {
                        final Ebms3Error aEbms3Error = new Ebms3Error();
                        aEbms3Error.setErrorDetail(aError.getErrorText(aLocale));
                        aEbms3Error.setErrorCode(aError.getErrorID());
                        aEbms3Error.setSeverity(aError.getErrorLevel().getID());
                        aEbms3Error.setOrigin(aError.getErrorFieldName());
                        aEbms3Error.setRefToMessageInError(sRefToMessageID);
                        aErrorMessages.add(aEbms3Error);
                    }
                }
                // Stop processing of other headers
                break;
            }
        } catch (final Exception ex) {
            // upon failure, the element stays unprocessed and sends back a signal
            // message with the errors
            LOGGER.error("Error processing SOAP header element " + aQName.toString() + " with processor " + aProcessor, ex);
            aErrorMessages.add(EEbmsError.EBMS_OTHER.getAsEbms3Error(aState.getLocale(), aState.getMessageID(), "Error processing SOAP header element " + aQName.toString()));
            // Stop processing of other headers
            break;
        }
    }
    // If an error message is present, send it back gracefully
    if (aErrorMessages.isEmpty()) {
        // Are all must-understand headers processed?
        for (final AS4SingleSOAPHeader aHeader : aHeaders) if (aHeader.isMustUnderstand() && !aHeader.isProcessed())
            throw new Phase4Exception("Required SOAP header element " + aHeader.getQName().toString() + " could not be handled");
    }
}
Also used : Locale(java.util.Locale) QName(javax.xml.namespace.QName) Node(org.w3c.dom.Node) Element(org.w3c.dom.Element) Ebms3Error(com.helger.phase4.ebms3header.Ebms3Error) IError(com.helger.commons.error.IError) AS4DecompressException(com.helger.phase4.attachment.AS4DecompressException) MessagingException(javax.mail.MessagingException) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) Phase4Exception(com.helger.phase4.util.Phase4Exception) IOException(java.io.IOException) AS4SingleSOAPHeader(com.helger.phase4.servlet.soap.AS4SingleSOAPHeader) Phase4Exception(com.helger.phase4.util.Phase4Exception) ErrorList(com.helger.commons.error.list.ErrorList) ESoapVersion(com.helger.phase4.soap.ESoapVersion) ChildElementIterator(com.helger.xml.ChildElementIterator) EEbmsError(com.helger.phase4.error.EEbmsError) HttpHeaderMap(com.helger.commons.http.HttpHeaderMap) Map(java.util.Map) ICommonsOrderedMap(com.helger.commons.collection.impl.ICommonsOrderedMap) CommonsArrayList(com.helger.commons.collection.impl.CommonsArrayList) ISOAPHeaderElementProcessor(com.helger.phase4.servlet.soap.ISOAPHeaderElementProcessor)

Aggregations

Nonnull (javax.annotation.Nonnull)13 Ebms3Error (com.helger.phase4.ebms3header.Ebms3Error)9 Ebms3UserMessage (com.helger.phase4.ebms3header.Ebms3UserMessage)9 CommonsArrayList (com.helger.commons.collection.impl.CommonsArrayList)8 Phase4Exception (com.helger.phase4.util.Phase4Exception)8 Node (org.w3c.dom.Node)8 WSS4JAttachment (com.helger.phase4.attachment.WSS4JAttachment)7 IOException (java.io.IOException)7 AS4DecompressException (com.helger.phase4.attachment.AS4DecompressException)6 Ebms3Property (com.helger.phase4.ebms3header.Ebms3Property)6 Ebms3SignalMessage (com.helger.phase4.ebms3header.Ebms3SignalMessage)6 IPMode (com.helger.phase4.model.pmode.IPMode)6 MessagingException (javax.mail.MessagingException)6 WSSecurityException (org.apache.wss4j.common.ext.WSSecurityException)6 HttpHeaderMap (com.helger.commons.http.HttpHeaderMap)5 Ebms3PullRequest (com.helger.phase4.ebms3header.Ebms3PullRequest)5 PModeLeg (com.helger.phase4.model.pmode.leg.PModeLeg)5 Locale (java.util.Locale)5 Document (org.w3c.dom.Document)5 ICommonsList (com.helger.commons.collection.impl.ICommonsList)4