use of com.helger.phase4.util.Phase4Exception in project phase4 by phax.
the class AbstractAS4UserMessageBuilderMIMEPayload method mainSendMessage.
@Override
protected final void mainSendMessage() throws Phase4Exception {
// Temporary file manager
try (final AS4ResourceHelper aResHelper = new AS4ResourceHelper()) {
// Start building AS4 User Message
final AS4ClientUserMessage aUserMsg = new AS4ClientUserMessage(aResHelper);
applyToUserMessage(aUserMsg);
// 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.sendAS4UserMessageAndReceiveAS4SignalMessage(m_aCryptoFactory, pmodeResolver(), incomingAttachmentFactory(), incomingProfileSelector(), aUserMsg, m_aLocale, m_sEndpointURL, m_aBuildMessageCallback, m_aOutgoingDumper, m_aIncomingDumper, m_aRetryCallback, m_aResponseConsumer, m_aSignalMsgConsumer);
} catch (final Phase4Exception ex) {
// Re-throw
throw ex;
} catch (final Exception ex) {
// wrap
throw new Phase4Exception("Wrapped Phase4Exception", ex);
}
}
use of com.helger.phase4.util.Phase4Exception 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");
}
}
use of com.helger.phase4.util.Phase4Exception in project phase4 by phax.
the class AS4IncomingHandler method _parseMessage.
@Nullable
private static IAS4MessageState _parseMessage(@Nonnull final IAS4CryptoFactory aCryptoFactory, @Nonnull final IPModeResolver aPModeResolver, @Nonnull final IAS4IncomingAttachmentFactory aIAF, @Nonnull final IAS4IncomingProfileSelector aAS4ProfileSelector, @Nonnull @WillNotClose final AS4ResourceHelper aResHelper, @Nullable final IPMode aSendingPMode, @Nonnull final Locale aLocale, @Nonnull final IAS4IncomingMessageMetadata aMessageMetadata, @Nonnull final HttpResponse aHttpResponse, @Nonnull final byte[] aResponsePayload, @Nullable final IAS4IncomingDumper aIncomingDumper) throws Phase4Exception {
// This wrapper will take the result
final Wrapper<IAS4MessageState> aRetWrapper = new Wrapper<>();
// Handler for the parsed message
final IAS4ParsedMessageCallback aCallback = (aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments) -> {
final ICommonsList<Ebms3Error> aErrorMessages = new CommonsArrayList<>();
// Use the sending PMode as fallback, because from the incoming
// receipt/error it is impossible to detect a PMode
final SOAPHeaderElementProcessorRegistry aRegistry = SOAPHeaderElementProcessorRegistry.createDefault(aPModeResolver, aCryptoFactory, aSendingPMode);
// Parse AS4, verify signature etc
final IAS4MessageState aState = processEbmsMessage(aResHelper, aLocale, aRegistry, aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments, aAS4ProfileSelector, aErrorMessages);
if (aState.isSoapHeaderElementProcessingSuccessful()) {
// Remember the parsed signal message
aRetWrapper.set(aState);
} else {
throw new Phase4Exception("Error processing AS4 message", aState.getSoapWSS4JException());
}
};
// Create header map from response headers
final HttpHeaderMap aHttpHeaders = new HttpHeaderMap();
for (final Header aHeader : aHttpResponse.getAllHeaders()) aHttpHeaders.addHeader(aHeader.getName(), aHeader.getValue());
try (final NonBlockingByteArrayInputStream aPayloadIS = new NonBlockingByteArrayInputStream(aResponsePayload)) {
// Parse incoming message
parseAS4Message(aIAF, aResHelper, aMessageMetadata, aPayloadIS, aHttpHeaders, aCallback, aIncomingDumper);
} catch (final Phase4Exception ex) {
throw ex;
} catch (final Exception ex) {
throw new Phase4Exception("Error parsing AS4 message", ex);
}
// This one contains the result
return aRetWrapper.get();
}
use of com.helger.phase4.util.Phase4Exception in project phase4 by phax.
the class AS4IncomingHandler method parseUserMessage.
@Nullable
public static Ebms3UserMessage parseUserMessage(@Nonnull final IAS4CryptoFactory aCryptoFactory, @Nonnull final IPModeResolver aPModeResolver, @Nonnull final IAS4IncomingAttachmentFactory aIAF, @Nonnull final IAS4IncomingProfileSelector aAS4ProfileSelector, @Nonnull @WillNotClose final AS4ResourceHelper aResHelper, @Nullable final IPMode aSendingPMode, @Nonnull final Locale aLocale, @Nonnull final IAS4IncomingMessageMetadata aMessageMetadata, @Nonnull final HttpResponse aHttpResponse, @Nonnull final byte[] aResponsePayload, @Nullable final IAS4IncomingDumper aIncomingDumper) throws Phase4Exception {
final IAS4MessageState aState = _parseMessage(aCryptoFactory, aPModeResolver, aIAF, aAS4ProfileSelector, aResHelper, aSendingPMode, aLocale, aMessageMetadata, aHttpResponse, aResponsePayload, aIncomingDumper);
if (aState == null) {
// Error message was already logged
return null;
}
final Ebms3UserMessage ret = aState.getEbmsUserMessage();
if (ret == null) {
if (aState.getEbmsSignalMessage() != null)
LOGGER.warn("A Message state is present, but it contains a SignalMessage instead of a UserMessage.");
else
LOGGER.warn("A Message state is present, but it contains neither a SignalMessage nor a UserMessage.");
}
return ret;
}
use of com.helger.phase4.util.Phase4Exception in project phase4 by phax.
the class AS4IncomingHandler method processEbmsMessage.
@Nonnull
public static IAS4MessageState processEbmsMessage(@Nonnull @WillNotClose final AS4ResourceHelper aResHelper, @Nonnull final Locale aLocale, @Nonnull final SOAPHeaderElementProcessorRegistry aRegistry, @Nonnull final HttpHeaderMap aHttpHeaders, @Nonnull final Document aSoapDocument, @Nonnull final ESoapVersion eSoapVersion, @Nonnull final ICommonsList<WSS4JAttachment> aIncomingAttachments, @Nonnull final IAS4IncomingProfileSelector aAS4ProfileSelector, @Nonnull final ICommonsList<Ebms3Error> aErrorMessagesTarget) throws Phase4Exception {
ValueEnforcer.notNull(aResHelper, "ResHelper");
ValueEnforcer.notNull(aLocale, "Locale");
ValueEnforcer.notNull(aHttpHeaders, "HttpHeaders");
ValueEnforcer.notNull(aSoapDocument, "SoapDocument");
ValueEnforcer.notNull(eSoapVersion, "SoapVersion");
ValueEnforcer.notNull(aIncomingAttachments, "IncomingAttachments");
ValueEnforcer.notNull(aAS4ProfileSelector, "AS4ProfileSelector");
ValueEnforcer.notNull(aErrorMessagesTarget, "aErrorMessagesTarget");
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Received the following SOAP " + eSoapVersion.getVersion() + " document:");
LOGGER.debug(AS4XMLHelper.serializeXML(aSoapDocument));
if (aIncomingAttachments.isEmpty()) {
LOGGER.debug("Without any incoming attachments");
} else {
LOGGER.debug("Including the following " + aIncomingAttachments.size() + " attachments:");
LOGGER.debug(aIncomingAttachments.toString());
}
}
// This is where all data from the SOAP headers is stored to
final AS4MessageState aState = new AS4MessageState(eSoapVersion, aResHelper, aLocale);
// Handle all headers - modifies the state
_processSoapHeaderElements(aRegistry, aSoapDocument, aIncomingAttachments, aState, aErrorMessagesTarget);
// Remember if header processing was successful or not
final boolean bSoapHeaderElementProcessingSuccess = aErrorMessagesTarget.isEmpty();
aState.setSoapHeaderElementProcessingSuccessful(bSoapHeaderElementProcessingSuccess);
if (bSoapHeaderElementProcessingSuccess) {
// Every message can only contain 1 User message or 1 pull message
// aUserMessage can be null on incoming Pull-Message!
final Ebms3UserMessage aEbmsUserMessage = aState.getEbmsUserMessage();
final Ebms3Error aEbmsError = aState.getEbmsError();
final Ebms3PullRequest aEbmsPullRequest = aState.getEbmsPullRequest();
final Ebms3Receipt aEbmsReceipt = aState.getEbmsReceipt();
// Check payload consistency
final int nCountData = (aEbmsUserMessage != null ? 1 : 0) + (aEbmsPullRequest != null ? 1 : 0) + (aEbmsReceipt != null ? 1 : 0) + (aEbmsError != null ? 1 : 0);
if (nCountData != 1) {
LOGGER.error("Expected a UserMessage(" + (aEbmsUserMessage != null ? 1 : 0) + "), a PullRequest(" + (aEbmsPullRequest != null ? 1 : 0) + "), a Receipt(" + (aEbmsReceipt != null ? 1 : 0) + ") or an Error(" + (aEbmsError != null ? 1 : 0) + ")");
// send EBMS:0001 error back
aErrorMessagesTarget.add(EEbmsError.EBMS_VALUE_NOT_RECOGNIZED.getAsEbms3Error(aLocale, aState.getMessageID()));
}
// Determine AS4 profile ID (since 0.13.0)
final String sProfileID = aAS4ProfileSelector.getAS4ProfileID(aState);
if (LOGGER.isDebugEnabled())
LOGGER.debug("Determined AS4 profile ID '" + sProfileID + "' for current message");
aState.setProfileID(sProfileID);
final IPMode aPMode = aState.getPMode();
final PModeLeg aEffectiveLeg = aState.getEffectivePModeLeg();
if (aEbmsUserMessage != null) {
// User message requires PMode
if (aPMode == null)
throw new Phase4Exception("No AS4 P-Mode configuration found for user-message!");
// Only check leg if the message is a usermessage
if (aEffectiveLeg == null)
throw new Phase4Exception("No AS4 P-Mode leg could be determined!");
// Only do profile checks if a profile is set
if (StringHelper.hasText(sProfileID)) {
// Resolve profile ID
final IAS4Profile aProfile = MetaAS4Manager.getProfileMgr().getProfileOfID(sProfileID);
if (aProfile == null)
throw new IllegalStateException("The configured AS4 profile '" + sProfileID + "' does not exist.");
// Profile Checks gets set when started with Server
final IAS4ProfileValidator aValidator = aProfile.getValidator();
if (aValidator != null) {
if (aAS4ProfileSelector.validateAgainstProfile()) {
final ErrorList aErrorList = new ErrorList();
aValidator.validatePMode(aPMode, aErrorList);
aValidator.validateUserMessage(aEbmsUserMessage, aErrorList);
if (aErrorList.isNotEmpty()) {
throw new Phase4Exception("Error validating incoming AS4 message with the profile " + aProfile.getDisplayName() + "\n Following errors are present: " + aErrorList.getAllErrors().getAllTexts(aLocale));
}
} else {
LOGGER.warn("The AS4 profile '" + sProfileID + "' has a validation configured, but the usage was disabled using the AS4ProfileSelector");
}
}
} else {
if (LOGGER.isDebugEnabled())
LOGGER.debug("AS4 state contains no AS4 profile ID - therefore no consistency checks are performed");
}
// Ensure the decrypted attachments are used
final ICommonsList<WSS4JAttachment> aDecryptedAttachments = aState.hasDecryptedAttachments() ? aState.getDecryptedAttachments() : aState.getOriginalAttachments();
// Decompress attachments (if compressed)
// Result is directly in the decrypted attachments list!
_decompressAttachments(aDecryptedAttachments, aEbmsUserMessage, aState);
} else {
// Pull-request also requires PMode
if (aEbmsPullRequest != null && aPMode == null)
throw new Phase4Exception("No AS4 P-Mode configuration found for pull-request!");
}
final boolean bUseDecryptedSOAP = aState.hasDecryptedSoapDocument();
final Document aRealSOAPDoc = bUseDecryptedSOAP ? aState.getDecryptedSoapDocument() : aSoapDocument;
assert aRealSOAPDoc != null;
// Find SOAP body (mandatory according to SOAP XSD)
final Node aBodyNode = XMLHelper.getFirstChildElementOfName(aRealSOAPDoc.getDocumentElement(), eSoapVersion.getNamespaceURI(), eSoapVersion.getBodyElementName());
if (aBodyNode == null)
throw new Phase4Exception((bUseDecryptedSOAP ? "Decrypted" : "Original") + " SOAP document is missing a Body element");
aState.setSoapBodyPayloadNode(aBodyNode.getFirstChild());
final boolean bIsPingMessage = AS4Helper.isPingMessage(aPMode);
aState.setPingMessage(bIsPingMessage);
if (bIsPingMessage)
LOGGER.info("Received an AS4 Ping message - meaning it will NOT be handled by the custom handlers.");
}
return aState;
}
Aggregations