Beispiel #1
0
        private XmlSchema GetMatchingSchema(IPipelineContext pipelineContext, Stream xmlStream)
        {
            XmlSchema     schema             = null;
            IDocumentSpec documentSpecByType = null;
            string        docType            = Utils.GetDocType(MarkableForwardOnlyEventingReadStream.EnsureMarkable(xmlStream));

            try
            {
                documentSpecByType = pipelineContext.GetDocumentSpecByType(docType);
            }
            catch (Exception)
            {
                return(null);
            }
            XmlSchemaSet schemaSet = (documentSpecByType as IDocumentSpec2).GetSchemaSet();

            if (schemaSet.Count == 0)
            {
                return(null);
            }
            foreach (XmlSchema schema2 in schemaSet.Schemas())
            {
                if (docType.Contains(schema2.TargetNamespace + "#"))
                {
                    schema = schema2;
                }
            }
            return(schema);
        }
        /// <summary>
        /// Returns the <see cref="ISchemaMetadata"/> associated to the XML schema of messages of a given <see
        /// cref="DocumentSpec"/> type.
        /// </summary>
        /// <param name="pipelineContext">
        /// The pipeline context from which the <see cref="DocumentSpec"/> can be queried.
        /// </param>
        /// <param name="docType">
        /// The <see cref="DocumentSpec"/> type of the messages for which the <see cref="ISchemaMetadata"/> are to be
        /// returned.
        /// </param>
        /// <returns>
        /// The <see cref="ISchemaMetadata"/> associated to the XML Schema.
        /// </returns>
        public static ISchemaMetadata GetSchemaMetadataByType(this IPipelineContext pipelineContext, string docType)
        {
            var docSpec    = pipelineContext.GetDocumentSpecByType(docType);
            var schemaType = Type.GetType(docSpec.DocSpecStrongName, true);

            return(schemaType.GetMetadata());
        }
Beispiel #3
0
        /// <summary>
        /// Sets the message schema strong name and message type.
        /// </summary>
        /// <param name="context">Pipeline context.</param>
        /// <param name="messageType">Message type.</param>
        /// <param name="message">Message instance.</param>
        /// <param name="docSpec">Document specification.</param>


        public static void SetDocProperties(IPipelineContext pContext, string messageType, IBaseMessage pInMsg, ref string docSpec)
        {
            try
            {
                pInMsg.Context.Promote(BtsProperties.MessageType.Name, BtsProperties.MessageType.Namespace, (object)messageType);
                IDocumentSpec documentSpecByType = pContext.GetDocumentSpecByType(messageType);
                if (documentSpecByType == null)
                {
                    return;
                }
                pInMsg.Context.Write(DasmProperties.DocumentSpecName.Name, DasmProperties.DocumentSpecName.Namespace, (object)null);
                pInMsg.Context.Write(BtsProperties.SchemaStrongName.Name, BtsProperties.SchemaStrongName.Namespace, (object)documentSpecByType.DocSpecStrongName);
                docSpec = docSpec == null ? (docSpec = documentSpecByType.DocSpecName) : docSpec;
            }
            catch (DocumentSpecException ex)
            {
                // Todo log this error
                DECore.TraceProvider.Logger.TraceInfo(ex.ToString());
            }
            catch (COMException ex)
            {
                // Todo log this errors
                DECore.TraceProvider.Logger.TraceInfo(ex.ToString());
            }
            catch (Exception ex)
            {
                DECore.TraceProvider.Logger.TraceError(ex);
                throw;
            }
        }
