Click here to Skip to main content
15,896,063 members
Articles / Programming Languages / C#

Fax Adapter

Rate me:
Please Sign up or sign in to vote.
3.62/5 (13 votes)
28 Sep 2006CPOL4 min read 63.5K   994   31  
Fax Adapter for BizTalk Server 2006
using System;
using System.IO;
using System.Net;
using System.Xml;
using System.Text;
using System.Security;
using System.Threading;
using System.Collections;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.TransportProxy.Interop;
using Microsoft.Samples.BizTalk.Adapter.Common;


namespace FaxAdapter
{
    internal class FaxReceiverEndpoint : ReceiverEndpoint
    {
        // constants
        private const string MESSAGE_BODY = "body";
        private const string DOT_NET_FILE_PROP_REMOTEFILENAME = "FileName";

        //  properties
        private FaxAdapterReceiveProperties properties;

        //  handle to the EPM
        private IBTTransportProxy transportProxy;

        // used to create new messages / message parts etc.
        private IBaseMessageFactory messageFactory;

        //  used in the creation of messages
        private string transportType;

        //  used in the creation of messages
        private string propertyNamespace;

        // used to track inflight work
        private ControlledTermination controlledTermination;

        //  error count for comparison with the error threshold
        int errorCount;

        private System.Threading.Timer timer = null;

        //  support for Update
        IPropertyBag updatedConfig;
        IPropertyBag updatedBizTalkConfig;
        IPropertyBag updatedHandlerPropertyBag;

        public FaxReceiverEndpoint() 
        { 
        
        }

        public override void Open(string uri, IPropertyBag config, IPropertyBag bizTalkConfig, IPropertyBag handlerPropertyBag, IBTTransportProxy transportProxy, string transportType, string propertyNamespace, ControlledTermination control)
        {
            Trace.WriteLine("[FaxReceiverEndpoint] Open called");
            this.errorCount = 0;

            this.properties = new FaxAdapterReceiveProperties();

            //  Location properties - possibly override some Handler properties
            XmlDocument locationConfigDom = ConfigProperties.ExtractConfigDom(config);
            this.properties.ReadLocationConfiguration(locationConfigDom);

            //  this is our handle back to the EPM
            this.transportProxy = transportProxy;

            // used to create new messages / message parts etc.
            this.messageFactory = this.transportProxy.GetMessageFactory();

            //  used in the creation of messages
            this.transportType = transportType;

            //  used in the creation of messages
            this.propertyNamespace = propertyNamespace;

            // used to track inflight work for shutting down properly
            this.controlledTermination = control;

            Start();

        }

        private void Start()
        {
            this.timer = new Timer(new TimerCallback(ControlledEndpointTask));
            this.timer.Change(0, this.properties.PollingInterval * 1000);
        }

        private void Stop()
        {
            this.timer.Dispose();
        }

        public void ControlledEndpointTask(object val)
        {
            if (this.controlledTermination.Enter())
            {
                try
                {
                    lock (this)
                    {
                        this.EndPointTask();
                    }
                    GC.Collect();
                }
                finally
                {
                    this.controlledTermination.Leave();
                }
            }
        }

        private void EndPointTask()
        {
            try
            {
                PickupFilesAndSubmit();

                errorCount = 0;
            }
            catch (Exception e)
            {
                transportProxy.SetErrorInfo(e);
                errorCount++;
            }
            CheckErrorThreshold();
        }


        private bool CheckErrorThreshold()
        {
            if ((0 != this.properties.ErrorThreshold) && (errorCount > this.properties.ErrorThreshold))
            {
                this.transportProxy.ReceiverShuttingdown(this.properties.Uri, new ErrorThresholdExceeded());
                Stop();
                return false;
            }
            return true;
        }

