Skip to content

Commit

Permalink
Made pass ping message to SPI customizable; #175
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Nov 30, 2023
1 parent 7325982 commit af5fa2e
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class AS4Profile implements IAS4Profile
private final IAS4ProfilePModeProvider m_aDefaultPModeProvider;
private final IPModeIDProvider m_aPModeIDProvider;
private final boolean m_bDeprecated;
private final boolean m_bInvokeSPIForPingMessage;

/**
* Constructor
Expand All @@ -61,13 +62,16 @@ public class AS4Profile implements IAS4Profile
* @param bDeprecated
* <code>true</code> if the profile is deprecated, <code>false</code>
* if not.
* @param bInvokeSPIForPingMessage
* <code>true</code> to invoke the custom SPI handler for received
*/
public AS4Profile (@Nonnull @Nonempty final String sID,
@Nonnull @Nonempty final String sDisplayName,
@Nonnull final Supplier <? extends IAS4ProfileValidator> aProfileValidatorProvider,
@Nonnull final IAS4ProfilePModeProvider aDefaultPModeProvider,
@Nonnull final IPModeIDProvider aPModeIDProvider,
final boolean bDeprecated)
final boolean bDeprecated,
final boolean bInvokeSPIForPingMessage)
{
ValueEnforcer.notEmpty (sID, "ID");
ValueEnforcer.notEmpty (sDisplayName, "DisplayName");
Expand All @@ -81,6 +85,7 @@ public AS4Profile (@Nonnull @Nonempty final String sID,
m_aDefaultPModeProvider = aDefaultPModeProvider;
m_aPModeIDProvider = aPModeIDProvider;
m_bDeprecated = bDeprecated;
m_bInvokeSPIForPingMessage = bInvokeSPIForPingMessage;
}

@Nonnull
Expand Down Expand Up @@ -122,6 +127,11 @@ public boolean isDeprecated ()
return m_bDeprecated;
}

public boolean isInvokeSPIForPingMessage ()
{
return m_bInvokeSPIForPingMessage;
}