Beispiel #4
0
 public static bool TryGetDocumentSpecByType(this IPipelineContext pipelineContext, string docType, out IDocumentSpec documentSpec)
 {
     if (pipelineContext == null)
     {
         throw new ArgumentNullException(nameof(pipelineContext));
     }
     try
     {
         documentSpec = pipelineContext.GetDocumentSpecByType(docType);
         return(true);
     }
     catch (COMException exception)
     {
         documentSpec = null;
         if ((uint)exception.ErrorCode == (uint)HResult.ErrorSchemaNotFound)
         {
             return(false);
         }
         if (_logger.IsWarnEnabled)
         {
             _logger.Warn($"SafeGetDocumentSpecByType({docType}) has failed.", exception);
         }
         throw;
     }
 }
        public static void ProbeAndPromoteMessageType(this IBaseMessage message, IPipelineContext pipelineContext)
        {
            var messageType = message.ProbeMessageType(pipelineContext);
            var docSpec     = pipelineContext.GetDocumentSpecByType(messageType);

            message.Promote(BtsProperties.MessageType, docSpec.DocType);
            message.Promote(BtsProperties.SchemaStrongName, docSpec.DocSpecStrongName);
        }
Beispiel #6
0
        /// <summary>
        /// Returns the <see cref="ISchemaMetadata"/> associated to the XML schema of messages of a given <see
        /// cref="DocumentSpec"/> type.
        /// </summary>
        /// <param name="pipelineContext">
        /// The pipeline context from which the <see cref="DocumentSpec"/> can be queried.
        /// </param>
        /// <param name="docType">
        /// The <see cref="DocumentSpec"/> type of the messages for which the <see cref="ISchemaMetadata"/> are to be returned.
        /// </param>
        /// <returns>
        /// The <see cref="ISchemaMetadata"/> associated to the XML Schema.
        /// </returns>
        public static ISchemaMetadata GetSchemaMetadataByType(this IPipelineContext pipelineContext, string docType)
        {
            if (pipelineContext == null)
            {
                throw new ArgumentNullException(nameof(pipelineContext));
            }
            var docSpec    = pipelineContext.GetDocumentSpecByType(docType);
            var schemaType = Type.GetType(docSpec.DocSpecStrongName, true);

            return(SchemaMetadata.For(schemaType));
        }
 public static bool TryGetDocumentSpecByType(this IPipelineContext pipelineContext, string docType, out IDocumentSpec documentSpec)
 {
     try
     {
         documentSpec = pipelineContext.GetDocumentSpecByType(docType);
         return(true);
     }
     catch (COMException exception)
     {
         documentSpec = null;
         // test HResult for Finding the document specification by message type "..." failed. Verify the schema deployed properly.
         if (exception.HResult == E_SCHEMA_NOT_FOUND)
         {
             return(false);
         }
         if (_logger.IsWarnEnabled)
         {
             _logger.Warn(string.Format("SafeGetDocumentSpecByType({0}) has failed.", docType), exception);
         }
         throw;
     }
 }
Beispiel #8
0
        private string GetSourceMessageMatchingMapName(ArrayList mapList, string btsMsgType, IPipelineContext context)
        {
            string mapName = string.Empty;

            if (mapList.Count > 1)
            {
                foreach (string map in mapList)
                {
                    try
                    {
                        Type type = Type.GetType(map);
                        TransformMetaData transformMetaData    = TransformMetaData.For(type);
                        SchemaMetadata    sourceSchemaMetadata = transformMetaData.SourceSchemas[0];
                        string            mapSourceSchemaName  = sourceSchemaMetadata.SchemaName;
                        IDocumentSpec     documentSpec         = context.GetDocumentSpecByType(btsMsgType);
                        string            msgSourceSchemaName  = documentSpec.DocType;

                        Logger.WriteTrace("Map Source Schema Name: " + mapSourceSchemaName);
                        Logger.WriteTrace("Msg Source Schema Name: " + msgSourceSchemaName);

                        if (string.Compare(mapSourceSchemaName, msgSourceSchemaName, false, CultureInfo.CurrentCulture) == 0)
                        {
                            Logger.WriteTrace("Match found: " + map);
                            mapName = map;
                            break;
                        }
                    }
                    catch (Exception) { }
                }
            }
            else
            {
                mapName = mapList[0].ToString();
            }

            return(mapName);
        }