        private void PickupFilesAndSubmit()
        {
            Trace.WriteLine("[FaxReceiverEndpoint] PickupFilesAndSubmit called");
            
            List<BatchMessage> files = new List<BatchMessage>();

            FaxManager faxManager = new FaxManager(this.properties.FaxMachineName,this.properties.FaxArchiveFolder);
            ArrayList faxFiles = faxManager.GetFilesContent(1);

            for (int i = 0; i < faxFiles.Count; i++)
            {
                IBaseMessagePart part = this.messageFactory.CreateMessagePart();
                part.Data = ((Stream)((FaxFile)faxFiles[i]).FileStream);

                IBaseMessage msg = this.messageFactory.CreateMessage();
                msg.AddPart(MESSAGE_BODY, part, true);

                SystemMessageContext context = new SystemMessageContext(msg.Context);
                context.InboundTransportLocation = this.properties.Uri;
                context.InboundTransportType = this.transportType;

                //msg.Context.Write(DOT_NET_FILE_PROP_REMOTEFILENAME,this.propertyNamespace,

                files.Add( new BatchMessage( msg , faxFiles , BatchOperationType.Submit)); 

            }

            if (this.controlledTermination.TerminateCalled)
                return;

            //  end of file list - one final batch to do
            if (files.Count > 0)
                SubmitFiles(files);

        }

        /// <summary>
        /// Given a List of Messages submit them to BizTalk for processing
        /// </summary>
        private void SubmitFiles(List<BatchMessage> files)
        {
            if (files == null || files.Count == 0) throw new ArgumentException("SubmitFiles was called with an empty list of Files");

            Trace.WriteLine(string.Format("[DotNetFileReceiverEndpoint] SubmitFiles called. Submitting a batch of {0} files.", files.Count));

            //This class is used to track the files associated with this ReceiveBatch
            BatchInfo batchInfo = new BatchInfo(files);
            using (ReceiveBatch batch = new ReceiveBatch(this.transportProxy, this.controlledTermination, batchInfo.OnBatchComplete, this.properties.MaximumNumberOfFiles))
            {
                foreach (BatchMessage file in files)
                {
                    // submit file to batch
                    batch.SubmitMessage(file.Message, file.UserData);
                }

                batch.Done(null);
            }
        }

        public override void Update(IPropertyBag config, IPropertyBag bizTalkConfig, IPropertyBag handlerPropertyBag)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override void Dispose()
        {
            base.Dispose();
        }


        private class BatchInfo
        {
            BatchMessage[] messages;

            internal BatchInfo(List<BatchMessage> messageList)
            {
                this.messages = new BatchMessage[messageList.Count];
                messageList.CopyTo(messages);
            }

            /// <summary>
            /// Called when the BizTalk Batch has been submitted.  If all the messages were submitted (good or suspended)
            /// we delete the files from the folder
            /// </summary>
            /// <param name="overallStatus"></param>
            internal void OnBatchComplete(bool overallStatus)
            {
                Trace.WriteLine(string.Format("[DotNetFileReceiverEndpoint] OnBatchComplete called. overallStatus == {0}.", overallStatus));

                if (overallStatus == true) //Batch completed
                {
                    
                    //Delete the files
                    foreach (BatchMessage batchMessage in messages)
                    {
                        //Close the stream so we can delete this file
                        batchMessage.Message.BodyPart.Data.Close();
                        FaxManager.DeleteMessage((FaxFile)batchMessage.UserData);
                        
                    }
                }
            }
        }

    }

    
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
India India
Anil is from Hyderabad, Andhra Pradesh. He is Currently Working with VisualSoft Technologies Ltd., As a Software Engineer.

Anil has more than 4 yrs of experience in the IT industry working on Microsoft Technologies. He is involved in various project activities like System Architecture, Design, and Development. Technical experience most specifically ASP.NET , Javascript, Biztalk 2004/2006, Webservices, C# and .NET framework. He has have worked on various language and platforms. He is Microsoft Certified professional.

The author has won several programming awards within the organizations worked and is well-recognized.


--

Comments and Discussions