/// <summary>
        /// Downloads the exception body.
        /// </summary>
        /// <param name="direction">The direction.</param>
        /// <param name="id"></param>
        /// <returns>The exception</returns>
        /// <exception cref="ArgumentNullException">messageId - messageId parameter cannot be null</exception>
        public async Task <Stream> DownloadExceptionMessageBody(Direction direction, long id)
        {
            if (id <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(id), @"Invalid value for id");
            }
            if (!Enum.IsDefined(typeof(Direction), direction))
            {
                throw new InvalidEnumArgumentException(nameof(direction), (int)direction, typeof(Direction));
            }
            string body;

            if (direction == Direction.Inbound)
            {
                body = await context
                       .InExceptions
                       .Where(msg => msg.Id == id)
                       .Select(msg => msg.MessageLocation)
                       .FirstOrDefaultAsync();
            }
            else
            {
                body = await context
                       .OutExceptions
                       .Where(msg => msg.Id == id)
                       .Select(msg => msg.MessageLocation)
                       .FirstOrDefaultAsync();
            }

            return(await bodyStore.LoadMessageBodyAsync(body));
        }
        /// <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));
        }
Beispiel #3
0
        private async Task <Stream> TryLoadMessageBody(IAS4MessageBodyStore store)
        {
            try
            {
                return(await store.LoadMessageBodyAsync(MessageLocation));
            }
            catch (Exception exception)
            {
                LogManager.GetCurrentClassLogger().Error(exception.Message);

                return(null);
            }
        }
        /// <summary>
        /// Gets the non-intermediary stored <see cref="AS4Message"/>s matching the specified ebMS <paramref name="messageIds"/>.
        /// </summary>
        /// <param name="messageIds">The ebMS message identifiers.</param>
        /// <returns></returns>
        public async Task <IEnumerable <AS4Message> > GetNonIntermediaryAS4UserMessagesForIds(IEnumerable <string> messageIds)
        {
            if (messageIds == null)
            {
                throw new ArgumentNullException(nameof(messageIds));
            }

            if (!messageIds.Any())
            {
                Logger.Trace("Specified ebMS message identifiers is empty");
                return(Enumerable.Empty <AS4Message>());
            }

            IEnumerable <OutMessage> messages =
                _repository.GetOutMessageData(
                    m => messageIds.Contains(m.EbmsMessageId) &&
                    m.Intermediary == false,
                    m => m)
                .Where(m => m != null);

            if (!messages.Any())
            {
                return(Enumerable.Empty <AS4Message>());
            }

            var foundMessages = new Collection <AS4Message>();

            foreach (OutMessage m in messages)
            {
                Stream body = await _messageBodyStore.LoadMessageBodyAsync(m.MessageLocation);

                AS4Message foundMessage =
                    await SerializerProvider.Default
                    .Get(m.ContentType)
                    .DeserializeAsync(body, m.ContentType);

                foundMessages.Add(foundMessage);
            }

            return(foundMessages.AsEnumerable());
        }
Beispiel #5
0
        /// <summary>
        /// Selects the available <see cref="SignalMessage"/>s that are ready to be bundled (PiggyBacked) with the given <see cref="PullRequest"/>.
        /// </summary>
        /// <param name="pr">The <see cref="PullRequest"/> for which a selection of <see cref="SignalMessage"/>s are returned.</param>
        /// <param name="sendingPMode">The sending configuration used to select <see cref="SignalMessage"/>s with the same configuration.</param>
        /// <param name="bodyStore">The body store at which the <see cref="SignalMessage"/>s are persisted.</param>
        /// <returns>
        ///     An subsection of the <see cref="SignalMessage"/>s where the referenced send <see cref="UserMessage"/> matches the given <paramref name="pr"/>
        ///     and where the sending configuration given in the <paramref name="sendingPMode"/> matches the stored <see cref="SignalMessage"/> sending configuration.
        /// </returns>
        internal async Task <IEnumerable <SignalMessage> > SelectToBePiggyBackedSignalMessagesAsync(
            PullRequest pr,
            SendingProcessingMode sendingPMode,
            IAS4MessageBodyStore bodyStore)
        {
            if (pr == null)
            {
                throw new ArgumentNullException(nameof(pr));
            }

            if (sendingPMode == null)
            {
                throw new ArgumentNullException(nameof(sendingPMode));
            }

            if (bodyStore == null)
            {
                throw new ArgumentNullException(nameof(bodyStore));
            }

            string url = sendingPMode.PushConfiguration?.Protocol?.Url;

            if (String.IsNullOrWhiteSpace(url))
            {
                throw new ArgumentException(
                          @"SendingPMode.PushConfiguration.Protocol.Url cannot be blank",
                          nameof(sendingPMode.PushConfiguration.Protocol.Url));
            }

            bool pullRequestSigned = sendingPMode.Security?.Signing?.IsEnabled == true;

            return(await _context.TransactionalAsync(async db =>
            {
                IEnumerable <OutMessage> query =
                    db.NativeCommands
                    .SelectToBePiggyBackedSignalMessages(url, pr.Mpc);

                var toBePiggyBackedSignals = new Collection <MessageUnit>();
                foreach (OutMessage found in query)
                {
                    Stream body = await bodyStore.LoadMessageBodyAsync(found.MessageLocation);
                    AS4Message signal =
                        await SerializerProvider
                        .Default
                        .Get(found.ContentType)
                        .DeserializeAsync(body, found.ContentType);

                    var toBePiggyBacked = signal.SignalMessages.FirstOrDefault(s => s.MessageId == found.EbmsMessageId);
                    if (toBePiggyBacked is Receipt || toBePiggyBacked is Error)
                    {
                        if (!pullRequestSigned && signal.IsSigned)
                        {
                            Logger.Warn(
                                $"Can't PiggyBack {toBePiggyBacked.GetType().Name} {toBePiggyBacked.MessageId} because SignalMessage is signed "
                                + $"while the SendingPMode {sendingPMode.Id} used is not configured for signing");
                        }
                        else
                        {
                            found.Operation = Operation.Sending;
                            toBePiggyBackedSignals.Add(toBePiggyBacked);
                        }
                    }
                    else if (toBePiggyBacked != null)
                    {
                        Logger.Warn(
                            $"Will not select {toBePiggyBacked.GetType().Name} {toBePiggyBacked.MessageId} "
                            + "for PiggyBacking because only Receipts and Errors are allowed SignalMessages to be PiggyBacked with PullRequests");
                    }
                    else
                    {
                        Logger.Warn("Will not select AS4Message for PiggyBacking because it doesn't contains any Message Units");
                    }
                }

                if (toBePiggyBackedSignals.Any())
                {
                    await db.SaveChangesAsync()
                    .ConfigureAwait(false);
                }

                return toBePiggyBackedSignals.Cast <SignalMessage>().AsEnumerable();
            }));
        }