public void ThreeSteps_SecondStepThrowsException_DoesntRunThirdStep() { var stepOneCount = 0; var stepTwoCount = 0; var stepThreeCount = 0; var stepper = new Stepper(); stepper .AddFirstStep(() => { stepOneCount++; return(StepResult.Success(1)); }) .Then <int>(test => { stepTwoCount++; throw new Exception("Fake Exception!"); }) .Then(test => { stepThreeCount++; return(StepResult.Success(1)); }); stepper.RunJob(); Assert.AreEqual(1, stepOneCount); Assert.AreEqual(1, stepTwoCount); Assert.AreEqual(0, stepThreeCount); }
private static StepResult CreateSignalResult(MessagingContext context) { if (Logger.IsInfoEnabled) { string ConcatErrorDescriptions(Error e) { if (e.ErrorLines != null) { return(String.Join(", ", e.ErrorLines.Select(er => er.Detail).Choose(x => x))); } return(String.Empty); } MessageUnit primaryMessageUnit = context.AS4Message.PrimaryMessageUnit; string errorDescriptions = primaryMessageUnit is Error error ? ": " + ConcatErrorDescriptions(error) : String.Empty; Logger.Info( $"({context.Mode}) <- response with {primaryMessageUnit.GetType().Name} {primaryMessageUnit.MessageId} {errorDescriptions}"); } return(StepResult.Success(context)); }
public void ThreeSteps_SecondStepReturnsFailedStepResult_DoesntRunThirdStep() { var stepOneCount = 0; var stepTwoCount = 0; var stepThreeCount = 0; var stepper = new Stepper(); stepper .AddFirstStep(() => { stepOneCount++; return(StepResult.Success(1)); }) .Then(test => { stepTwoCount++; if (false) { return(StepResult.Success(2)); } return(StepResult.Failure()); }) .Then(test => { stepThreeCount++; return(StepResult.Success(1)); }); stepper.RunJob(); Assert.AreEqual(1, stepOneCount); Assert.AreEqual(1, stepTwoCount); Assert.AreEqual(0, stepThreeCount); }
/// <summary> /// Execute the step for a given <paramref name="messagingContext" />. /// </summary> /// <param name="messagingContext">Message used during the step execution.</param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { var pullRequest = messagingContext?.AS4Message?.FirstSignalMessage as PullRequest; if (pullRequest == null) { throw new InvalidMessageException( "The received message is not a PullRequest message, " + "therefore no UserMessage can be selected to return to the sender"); } (bool hasMatch, OutMessage match) = RetrieveUserMessageForPullRequest(pullRequest); if (hasMatch) { // Retrieve the existing MessageBody and put that stream in the MessagingContext. // The HttpReceiver processor will make sure that it gets serialized to the http response stream. Stream messageBody = await match.RetrieveMessageBody(_messageBodyStore).ConfigureAwait(false); messagingContext.ModifyContext( new ReceivedMessage(messageBody, match.ContentType), MessagingContextMode.Send); messagingContext.SendingPMode = AS4XmlSerializer.FromString <SendingProcessingMode>(match.PMode); return(StepResult.Success(messagingContext)); } AS4Message pullRequestWarning = AS4Message.Create(Error.CreatePullRequestWarning(IdentifierFactory.Instance.Create())); messagingContext.ModifyContext(pullRequestWarning); return(StepResult.Success(messagingContext).AndStopExecution()); }
private async Task <StepResult> DecryptAS4MessageAsync(MessagingContext messagingContext) { try { Logger.Trace("Start decrypting AS4Message ..."); X509Certificate2 decryptionCertificate = GetCertificate(messagingContext); messagingContext.AS4Message.Decrypt(decryptionCertificate); Logger.Info($"{messagingContext.LogTag} AS4Message is decrypted correctly"); JournalLogEntry entry = JournalLogEntry.CreateFrom( messagingContext.AS4Message, $"Decrypted using certificate {decryptionCertificate.FriendlyName}"); return(await StepResult .Success(messagingContext) .WithJournalAsync(entry)); } catch (Exception ex) when(ex is CryptoException || ex is CryptographicException) { Logger.Error(ex); messagingContext.ErrorResult = new ErrorResult( description: "Decryption of message failed", alias: ErrorAlias.FailedDecryption); Logger.Error(messagingContext.ErrorResult.Description); return(StepResult.Failed(messagingContext)); } }
/// <summary> /// Handle the given <paramref name="response" />, but delegate to the next handler if you can't. /// </summary> /// <param name="response"></param> /// <returns></returns> public async Task <StepResult> HandleResponse(IAS4Response response) { if (response.ReceivedAS4Message.IsEmpty) { if (response.StatusCode == HttpStatusCode.Accepted) { response.OriginalRequest.ModifyContext(response.ReceivedAS4Message, MessagingContextMode.Send); return(StepResult.Success(response.OriginalRequest).AndStopExecution()); } Logger.Error($"Response with HTTP status: {response.StatusCode}"); if (Logger.IsErrorEnabled) { using (var r = new StreamReader(response.ReceivedStream.UnderlyingStream)) { string content = await r.ReadToEndAsync(); if (!string.IsNullOrEmpty(content)) { Logger.Error("Response with HTTP content: " + content); } } } response.OriginalRequest.ModifyContext(response.ReceivedStream, MessagingContextMode.Send); return(StepResult.Failed(response.OriginalRequest).AndStopExecution()); } return(await _nextHandler.HandleResponse(response)); }
private static async Task <StepResult> ExecuteSteps( IEnumerable <IStep> steps, MessagingContext context) { StepResult result = StepResult.Success(context); var currentContext = context; foreach (IStep step in steps) { result = await step.ExecuteAsync(currentContext).ConfigureAwait(false); if (result.CanProceed == false || result.Succeeded == false || result.MessagingContext?.Exception != null) { return(result); } if (result.MessagingContext != null && currentContext != result.MessagingContext) { currentContext = result.MessagingContext; } } return(result); }
public void ThreeSteps_UsingLambdaFunctions_RunsEachStepOnce() { var stepOneCount = 0; var stepTwoCount = 0; var stepThreeCount = 0; var stepper = new Stepper(); stepper .AddFirstStep(() => { stepOneCount++; return(StepResult.Success("ghj")); }) .Then(test => { stepTwoCount++; return(StepResult.Success(1)); }) .Then(test => { stepThreeCount++; return(StepResult.Success(1)); }); stepper.RunJob(); Assert.AreEqual(1, stepOneCount); Assert.AreEqual(1, stepTwoCount); Assert.AreEqual(1, stepThreeCount); }
/// <summary> /// Execute the step for a given <paramref name="messagingContext"/>. /// </summary> /// <param name="messagingContext">Message used during the step execution.</param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext?.AS4Message == null) { throw new InvalidOperationException( $"{nameof(SetMessageToBeSentStep)} requires an AS4Message to mark for sending but no AS4Message is present in the MessagingContext"); } Logger.Trace($"{messagingContext.LogTag} Set the message's Operation=ToBeSent"); if (messagingContext.MessageEntityId == null) { throw new InvalidOperationException( $"{messagingContext.LogTag} MessagingContext does not contain the ID of the OutMessage that must be set to ToBeSent"); } using (DatastoreContext context = _createContext()) { var repository = new DatastoreRepository(context); var service = new OutMessageService(repository, _messageStore); service.UpdateAS4MessageToBeSent( messagingContext.MessageEntityId.Value, messagingContext.AS4Message, messagingContext.SendingPMode?.Reliability?.ReceptionAwareness); await context.SaveChangesAsync().ConfigureAwait(false); } return(StepResult.Success(messagingContext)); }
public Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { return(StepResult .Success(messagingContext) .WithJournalAsync( JournalLogEntry.CreateFrom( messagingContext.AS4Message, "Log entry 2"))); }
/// <summary> /// Sign the <see cref="AS4Message" /> /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(SignAS4MessageStep)} requires an AS4Message to sign but no AS4Message is present in the MessagingContext"); } if (messagingContext.AS4Message.IsEmpty) { Logger.Debug("No signing will be performed on the message because it's empty"); return(await StepResult.SuccessAsync(messagingContext)); } Signing signInfo = RetrieveSigningInformation( messagingContext.AS4Message, messagingContext.SendingPMode, messagingContext.ReceivingPMode); if (signInfo == null) { Logger.Trace("No signing will be performend on the message because no signing information was found in either Sending or Receiving PMode"); return(await StepResult.SuccessAsync(messagingContext)); } if (signInfo.IsEnabled == false) { Logger.Trace("No signing will be performend on the message because the PMode siging information is disabled"); return(await StepResult.SuccessAsync(messagingContext)); } Logger.Info($"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Sign AS4Message with given signing information of the PMode"); X509Certificate2 certificate = RetrieveCertificate(signInfo); var settings = new CalculateSignatureConfig( signingCertificate: certificate, referenceTokenType: signInfo.KeyReferenceMethod, signingAlgorithm: signInfo.Algorithm, hashFunction: signInfo.HashFunction); SignAS4Message(settings, messagingContext.AS4Message); JournalLogEntry logEntry = JournalLogEntry.CreateFrom( messagingContext.AS4Message, $"Signed with certificate {settings.SigningCertificate.FriendlyName} and reference {settings.ReferenceTokenType} " + $"using algorithm {settings.SigningAlgorithm} and hash {settings.HashFunction}"); return(await StepResult .Success(messagingContext) .WithJournalAsync(logEntry)); }
public void IsTrueIfStopExecutiongIsntCalled() { // Act StepResult actualStepResult = StepResult.Success(AnonymousMessage()); // Assert Assert.True(actualStepResult.CanProceed); Assert.True(actualStepResult.Succeeded); }
/// <summary> /// Start Encrypting AS4 Message /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(EncryptAS4MessageStep)} requires an AS4Message to encrypt but no AS4Message is present in the MessagingContext"); } if (messagingContext.SendingPMode == null) { throw new InvalidOperationException( $"{nameof(EncryptAS4MessageStep)} requires a SendingPMode to encrypt the AS4Message but no SendingPMode is present in the MessagingContext"); } if (messagingContext.SendingPMode.Security?.Encryption == null || messagingContext.SendingPMode.Security.Encryption.IsEnabled == false) { Logger.Trace( "No encryption of the AS4Message will happen because the " + $"SendingPMode {messagingContext.SendingPMode?.Id} Security.Encryption.IsEnabled is disabled"); return(await StepResult.SuccessAsync(messagingContext)); } Logger.Info( $"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Encrypt AS4Message with given encryption information " + $"configured in the SendingPMode: {messagingContext.SendingPMode.Id}"); KeyEncryptionConfiguration keyEncryptionConfig = RetrieveKeyEncryptionConfig(messagingContext.SendingPMode); Encryption encryptionSettings = messagingContext.SendingPMode.Security.Encryption; var dataEncryptionConfig = new DataEncryptionConfiguration( encryptionMethod: encryptionSettings.Algorithm, algorithmKeySize: encryptionSettings.AlgorithmKeySize); EncryptAS4Message( messagingContext.AS4Message, keyEncryptionConfig, dataEncryptionConfig); var journal = JournalLogEntry.CreateFrom( messagingContext.AS4Message, $"Encrypted using certificate {keyEncryptionConfig.EncryptionCertificate.FriendlyName} and " + $"key encryption method: {keyEncryptionConfig.EncryptionMethod}, key digest method: {keyEncryptionConfig.DigestMethod}, " + $"key mgf: {keyEncryptionConfig.Mgf} and Data encryption method: {dataEncryptionConfig.EncryptionMethod}, " + $" data encryption type: {dataEncryptionConfig.EncryptionType}, data transport algorithm: {dataEncryptionConfig.TransformAlgorithm}"); return(await StepResult .Success(messagingContext) .WithJournalAsync(journal)); }
/// <summary> /// Execute the step for a given <paramref name="messagingContext" />. /// </summary> /// <param name="messagingContext">Message used during the step execution.</param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext?.ErrorResult == null) { return(StepResult.Success(messagingContext)); } await InsertReferencedInException(messagingContext, CancellationToken.None).ConfigureAwait(false); return(StepResult.Success(messagingContext)); }
private static StepResult CreateEmptySoapResult(MessagingContext messagingContext) { Logger.Debug("Empty Accepted response will be send to requested party since signal will be sent async"); return(StepResult.Success( new MessagingContext( AS4Message.Create(messagingContext.SendingPMode), MessagingContextMode.Receive) { ReceivingPMode = messagingContext.ReceivingPMode })); }
public Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { return(StepResult .Success(messagingContext) .WithJournalAsync( JournalLogEntry.CreateFrom( AS4Message.Create(new Receipt( $"receipt-{Guid.NewGuid()}", messagingContext.AS4Message.PrimaryMessageUnit.MessageId)), "Log entry 1"))); }
/// <summary> /// Execute the step for a given <paramref name="messagingContext"/>. /// </summary> /// <param name="messagingContext">Message used during the step execution.</param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { var entityMessage = messagingContext?.ReceivedMessage as ReceivedEntityMessage; if (!(entityMessage?.Entity is InMessage receivedInMessage)) { throw new InvalidOperationException( "The MessagingContext must contain a ReceivedMessage that represents an InMessage." + Environment.NewLine + "Other types of ReceivedMessage models are not supported in this Step."); } // Forward message by creating an OutMessage and set operation to 'ToBeProcessed'. Logger.Info($"{messagingContext.LogTag} Create a message that will be forwarded to the next MSH"); using (Stream originalInMessage = await _messageStore.LoadMessageBodyAsync(receivedInMessage.MessageLocation)) { string outLocation = await _messageStore.SaveAS4MessageStreamAsync( _configuration.OutMessageStoreLocation, originalInMessage); originalInMessage.Position = 0; AS4Message msg = await SerializerProvider.Default .Get(receivedInMessage.ContentType) .DeserializeAsync(originalInMessage, receivedInMessage.ContentType); using (DatastoreContext dbContext = _createDataStoreContext()) { var repository = new DatastoreRepository(dbContext); // Only create an OutMessage for the primary message-unit. OutMessage outMessage = OutMessageBuilder .ForMessageUnit( msg.PrimaryMessageUnit, receivedInMessage.ContentType, messagingContext.SendingPMode) .BuildForForwarding(outLocation, receivedInMessage); Logger.Debug("Insert OutMessage {{Intermediary=true, Operation=ToBeProcesed}}"); repository.InsertOutMessage(outMessage); // Set the InMessage to Forwarded. // We do this for all InMessages that are present in this AS4 Message repository.UpdateInMessages( m => msg.MessageIds.Contains(m.EbmsMessageId), r => r.Operation = Operation.Forwarded); await dbContext.SaveChangesAsync(); } } return(StepResult.Success(messagingContext)); }
private static async Task <StepResult> TryVerifyingSignatureAsync( MessagingContext messagingContext, SigningVerification verification) { try { VerifySignatureConfig options = CreateVerifyOptionsForAS4Message(messagingContext.AS4Message, verification); Logger.Debug($"Verify signature on the AS4Message {{AllowUnknownRootCertificateAuthority={options.AllowUnknownRootCertificateAuthority}}}"); if (!messagingContext.AS4Message.VerifySignature(options)) { return(InvalidSignatureResult( "The signature is invalid", ErrorAlias.FailedAuthentication, messagingContext)); } Logger.Info($"{messagingContext.LogTag} AS4Message has a valid signature present"); JournalLogEntry entry = JournalLogEntry.CreateFrom( messagingContext.AS4Message, $"Signature verified with {(options.AllowUnknownRootCertificateAuthority ? "allowing" : "disallowing")} unknown certificate authorities"); return(await StepResult .Success(messagingContext) .WithJournalAsync(entry)); } catch (CryptographicException exception) { var description = "Signature verification failed"; if (messagingContext.AS4Message.IsEncrypted) { Logger.Error( "Signature verification failed because the received message is still encrypted. " + "Make sure that you specify <Decryption/> information in the <Security/> element of the " + "ReceivingPMode so the ebMS MessagingHeader is first decrypted before it's signature gets verified"); description = "Signature verification failed because the message is still encrypted"; } Logger.Error($"{messagingContext.LogTag} An exception occured while validating the signature: {exception.Message}"); return(InvalidSignatureResult( description, ErrorAlias.FailedAuthentication, messagingContext)); } }
/// <summary> /// Start determine the Receiving Processing Mode /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(DeterminePModesStep)} requires an AS4Message but no AS4Message is present in the MessagingContext"); } AS4Message as4Message = messagingContext.AS4Message; bool containsSignalThatNotPullRequest = as4Message.SignalMessages.Any(s => !(s is Model.Core.PullRequest)); if (containsSignalThatNotPullRequest && (as4Message.IsMultiHopMessage || messagingContext.SendingPMode == null)) { messagingContext.SendingPMode = await DetermineSendingPModeForSignalMessageAsync(as4Message); } if (messagingContext.ReceivingPMode != null) { Logger.Debug( $"Will not determine ReceivingPMode: incoming message has already a ReceivingPMode: {messagingContext.ReceivingPMode.Id} configured. " + $"{Environment.NewLine} This happens when the Receive Agent is configured as a \"Static Receive Agent\""); } else if (as4Message.HasUserMessage || as4Message.SignalMessages.Any(s => s.IsMultihopSignal)) { Logger.Trace("Incoming message hasn't yet a ReceivingPMode, will determine one"); UserMessage userMessage = GetUserMessageFromFirstMessageUnitOrRoutingInput(messagingContext.AS4Message); IEnumerable <ReceivePMode> possibilities = GetMatchingReceivingPModeForUserMessage(userMessage); if (possibilities.Any() == false) { return(NoMatchingPModeFoundFailure(messagingContext)); } if (possibilities.Count() > 1) { return(TooManyPossibilitiesFailure(messagingContext, possibilities)); } ReceivePMode pmode = possibilities.First(); Logger.Info($"Found ReceivingPMode \"{pmode.Id}\" to further process the incoming message"); messagingContext.ReceivingPMode = pmode; } return(StepResult.Success(messagingContext)); }
public async void ThenTransmitMessageSucceeds() { // Arrange MessagingContext dummyMessage = CreateDummyMessageWithAttachment(); StepResult expectedStepResult = StepResult.Success(dummyMessage); var compositeStep = new CompositeStep(CreateMockStepWith(expectedStepResult).Object); // Act StepResult actualStepResult = await compositeStep.ExecuteAsync(dummyMessage); // Assert Assert.Equal(expectedStepResult.MessagingContext, actualStepResult.MessagingContext); }
public void OneStep_UsingLambdaFunction_RunsFunctionOnce() { var runCount = 0; var stepper = new Stepper(); stepper.AddFirstStep(() => { runCount++; return(StepResult.Success(0)); }); stepper.RunJob(); Assert.AreEqual(1, runCount); }
/// <summary> /// Start updating the Data store /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> /// <exception cref="Exception">A delegate callback throws an exception.</exception> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.ReceivedMessage == null) { throw new InvalidOperationException( $"{nameof(SaveReceivedMessageStep)} requires a ReceivedMessage to store the incoming message into the datastore but no ReceivedMessage is present in the MessagingContext"); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(SaveReceivedMessageStep)} requires an AS4Message to save but no AS4Message is present in the MessagingContext"); } Logger.Trace($"{messagingContext.LogTag} Store the incoming AS4 Message to the datastore"); MessagingContext resultContext = await InsertReceivedAS4MessageAsync(messagingContext); if (resultContext != null && resultContext.Exception == null) { /* PullRequests will not be notified, so we don't need a referenced Id, * Receipts and Errors will need to have a referenced UserMessage * if we want to know the original Sending PMode required for the notification. */ MessageUnit primaryMessageUnit = resultContext.AS4Message.PrimaryMessageUnit; if ((primaryMessageUnit is Receipt || primaryMessageUnit is Error) && string.IsNullOrWhiteSpace(primaryMessageUnit.RefToMessageId)) { Logger.Warn( $"{messagingContext.LogTag} Received message is a SignalMessage without RefToMessageId. " + "No such SignalMessage are supported so the message cannot be processed any further"); return(StepResult .Success(new MessagingContext(AS4Message.Empty, messagingContext.Mode)) .AndStopExecution()); } Logger.Trace($"{messagingContext.LogTag} The AS4Message is successfully stored into the datastore"); return(StepResult.Success(resultContext)); } Logger.Error($"{messagingContext.LogTag} The AS4Message is not stored correctly into the datastore {resultContext?.Exception}"); return(StepResult.Failed(resultContext)); }
public void ThreeSteps_FirstStepCreatesString_SecondStepGetsString() { var testString = "This is a test string"; var stepper = new Stepper(); stepper.AddFirstStep(() => { var stringInFirstStep = testString; return(StepResult.Success(stringInFirstStep)); }) .Then(stringUnderTest => { Assert.AreEqual(testString, stringUnderTest); return(StepResult.Success(stringUnderTest)); }); }
public async void ThenStepStopExecutionWithMarkedStepResult() { // Arrange MessagingContext expectedMessage = CreateDummyMessageWithAttachment(); StepResult stopExecutionResult = StepResult.Success(expectedMessage).AndStopExecution(); var spyStep = new SpyStep(); var compositeStep = new CompositeStep(CreateMockStepWith(stopExecutionResult).Object, spyStep); // Act StepResult actualResult = await compositeStep.ExecuteAsync(new EmptyMessagingContext()); // Assert Assert.False(spyStep.IsCalled); Assert.Equal(expectedMessage, actualResult.MessagingContext); }
/// <summary> /// Compress the <see cref="AS4Message" /> if required /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(CompressAttachmentsStep)} requires an AS4Message to compress it attachments but no AS4Message is present in the MessagingContext"); } if (messagingContext.SendingPMode == null) { throw new InvalidOperationException( $"{nameof(CompressAttachmentsStep)} requires a Sending Processing Mode to use during the compression but no Sending Processing Mode is present in the MessagingContext"); } if (messagingContext.SendingPMode.MessagePackaging?.UseAS4Compression == false) { Logger.Trace($"No compression will happen because the SendingPMode {messagingContext.SendingPMode.Id} MessagePackaging.UseAS4Compression is disabled"); return(StepResult.Success(messagingContext)); } try { Logger.Info($"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Compress AS4Message attachments with GZip compression"); messagingContext.AS4Message.CompressAttachments(); } catch (SystemException exception) { const string description = "Attachments cannot be compressed because of an exception"; Logger.Error(description); throw new InvalidDataException(description, exception); } JournalLogEntry journal = JournalLogEntry.CreateFrom( messagingContext.AS4Message, $"Compressed {messagingContext.AS4Message.Attachments.Count()} attachments with GZip compression"); return(await StepResult .Success(messagingContext) .WithJournalAsync(journal)); }
/// <summary> /// Execute the step on a given <paramref name="messagingContext"/>. /// </summary> /// <param name="messagingContext"><see cref="MessagingContext"/> on which the step must be executed.</param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.AS4Message == null) { throw new InvalidOperationException( $"{nameof(BundleSignalMessageToPullRequestStep)} requires a AS4Message to possible bundle a " + "SignalMessage to the PullRequest but there's not a AS4Message present in the MessagingContext"); } if (messagingContext.SendingPMode == null) { throw new InvalidOperationException( $"{nameof(BundleSignalMessageToPullRequestStep)} requires a SendingPMode to select the right " + "SignalMessages for piggybacking but there's not a SendingPMode present in the MessagingContext"); } if (!(messagingContext.AS4Message.PrimaryMessageUnit is PullRequest pullRequest)) { throw new InvalidOperationException( $"{nameof(BundleSignalMessageToPullRequestStep)} requires a PullRequest as primary message unit in the " + "AS4Message but there's not a PullRequest present in the MessagingContext"); } using (DatastoreContext db = _createContext()) { var service = new PiggyBackingService(db); IEnumerable <SignalMessage> signals = await service.SelectToBePiggyBackedSignalMessagesAsync(pullRequest, messagingContext.SendingPMode, _bodyStore); foreach (SignalMessage signal in signals) { Logger.Info( $"PiggyBack the {signal.GetType().Name} \"{signal.MessageId}\" which reference " + $"UserMessage \"{signal.RefToMessageId}\" to the PullRequest"); messagingContext.AS4Message.AddMessageUnit(signal); } return(StepResult.Success(messagingContext)); } }
/// <summary> /// Handle the given <paramref name="response" />, but delegate to the next handler if you can't. /// </summary> /// <param name="response"></param> /// <returns></returns> public async Task <StepResult> HandleResponse(IAS4Response response) { if (response == null) { throw new ArgumentNullException(nameof(response)); } MessagingContext request = response.OriginalRequest; if (request?.AS4Message?.IsPullRequest == true) { bool pullRequestWasPiggyBacked = request.AS4Message.SignalMessages.Any(s => !(s is PullRequest)); if (pullRequestWasPiggyBacked) { using (DatastoreContext ctx = _createContext()) { SendResult result = response.StatusCode == HttpStatusCode.Accepted || response.StatusCode == HttpStatusCode.OK ? SendResult.Success : SendResult.RetryableFail; var service = new PiggyBackingService(ctx); service.ResetSignalMessagesToBePiggyBacked(request.AS4Message.SignalMessages, result); await ctx.SaveChangesAsync().ConfigureAwait(false); } } bool isEmptyChannelWarning = (response.ReceivedAS4Message?.FirstSignalMessage as Error)?.IsPullRequestWarning == true; if (isEmptyChannelWarning) { request.ModifyContext(response.ReceivedAS4Message, MessagingContextMode.Send); return(StepResult.Success(response.OriginalRequest).AndStopExecution()); } } return(await _nextHandler.HandleResponse(response)); }
/// <summary> /// Start zipping <see cref="Attachment"/> Models /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext?.AS4Message == null) { throw new InvalidOperationException( $"{nameof(ZipAttachmentsStep)} requires an AS4Message to zip the attachments but no AS4Message is present in the MessagingContext"); } if (messagingContext.AS4Message.Attachments.Count() > 1) { Stream zippedStream = await ZipAttachmentsInAS4MessageAsync(messagingContext.AS4Message).ConfigureAwait(false); Attachment zipAttachment = CreateZippedAttachment(zippedStream); OverwriteAttachmentEntries(messagingContext.AS4Message, zipAttachment); } LogManager.GetCurrentClassLogger().Info($"{messagingContext.LogTag} Zip the Attachments to a single file"); return(StepResult.Success(messagingContext)); }
/// <summary> /// Start sending the AS4 Messages /// to the consuming business application /// </summary> /// <param name="messagingContext"></param> /// <returns></returns> public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext) { if (messagingContext == null) { throw new ArgumentNullException(nameof(messagingContext)); } if (messagingContext.ReceivingPMode == null) { throw new InvalidOperationException( "Unable to send DeliverMessage: no ReceivingPMode is set"); } if (messagingContext.ReceivingPMode.MessageHandling?.DeliverInformation == null) { throw new InvalidOperationException( $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} does not contain any <DeliverInformation />." + "Please provide a correct <DeliverInformation /> tag to indicate where the deliver message (and its attachments) should be send to."); } if (messagingContext.ReceivingPMode.MessageHandling.DeliverInformation.DeliverMethod?.Type == null) { throw new InvalidOperationException( $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} " + "does not contain any <Type/> element indicating the uploading strategy in the MessageHandling.Deliver.DeliverMethod element. " + "Default sending strategies are: 'FILE' and 'HTTP'. See 'Deliver Uploading' for more information"); } Logger.Trace($"{messagingContext.LogTag} Start sending the DeliverMessage to the consuming business application..."); SendResult result = await SendDeliverMessageAsync( messagingContext.ReceivingPMode.MessageHandling.DeliverInformation.DeliverMethod, messagingContext.DeliverMessage); Logger.Trace($"{messagingContext.LogTag} Done sending the DeliverMesssage to the consuming business application"); await UpdateDeliverMessageAsync(messagingContext, result); return(StepResult.Success(messagingContext)); }
public void OneStep_HasBothSuccessAndFailStepResult_DoesntThrowException() { var stepper = new Stepper(); stepper.AddFirstStep(() => { if (true) { return(StepResult.Success(1)); } return(StepResult.Failure()); }) .Then(test => { Console.WriteLine(test); return(StepResult.Success()); }); var jobResult = stepper.RunJob(); Assert.AreEqual(false, jobResult.HasFailed); }