@Override
public boolean equals (final Object o)
{
Expand All @@ -148,6 +158,7 @@ public String toString ()
.append ("DefaultPModeProvider", m_aDefaultPModeProvider)
.append ("PModeIDProvider", m_aPModeIDProvider)
.append ("Deprecated", m_bDeprecated)
.append ("InvokeSPIForPingMessage", m_bInvokeSPIForPingMessage)
.getToString ();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,12 @@ PMode createPModeTemplate (@Nonnull @Nonempty String sInitiatorID,
* therefore not be used, or <code>false</code> if not.
*/
boolean isDeprecated ();

/**
* @return <code>true</code> if this profile wants to handle Ping messages
* inside the custom SPI handler. This was introduced for sole usage
* in BDEW profile.
* @since v2.5.3
*/
boolean isInvokeSPIForPingMessage ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ public static void parseAS4Message (@Nonnull final IAS4IncomingAttachmentFactory
final IMimeType aPlainContentType = aContentType.getCopyWithoutParameters ();

// Fallback to global dumper if none is provided
final IAS4IncomingDumper aRealIncomingDumper = aIncomingDumper != null ? aIncomingDumper : AS4DumpManager
.getIncomingDumper ();
final IAS4IncomingDumper aRealIncomingDumper = aIncomingDumper != null ? aIncomingDumper
: AS4DumpManager.getIncomingDumper ();

Document aSoapDocument = null;
ESoapVersion eSoapVersion = null;
Expand Down Expand Up @@ -468,7 +468,8 @@ private static void _processSoapHeaderElements (@Nonnull final SOAPHeaderElement
aHeader.getNode (),
aIncomingAttachments,
aState,
aErrorList).isSuccess ())
aErrorList)
.isSuccess ())
{
// Mark header as processed (for mustUnderstand check)
aHeader.setProcessed (true);
Expand Down Expand Up @@ -688,7 +689,6 @@ public static IAS4MessageState processEbmsMessage (@Nonnull @WillNotClose final
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 ();
Expand All @@ -703,6 +703,8 @@ public static IAS4MessageState processEbmsMessage (@Nonnull @WillNotClose final
if (aProfile == null)
throw new IllegalStateException ("The configured AS4 profile '" + sProfileID + "' does not exist.");

aState.setAS4Profile (aProfile);

// Profile Checks gets set when started with Server
aValidator = aProfile.getValidator ();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.helger.phase4.model.mpc.IMPC;
import com.helger.phase4.model.pmode.IPMode;
import com.helger.phase4.model.pmode.leg.PModeLeg;
import com.helger.phase4.profile.IAS4Profile;
import com.helger.phase4.soap.ESoapVersion;
import com.helger.phase4.util.AS4ResourceHelper;

Expand Down Expand Up @@ -77,7 +78,7 @@ public final class AS4MessageState extends AttributeContainerAny <String> implem
private static final String KEY_EFFECTIVE_PMODE_LEG_NUMBER = "phase4.pmode.effective.leg.number";
private static final String KEY_WSS4J_SECURITY_ACTIONS = "phase4.soap.wss4j-security-actions";
private static final String KEY_WSS4J_EXCEPTION = "phase4.soap.wss4j-exception";
private static final String KEY_PHASE4_PROFILE_ID = "phase4.profile.id";
private static final String KEY_PHASE4_PROFILE = "phase4.profile";
private static final String KEY_AS4_MESSAGE_ID = "phase4.message.id";
private static final String KEY_AS4_REF_TO_MESSAGE_ID = "phase4.ref.to.message.id";
private static final String KEY_AS4_MESSAGE_TIMESTAMP = "phase4.message.timestamp";
Expand Down Expand Up @@ -312,20 +313,20 @@ public void setSoapWSS4JException (@Nullable final Exception aException)
}

@Nullable
public String getProfileID ()
public IAS4Profile getAS4Profile ()
{
return getAsString (KEY_PHASE4_PROFILE_ID);
return getCastedValue (KEY_PHASE4_PROFILE);
}

/**
* Set the ID of the AS4 profile of the message.
* Set the AS4 profile of the message.
*
* @param sProfileID
* The internal AS4 profile ID. May be <code>null</code>.
* @param aProfile
* The internal AS4 profile. May be <code>null</code>.
*/
public void setProfileID (@Nullable final String sProfileID)
public void setAS4Profile (@Nullable final IAS4Profile aProfile)
{
putIn (KEY_PHASE4_PROFILE_ID, sProfileID);
putIn (KEY_PHASE4_PROFILE, aProfile);
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
import com.helger.phase4.model.pmode.leg.PModeLeg;
import com.helger.phase4.model.pmode.leg.PModeLegSecurity;
import com.helger.phase4.model.pmode.resolve.IPModeResolver;
import com.helger.phase4.profile.IAS4Profile;
import com.helger.phase4.servlet.AS4IncomingHandler.IAS4ParsedMessageCallback;
import com.helger.phase4.servlet.mgr.AS4ServletMessageProcessorManager;
import com.helger.phase4.servlet.soap.SOAPHeaderElementProcessorRegistry;
Expand Down Expand Up @@ -665,9 +666,8 @@ private void _invokeSPIsForIncoming (@Nonnull final HttpHeaderMap aHttpHeaders,
"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 ();
final String sMessageID = bIsUserMessage ? aEbmsUserMessage.getMessageInfo ().getMessageId ()
: aEbmsSignalMessage.getMessageInfo ().getMessageId ();

// Get all processors
final ICommonsList <IAS4ServletMessageProcessorSPI> aAllProcessors = m_aProcessorSupplier.get ();
Expand Down Expand Up @@ -876,8 +876,8 @@ private void _invokeSPIsForResponse (@Nonnull final IAS4MessageState aState,
byte [] aResponsePayload = null;
if (aResponseFactory != null)
{
final HttpEntity aRealHttpEntity = aHttpEntity != null ? aHttpEntity : aResponseFactory.getHttpEntityForSending (
aMimeType);
final HttpEntity aRealHttpEntity = aHttpEntity != null ? aHttpEntity
: aResponseFactory.getHttpEntityForSending (aMimeType);
if (aRealHttpEntity.isRepeatable ())
{
int nContentLength = (int) aRealHttpEntity.getContentLength ();
Expand Down Expand Up @@ -1374,7 +1374,28 @@ private IAS4ResponseFactory _handleSoapMessage (@Nonnull final HttpHeaderMap aHt
// * Exactly one UserMessage or SignalMessage
// * No ping/test message
// * No Duplicate message ID
final boolean bCanInvokeSPIs = aErrorMessagesTarget.isEmpty () && !aState.isPingMessage ();
boolean bCanInvokeSPIs = true;
if (aErrorMessagesTarget.isNotEmpty ())
{
// Previous processing errors
bCanInvokeSPIs = false;
}

final IAS4Profile aAS4Profile = aState.getAS4Profile ();
if (aAS4Profile == null)
{
// If no AS4 profile is present, we don't invoke SPI for ping messages
if (aState.isPingMessage ())
bCanInvokeSPIs = false;
}
else
{
// If an AS4 profile is present, we check if we need to pass through ping
// messages or not
if (aState.isPingMessage ())
bCanInvokeSPIs = aAS4Profile.isInvokeSPIForPingMessage ();
}

if (bCanInvokeSPIs)
{
// PMode may be null for receipts
Expand Down Expand Up @@ -1530,8 +1551,9 @@ private IAS4ResponseFactory _handleSoapMessage (@Nonnull final HttpHeaderMap aHt
new ResponseHandlerXml ());
}
AS4HttpDebug.debug ( () -> "SEND-RESPONSE [async sent] received: " +
(aAsyncResponse == null ? "null" : XMLWriter.getNodeAsString (aAsyncResponse,
AS4HttpDebug.getDebugXMLWriterSettings ())));
(aAsyncResponse == null ? "null"
: XMLWriter.getNodeAsString (aAsyncResponse,
AS4HttpDebug.getDebugXMLWriterSettings ())));
};

final CompletableFuture <Void> aFuture = PhotonWorkerPool.getInstance ()
Expand Down Expand Up @@ -1756,8 +1778,8 @@ public void handleRequest (@Nonnull @WillClose final InputStream aServletRequest
if (aResponder != null)
{
// Response present -> send back
final IAS4OutgoingDumper aRealOutgoingDumper = m_aOutgoingDumper != null ? m_aOutgoingDumper : AS4DumpManager
.getOutgoingDumper ();
final IAS4OutgoingDumper aRealOutgoingDumper = m_aOutgoingDumper != null ? m_aOutgoingDumper
: AS4DumpManager.getOutgoingDumper ();
aResponder.applyToResponse (aHttpResponse, aRealOutgoingDumper);
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.helger.phase4.model.mpc.IMPC;
import com.helger.phase4.model.pmode.IPMode;
import com.helger.phase4.model.pmode.leg.PModeLeg;
import com.helger.phase4.profile.IAS4Profile;
import com.helger.phase4.soap.ESoapVersion;
import com.helger.phase4.util.AS4ResourceHelper;

Expand Down Expand Up @@ -118,7 +119,8 @@ default Ebms3SignalMessage getEbmsSignalMessage ()
default Ebms3Error getEbmsError ()
{
final Ebms3SignalMessage aEbmsSignalMessage = getEbmsSignalMessage ();
return aEbmsSignalMessage != null && aEbmsSignalMessage.hasErrorEntries () ? aEbmsSignalMessage.getErrorAtIndex (0) : null;
return aEbmsSignalMessage != null && aEbmsSignalMessage.hasErrorEntries () ? aEbmsSignalMessage.getErrorAtIndex (0)
: null;
}

/**
Expand Down Expand Up @@ -402,7 +404,19 @@ default boolean hasSoapWSS4JException ()
* @since v0.9.7
*/
@Nullable
String getProfileID ();
default String getProfileID ()
{
final IAS4Profile aProfile = getAS4Profile ();
return aProfile == null ? null : aProfile.getID ();
}

/**
* @return The phase4 profile to be used. May be <code>null</code> in case it
* could not be determined.
* @since v2.5.3
*/
@Nullable
IAS4Profile getAS4Profile ();

/**
* @return The AS4 message ID. Source is the <code>MessageInfo</code> element.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ public void registerAS4Profile (@Nonnull final IAS4ProfileRegistrar aRegistrar)
BDEWCompatibilityValidator::new,
aDefaultPModeProvider,
PMODE_ID_PROVIDER,
false);
false,
true);
aRegistrar.registerProfile (aProfile);
aRegistrar.setDefaultProfile (aProfile);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public void registerAS4Profile (@Nonnull final IAS4ProfileRegistrar aRegistrar)
BPCCompatibilityValidator::new,
aDefaultPModeProvider,
PMODE_ID_PROVIDER,
false,
false);
aRegistrar.registerProfile (aProfile);
aRegistrar.setDefaultProfile (aProfile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public void registerAS4Profile (@Nonnull final IAS4ProfileRegistrar aRegistrar)
() -> new CEFCompatibilityValidator ().setExpectFourCornerModel (true),
aDefaultPModeProvider,
PMODE_ID_PROVIDER,
false,
false);
aRegistrar.registerProfile (aProfileFourCorner);

Expand All @@ -71,6 +72,7 @@ public void registerAS4Profile (@Nonnull final IAS4ProfileRegistrar aRegistrar)
() -> new CEFCompatibilityValidator ().setExpectFourCornerModel (false),
aDefaultPModeProvider,
PMODE_ID_PROVIDER,
false,
false);
aRegistrar.registerProfile (aProfileTwoCorner);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,22 @@ public final class AS4EESPAProfileRegistarSPI implements IAS4ProfileRegistrarSPI

public void registerAS4Profile (@Nonnull final IAS4ProfileRegistrar aRegistrar)
{
final IAS4ProfilePModeProvider aDefaultPModeProviderAcc = (i, r, a) -> EESPAPMode.createEESPAPMode (i,
r,
a,
PMODE_ID_PROVIDER,
true,
false);
final IAS4ProfilePModeProvider aDefaultPModeProviderProd = (i, r, a) -> EESPAPMode.createEESPAPMode (i,
r,
a,
PMODE_ID_PROVIDER,
false,
false);
final IAS4ProfilePModeProvider aDefaultPModeProviderAcc = (i,
r,
a) -> EESPAPMode.createEESPAPMode (i,
r,
a,
PMODE_ID_PROVIDER,
true,
false);
final IAS4ProfilePModeProvider aDefaultPModeProviderProd = (i,
r,
a) -> EESPAPMode.createEESPAPMode (i,
r,
a,
PMODE_ID_PROVIDER,
false,
false);

if (LOGGER.isDebugEnabled ())
LOGGER.debug ("Registering phase4 profile '" + AS4_PROFILE_ID_ACCEPTANCE + "'");
Expand All @@ -68,6 +72,7 @@ public void registerAS4Profile (@Nonnull final IAS4ProfileRegistrar aRegistrar)
EESPACompatibilityValidator::new,
aDefaultPModeProviderAcc,
PMODE_ID_PROVIDER,
false,
false);
aRegistrar.registerProfile (aProfileAcc);

Expand All @@ -78,6 +83,7 @@ public void registerAS4Profile (@Nonnull final IAS4ProfileRegistrar aRegistrar)
EESPACompatibilityValidator::new,
aDefaultPModeProviderProd,
PMODE_ID_PROVIDER,
false,
false);
aRegistrar.registerProfile (aProfileProd);

Expand Down
Loading

0 comments on commit af5fa2e

Please sign in to comment.