Beispiel #9
0
        /// <summary>
        /// Executes the logic for this component.
        /// </summary>
        /// <param name="pContext">Pipeline context</param>
        /// <param name="pInMsg">Input message</param>
        /// <returns>Outgoing message</returns>
        private IBaseMessage ExecuteInternal(IPipelineContext pContext, IBaseMessage pInMsg)
        {
            // Check arguments
            if (null == pContext)
            {
                throw new ArgumentNullException("pContext");
            }

            if (null == pInMsg)
            {
                throw new ArgumentNullException("pInMsg");
            }

            if (null == pInMsg.BodyPart)
            {
                throw new ArgumentNullException("pInMsg.BodyPart");
            }

            if (null == pInMsg.BodyPart.GetOriginalDataStream())
            {
                throw new ArgumentNullException("pInMsg.BodyPart.GetOriginalDataStream()");
            }

            //
            // The logic behind this component is as follows:
            // 1. Create a seekable read-only stream over the input message body part stream
            //    (because input message can be both large and stream can be non-seekable,
            //     so it should have small memory footprint and change stream positions).
            // 2. Create a new outgoing message, new body part for it, assign seekable read-only stream
            //    to the new body part, clone body part properties, clone message context.
            // 3. Get a schema for the input message or based on schemas specified during
            //    design time.
            // 4. Load stream into XmlDocument.
            // 5. Walk through promoted properties and distinguished fields and promote/write
            //    them to the message context of the outgoing message.
            // 6. Return outgoing message.
            //

            //
            // 1. Create a seekable read-only stream over the input message body part stream.
            //

            // Create a virtual stream, using GetOriginalDataStream() method on the IBaseMessagePart because
            // this call doesn't clone stream (instead of IBaseMessagePart.Data property).
            SeekableReadOnlyStream stream = new SeekableReadOnlyStream(pInMsg.BodyPart.GetOriginalDataStream());

            //
            // 2. Create a new outgoing message, copy all required stuff.
            //

            // Create a new output message
            IBaseMessage outMessage = pContext.GetMessageFactory().CreateMessage();

            // Copy message context by reference
            outMessage.Context = pInMsg.Context;

            // Create new message body part
            IBaseMessagePart newBodyPart = pContext.GetMessageFactory().CreateMessagePart();

            // Copy body part properties by references.
            newBodyPart.PartProperties = pInMsg.BodyPart.PartProperties;

            // Set virtual stream as a data stream for the new message body part
            newBodyPart.Data = stream;

            // Copy message parts
            CopyMessageParts(pInMsg, outMessage, newBodyPart);

            //
            // 3. Get a schema for the message.
            //

            // Initialize schema map
            SchemaMap schemaMap = new SchemaMap(this.documentSchemaList);

            // Get message type from the message data stream
            string messageType = GetMessageType(stream);

            // Get a document spec from based on the message type
            IDocumentSpec documentSpec = schemaMap[messageType];

            if (null == documentSpec)
            {
                documentSpec = pContext.GetDocumentSpecByType(messageType);
            }

            // Promote BTS.MessageType message context property to allow orchestration schedule instances be activated
            // on produced message.
            outMessage.Context.Promote(messageTypeWrapper.Name.Name, messageTypeWrapper.Name.Namespace, messageType);

            //
            // 4. Load document stream into XmlDocument.
            //

            // Save new message stream's current position
            long position = stream.Position;

            // Load document into XmlDocument
            XmlDocument document = new XmlDocument();

            document.Load(stream);

            // Restore the 0 position for the virtual stream
            Debug.Assert(stream.CanSeek);

            // Restore new message stream's current position
            stream.Position = position;

            //
            // 5. Walk through promoted properties/distinguished fields and promote/write them.
            //

            // Walk through and promote properties
            IEnumerator annotations = documentSpec.GetPropertyAnnotationEnumerator();

            while (annotations.MoveNext())
            {
                IPropertyAnnotation annotation   = (IPropertyAnnotation)annotations.Current;
                XmlNode             propertyNode = document.SelectSingleNode(annotation.XPath);
                if (propertyNode != null)
                {
                    // Promote context property to the message context as a typed value
                    outMessage.Context.Promote(annotation.Name, annotation.Namespace, promotingMap.MapValue(propertyNode.InnerText, annotation.XSDType));
                }
            }

            // Walk through and write distinguished fields
            IDictionaryEnumerator distFields = documentSpec.GetDistinguishedPropertyAnnotationEnumerator();

            // IDocumentSpec.GetDistinguishedPropertyAnnotationEnumerator() can return null
            if (distFields != null)
            {
                while (distFields.MoveNext())
                {
                    DistinguishedFieldDefinition distField = (DistinguishedFieldDefinition)distFields.Value;
                    XmlNode distFieldNode = document.SelectSingleNode(distField.XPath);
                    if (distFieldNode != null)
                    {
                        // Write distinguished field to the message context as a string value
                        outMessage.Context.Write(distField.XPath, Globals.DistinguishedFieldsNamespace, distFieldNode.InnerText);
                    }
                }
            }

            //
            // 6. Return outgoing message.
            //

            return(outMessage);
        }
