BizTalk Streaming Transform Pipeline Component

Simple component to run a BizTalk map in streaming fashion. The mapName pipeline property is the fully qualified map name. e.g. Microsoft.Practices.ESB.ExceptionHandling.Maps.FaultMessage_to_ExceptionSql, Microsoft.Practices.ESB.ExceptionHandling.Maps, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

StreamingTransform.cs

using System;
using System.IO;
using System.Xml;
using System.Linq;
using System.Resources;
using System.Reflection;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.ComponentModel;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;

namespace Integr8.BizTalk.PipelineComponents
{
    /// <summary>
    /// Funcitonality to remove selected nodes from XML fomatted IBaseMessage
    /// </summary>
    [ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
    [System.Runtime.InteropServices.Guid("45dc154c-6666-4152-9c16-bf8900ebb5a5")]
    [ComponentCategory(CategoryTypes.CATID_Any)]
    public class StreamingTransform : Microsoft.BizTalk.Component.Interop.IComponent, IBaseComponent, IPersistPropertyBag, IComponentUI
    {
        #region Constants

        #endregion

        #region Variables

        private bool enabled = false;
        private string mapName = string.Empty;

        #endregion

        #region Pipeline Properties

        [Description("If set to false the component will bypass processing.")]
        [DisplayName("Enabled")]
        public bool Enabled
        {
            get { return enabled; }
            set { enabled = value; }
        }

        [Description("Fully qualified name of map.")]
        [DisplayName("Map Name")]
        public string MapName
        {
            get { return mapName; }
            set { mapName = value; }
        }

        #endregion

        #region Public Methods

        public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
        {
            if (!Enabled)
                return pInMsg;

            Stream memoryStream = TransformMessage(pInMsg.BodyPart.Data);

            pInMsg.BodyPart.Data = memoryStream;
            pContext.ResourceTracker.AddResource(memoryStream);

            if (pInMsg.BodyPart.Data.Position > 0)
                pInMsg.BodyPart.Data.Seek(0, SeekOrigin.Begin);

            if (pInMsg.BodyPart.GetOriginalDataStream().Position > 0)
                pInMsg.BodyPart.GetOriginalDataStream().Seek(0, SeekOrigin.Begin);

            return pInMsg;
        }

        public void GetClassID(out Guid classID)
        {
            classID = new Guid("45dc154c-6666-4152-9c16-bf8900ebb5a5");
        }

        public void InitNew()
        {

        }

        IEnumerator IComponentUI.Validate(object projectSystem)
        {
            return new ArrayList(0).GetEnumerator();
        }

        public void Load(IPropertyBag propertyBag, int errorLog)
        {
            object val = Helper.ReadPropertyBag(propertyBag, "Enabled");

            if (val != null)
                enabled = (bool)val;

            object val1 = Helper.ReadPropertyBag(propertyBag, "MapName");

            if (val1 != null)
                mapName = (string)val1;
        }

        public void Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties)
        {
            Helper.WritePropertyBag(propertyBag, "Enabled", (object)enabled);
            Helper.WritePropertyBag(propertyBag, "MapName", (object)mapName);
        }

        #endregion

        #region Private Methods

        private Stream TransformMessage(Stream bodyStream)
        {
            Microsoft.BizTalk.Streaming.VirtualStream vs = null;

            try
            {
                Microsoft.BizTalk.ScalableTransformation.BTSXslTransform trans = new Microsoft.BizTalk.ScalableTransformation.BTSXslTransform();
                System.Xml.Xsl.XsltArgumentList args = null;

                XmlTextReader inputReader = new XmlTextReader(bodyStream);

                // Load map from map spec
                Type mapType = Type.GetType(mapName, true);
                Microsoft.XLANGs.RuntimeTypes.TransformMetaData map = Microsoft.XLANGs.RuntimeTypes.TransformMetaData.For(mapType);
                trans = map.StreamingTransform;
                args = map.ArgumentList;

                // Create memory stream to hold transformed data 
                vs = new Microsoft.BizTalk.Streaming.VirtualStream(Microsoft.BizTalk.Streaming.VirtualStream.MemoryFlag.AutoOverFlowToDisk);
                trans.ScalableTransform(inputReader, null, vs, new XmlUrlResolver(), false);
                vs.Seek(0, SeekOrigin.Begin);
            }
            catch (Exception e)
            {
                System.Diagnostics.Trace.WriteLine(e.Message);
                System.Diagnostics.Trace.WriteLine(e.StackTrace);
                throw e;
            }
            return vs;
        } 

        #endregion

        #region IComponentUI Properties

        [Browsable(false)]
        public string Description
        {
            get
            {
                return "StreamingTransform";
            }
        }

        [Browsable(false)]
        IntPtr IComponentUI.Icon
        {
            get
            {
                return IntPtr.Zero;
            }
        }

        [Browsable(false)]
        public string Name
        {
            get
            {
                return "Streaming Transform";
            }
        }

        [Browsable(false)]
        public string Version
        {
            get
            {
                return Assembly.GetExecutingAssembly().GetName().Version.ToString(2);
            }
        }

        #endregion
    }
}