Beispiel #10
0
        /// <summary>
        /// processes the inbound message part
        /// </summary>
        /// <param name="pc"></param>
        /// <param name="inmsg"></param>
        /// <param name="outmsg"></param>
        /// <param name="part"></param>
        private void ProcessPart(IPipelineContext pc, IBaseMessage inmsg, IBaseMessage outmsg, IBaseMessagePart part)
        {
            IDocumentSpec docSpec = null;

            Stream dataStream = part.GetOriginalDataStream();
            MarkableForwardOnlyEventingReadStream eventingDataStream = new MarkableForwardOnlyEventingReadStream(dataStream);

            XmlSchemaCollection schemaCollection = new XmlSchemaCollection(new NameTable());

            schemaCollection.ValidationEventHandler += new ValidationEventHandler(this.ValidationCallBack);

            // retrieve the assigned document schemas to validate against
            SchemaList docSchemas = this.DocumentSchemas;

            // retrieve the namespace this document adheres to
            string contextProperty = (string)outmsg.Context.Read(XmlCompleteValidator._documentSpecNameProperty.Name.Name, XmlCompleteValidator._documentSpecNameProperty.Name.Namespace);

            // if the inbound message has a namespace,
            if (contextProperty != null && contextProperty.Length > 0)
            {
                // clear the original schemas to validate against
                docSchemas.Clear();

                string[] contextSchemas = contextProperty.Split(new char[] { '|' });

                // set it's schemas
                foreach (string schemaName in contextSchemas)
                {
                    docSchemas.Add(new Schema(schemaName));
                }
            }

            #region retrieve validation schemas, shamelessly copied from the original XmlValidator pipeline component
            bool validateSchemas = this.DocumentSchemas != null && this.DocumentSchemas.Count > 0;
            if (validateSchemas && this.DocumentSchemas.Count == 1 && this.DocumentSchemas[0].SchemaName.Length == 0)
            {
                validateSchemas = false;
            }

            if (validateSchemas)
            {
                foreach (Schema s in docSchemas)
                {
                    try
                    {
                        docSpec = pc.GetDocumentSpecByName(s.SchemaName);
                    }
                    catch (COMException e)
                    {
                        throw new XmlCompleteValidatorException(
                                  ExceptionType.CANNOT_GET_DOCSPEC_BY_NAME,
                                  e.ErrorCode.ToString("X") + ": " + e.Message,
                                  new string[] { s.SchemaName });
                    }

                    if (docSpec == null)
                    {
                        throw new XmlCompleteValidatorException(
                                  ExceptionType.CANNOT_GET_DOCSPEC_BY_NAME,
                                  string.Empty,
                                  new string[] { s.SchemaName });
                    }

                    XmlSchemaCollection coll = docSpec.GetSchemaCollection();

                    schemaCollection.Add(coll);
                }
            }
            else
            {
                try
                {
                    docSpec = pc.GetDocumentSpecByType(Utils.GetDocType(eventingDataStream));
                }
                catch (COMException e)
                {
                    throw new XmlCompleteValidatorException(
                              ExceptionType.CANNOT_GET_DOCSPEC_BY_TYPE,
                              e.ErrorCode.ToString("X") + ": " + e.Message,
                              new string[] { Utils.GetDocType(eventingDataStream) });
                }

                if (docSpec == null)
                {
                    throw new XmlCompleteValidatorException(
                              ExceptionType.CANNOT_GET_DOCSPEC_BY_TYPE,
                              string.Empty,
                              new string[] { Utils.GetDocType(eventingDataStream) });
                }

                schemaCollection = docSpec.GetSchemaCollection();
            }
            #endregion

            // the most critical line within this component, assign an
            // XmlEventingValidationStream to ensure the inbound messagestream is validated
            // and events can be assigned which allow us to capture any erros that might occur
            XmlEventingValidationStream validatingStream = new XmlEventingValidationStream(eventingDataStream);

            // add the schemas we'd like to validate the inbound message against
            validatingStream.Schemas.Add(schemaCollection);

            // assign a validation event which will accumulate any errors within the inbound message
            validatingStream.ValidatingReader.ValidationEventHandler += new ValidationEventHandler(XmlMessageValidationCallBack);

            // and assign the AfterLastReadEvent, which fires upon reading the last piece of information
            // from the inbound message stream and pushes all accumulated error information out into
            // the eventviewer and onto the HAT context by throwing an exception which contains the errors
            validatingStream.AfterLastReadEvent += new AfterLastReadEventHandler(validatingStream_AfterLastReadEvent);

            // duplicate the inbound message part by creating a new one and copying it's properties
            IBaseMessageFactory messageFactory = pc.GetMessageFactory();
            IBaseMessagePart    messagePart    = messageFactory.CreateMessagePart();

            // if the inbound message exists and has a body part, copy the part properties
            // into the outbound messagepart
            if (inmsg != null && inmsg.BodyPart != null)
            {
                messagePart.PartProperties = PipelineUtil.CopyPropertyBag(inmsg.BodyPart.PartProperties, messageFactory);
            }

            // set the outbound charset
            messagePart.Charset = "UTF-8";

            // set the outbound content type
            messagePart.ContentType = "text/xml";

            // and assign the outbound datastream
            messagePart.Data = validatingStream;

            // finally, copy existing message parts
            CopyMessageParts(pc, inmsg, outmsg, messagePart, false);
        }
Beispiel #11
0
        public bool Probe(IPipelineContext pContext, IBaseMessage pInMsg)
        {
            // Check arguments
            if (null == pContext)
            {
                throw new ArgumentNullException("pContext");
            }

            if (null == pInMsg)
            {
                throw new ArgumentNullException("pInMsg");
            }

            // We need to determine a document schema to use based on message content. For the sake of simplicity of this
            // sample, we will check the first two characters in input stream and map them to some schema message types we
            // have predefined. The more sofisticated component could use UI configuration options to map identification
            // text located at specified offsets in message stream and having specified length, which could map to specified
            // message type or document spec type name.

            // Check whether input message doesn't have a body part or it is set to null, fail probe in those cases
            if (null == pInMsg.BodyPart || null == pInMsg.BodyPart.GetOriginalDataStream())
            {
                return(false);
            }

            SeekableReadOnlyStream stream = new SeekableReadOnlyStream(pInMsg.BodyPart.GetOriginalDataStream());
            Stream sourceStream           = pInMsg.BodyPart.GetOriginalDataStream();

            // Check if source stream can seek
            if (!sourceStream.CanSeek)
            {
                // Create a virtual (seekable) stream
                SeekableReadOnlyStream seekableStream = new SeekableReadOnlyStream(sourceStream);

                // Set new stream for the body part data of the input message. This new stream will then used for further processing.
                // We need to do this because input stream may not support seeking, so we wrap it with a seekable stream.
                pInMsg.BodyPart.Data = seekableStream;

                // Replace sourceStream with a new seekable stream wrapper
                sourceStream = pInMsg.BodyPart.Data;
            }

            // Preserve the stream position
            long position = sourceStream.Position;

            char [] signature = new char[2];
            try
            {
                // Read signature from a stream
                StreamReader reader = new StreamReader(sourceStream);
                if (reader.Read(signature, 0, signature.Length) < signature.Length)
                {
                    return(false);
                }

                // Don't close stream reader to avoid closing of underlying stream
            }
            finally
            {
                // Restore the stream position
                sourceStream.Position = position;
            }

            // Get message type from signature
            string messageType = GetMessageType(new string(signature));

            // Fail if message type is unknown
            if (null == messageType)
            {
                return(false);
            }

            // Get document spec from the message type
            IDocumentSpec documentSpec = pContext.GetDocumentSpecByType(messageType);

            // Instead of loading schema to get a document spec type name we could change implementation to return defined
            // during a design time document spec type name and directly specify it in the call below:

            // Write document spec type name to the message context so Flat File disassembler could access this property and
            // do message processing for a schema which has document spec type name we've discovered
            pInMsg.Context.Write(DocumentSpecNamePropertyName, XmlNormNamespaceURI, documentSpec.DocSpecStrongName);

            // Delegate call to Flat File disassembler
            return(disassembler.Probe(pContext, pInMsg));
        }