Helper.cs

using System;
using System.IO;
using System.Linq;
using System.Resources;
using System.Reflection;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.ComponentModel;
using System.Collections.Generic;
using Microsoft.BizTalk.Streaming;
using System.Runtime.InteropServices;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;

namespace Integr8.BizTalk.PipelineComponents
{
    /// &lt;summary&gt;
    /// Helper class for reusable functionality
    /// &lt;/summary&gt;
    [Serializable]
    internal class Helper
    {
        #region Internal Methods

        internal static object ReadPropertyBag(IPropertyBag propertyBag, string propName)
        {
            object ptrVar = null;
            try
            {
                propertyBag.Read(propName, out ptrVar, 0);
            }
            catch (ArgumentException)
            {
                return ptrVar;
            }
            catch (System.Exception exception)
            {
                throw new System.Exception(exception.ToString());
            }
            return ptrVar;
        }

        internal static void WritePropertyBag(IPropertyBag propertyBag, string propName, object val)
        {
            try
            {
                propertyBag.Write(propName, ref val);
            }
            catch (System.Exception exception)
            {
                throw new System.Exception(exception.ToString());
            }
        }

        internal static string GetMessageBody(IBaseMessage pInMsg)
        {
            System.IO.Stream sourceStream = pInMsg.BodyPart.GetOriginalDataStream();
            string body = string.Empty;

            if (!sourceStream.CanSeek)
            {
                ReadOnlySeekableStream seekableStream = new ReadOnlySeekableStream(sourceStream);
                pInMsg.BodyPart.Data = seekableStream;
                sourceStream = pInMsg.BodyPart.Data;
            }
            if (pInMsg.BodyPart.Data != null)
            {
                sourceStream.Seek(0, System.IO.SeekOrigin.Begin);

                System.IO.StreamReader reader = new System.IO.StreamReader(sourceStream);
                body = reader.ReadToEnd();
            }
            else
                throw new System.Exception(&quot;Cannot retrieve message body, body of message is empty&quot;);

            return body;
        }

        internal static string GetContextProperty(IBaseMessage pInMsg, string propertyName, string propertyNamespace)
        {
            if (pInMsg.Context.Read(propertyName, propertyNamespace) != null)
            {
                return pInMsg.Context.Read(propertyName, propertyNamespace).ToString();
            }
            else
            {
                return string.Empty;
            }
        }

        internal static IBaseMessage CreateIBaseMessage(string xml, IPipelineContext pContext)
        {
            Stream recordStream = new MemoryStream();
            StreamWriter sw = new StreamWriter(recordStream);
            sw.Write(xml);
            sw.Flush();

            IBaseMessage message = pContext.GetMessageFactory().CreateMessage();
            message.AddPart(&quot;Body&quot;, pContext.GetMessageFactory().CreateMessagePart(), true);

            if (recordStream.Position &gt; 0)
                recordStream.Seek(0, System.IO.SeekOrigin.Begin);

            message.BodyPart.Data = recordStream;

            if (message.BodyPart.Data.Position &gt; 0)
                message.BodyPart.Data.Seek(0, System.IO.SeekOrigin.Begin);

            return message;
        }

        #endregion
    }
}
Advertisements
This entry was posted in BizTalk Server. Bookmark the permalink.

One Response to BizTalk Streaming Transform Pipeline Component

  1. Pingback: Remove Empty Nodes XSL | Microsoft Tech

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s