Beispiel #12
0
        /// <summary>
        /// Execute the Custom Logic To Do the Schema Validation
        /// </summary>
        /// <param name="pContext">Pipeline context</param>
        /// <param name="pInMsg">Input message to the pipeline</param>
        /// <returns>Output message</returns>
        public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
        {
            _logger.Debug("PipelineComponent::XmlValidator: Executing validation pipeline component.");

            int maxErrorCount = 20;

            //Parse the maxErrorCount property value to int
            Int32.TryParse(_maxErrorCount, out maxErrorCount);

            string messageType = Convert.ToString(pInMsg.Context.Read(Constants.MessageTypePropName, Constants.SystemPropertiesNamespace));
            string messageId   = Convert.ToString(pInMsg.MessageID);
            string fileName    = Convert.ToString(pInMsg.Context.Read(Constants.ReceivedFileNamePropName, Constants.FileAdapterPropertiesNameSpace));

            fileName = PipelineHelper.GetFileNameWithoutExtension(fileName);

            XmlValidatorHelper helper = new XmlValidatorHelper(); // (maxErrorCount, fileName);

            helper.Logger = _logger;

            if (pContext == null)
            {
                throw new ArgumentNullException("Pipeline Context is null");
            }

            if (pInMsg == null)
            {
                throw new ArgumentNullException("Incoming Message in null");
            }

            //Create OutMessage

            //Invoke the XMLValidator Validate Method

            var    originalStream = pInMsg.BodyPart.GetOriginalDataStream();
            Stream seekableStream;

            if (!originalStream.CanSeek)
            {
                seekableStream       = new ReadOnlySeekableStream(originalStream);
                pInMsg.BodyPart.Data = seekableStream;
            }
            else
            {
                seekableStream = originalStream;
            }

            IDocumentSpec docSpec = null;

            try
            {
                docSpec = pContext.GetDocumentSpecByType(messageType);


                //Use a temperory Disposable Virtual Stream
                using (VirtualStream virtusalStream = new VirtualStream())
                {
                    seekableStream.CopyTo(virtusalStream);
                    virtusalStream.Position = 0;
                    helper.ValidationWrapper(docSpec, maxErrorCount, virtusalStream, messageType, messageId);
                }


                //var errorProcessStatus = null; // helper.ProcessStatus;
                ////Check if validation Helper has caught any errors
                //if (errorProcessStatus.Errors != null && errorProcessStatus.Errors.Count() > 0)
                //{

                //    return CreateOutputMessageWrapper(pContext, pInMsg, errorProcessStatus, fileName);

                //}
                //else
                //{
                //    //Need to move the wrapped seekable stream to beginning and assign to the BodyPart as incoming message is not seekable
                //    seekableStream.Seek(0, SeekOrigin.Begin);
                //    // Track the stream so that it can be disposed when the message is finially finished with
                //    pContext.ResourceTracker.AddResource(pInMsg.BodyPart.Data);
                return(pInMsg);
                //}
            }
            catch (Exception ex)
            {
                string errorMessage = string.Format("RequestId: {0} ErrorMessage: {1}", fileName, ex.Message);
                _logger.Error(errorMessage);
                return(pInMsg);
            }
        }
Beispiel #13
0
        /// <summary>
        /// Updates the BizTalk BaseMessage and Message Context with any new or modified values from the executed BRE Policies.
        /// </summary>
        /// <param name="pipelineContext">PipelineContext</param>
        /// <param name="baseMessage">BizTalk BaseMessage to update</param>
        /// <param name="allowRepromotion">Value indicating whether to allow to re-promote properties.</param>
        public void ApplyMessageContextUpdates(IPipelineContext pipelineContext, IBaseMessage baseMessage, bool allowRepromotion)
        {
            try
            {
                if (baseMessage == null || this.UpdateMessageContext == false)
                {
                    return;
                }

                foreach (var keyValuePair in this.contextProperties)
                {
                    ContextProperty prop = keyValuePair.Value;

                    // update the message context with the context properties that
                    // have been changed (dirty)
                    if (prop.Dirty == true)
                    {
                        // check to determine if we should promote
                        if (prop.Promote == true)
                        {
                            // however check to see if already promoted or not
                            bool isAlreadyPromoted = false;
                            var  ovalue            = baseMessage.Context.Read(prop.Name, prop.Namespace);
                            if (ovalue != null)
                            {
                                isAlreadyPromoted = baseMessage.Context.IsPromoted(prop.Name, prop.Namespace);
                            }

                            if (isAlreadyPromoted == true)
                            {
                                // we need to remove and re - promote
                                baseMessage.Context.Write(prop.Name, prop.Namespace, null);
                                baseMessage.Context.Promote(prop.Name, prop.Namespace, null);
                                baseMessage.Context.Promote(prop.Name, prop.Namespace, prop.Value);
                            }
                            else
                            {
                                // it's not already promoted and we should promote if we can,
                                // this assumes there is a valid property schema, name, and data type associated with it for promotion validation...
                                // dangerous operation which could cause cyclic loop by re-promoting a property that was slated to be demoted *wasPromote*...
                                if (allowRepromotion == true)
                                {
                                    try
                                    {
                                        baseMessage.Context.Write(prop.Name, prop.Namespace, null);
                                        baseMessage.Context.Promote(prop.Name, prop.Namespace, null);
                                        baseMessage.Context.Promote(prop.Name, prop.Namespace, prop.Value);
                                    }
                                    catch (Exception ex)
                                    {
                                        TraceProvider.Logger.TraceError("Context property: {0}#{1} caused an exception:\n{2}\nThis property was not promoted.",
                                                                        prop.Namespace, prop.Name, ex.Message);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // we don't need to promote it, only write it (Distinguished)
                            // we need to remove and re-write it
                            baseMessage.Context.Write(prop.Name, prop.Namespace, null);
                            baseMessage.Context.Write(prop.Name, prop.Namespace, prop.Value);
                        }
                    }
                }

                if (this.AutoSetDocumentSpecName == true)
                {
                    // set document spec name based on the message type
                    string messageType = baseMessage.Context.Read <string>(BtsProperties.MessageType.Name, BtsProperties.MessageType.Namespace, null);
                    if (string.IsNullOrEmpty(messageType) == false)
                    {
                        IDocumentSpec documentSpec = pipelineContext.GetDocumentSpecByType(messageType);
                        TraceProvider.Logger.TraceInfo("Using document specification: {0}", documentSpec.DocSpecName);
                        // write document spec type name to the message context so that the Flat File disassembler could access this
                        // property and do the message processing for a schema that has the document spec type name we've discovered
                        baseMessage.Context.Write(BtsProperties.DocumentSpecName.Name, BtsProperties.DocumentSpecName.Namespace, documentSpec.DocSpecStrongName);
                    }
                }

                pipelineContext.ResourceTracker.AddResource(baseMessage.Context);
            }
            catch (Exception ex)
            {
                TraceProvider.Logger.TraceError(ex);
                throw;
            }
        }