/// <summary>
        /// Writes the supplied <see cref="ISyndicationResource"/> to the specified <see cref="HttpContext"/> response stream and sets the appropriate headers.
        /// </summary>
        /// <param name="context">
        ///     An <see cref="HttpContext"/> object that provides references to the intrinsic server objects
        ///     (for example, <b>Request</b>, <b>Response</b>, <b>Session</b>, and <b>Server</b>) used to service HTTP requests.
        /// </param>
        /// <param name="resource">The <see cref="ISyndicationResource"/> to be written to the response stream.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="context"/> is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="resource"/> is a null reference (Nothing in Visual Basic).</exception>
        private void WriteResource(HttpContext context, ISyndicationResource resource)
        {
            //------------------------------------------------------------
            //	Validate parameters
            //------------------------------------------------------------
            Guard.ArgumentNotNull(context, "context");
            Guard.ArgumentNotNull(resource, "resource");

            //------------------------------------------------------------
            //	Process conditional GET information if present
            //  (If conditions met, handler execution stops.)
            //------------------------------------------------------------
            SyndicationResourceHandler.ProcessConditionalGetInformation(context, resource);

            //------------------------------------------------------------
            //	Modify response meta-data information
            //------------------------------------------------------------
            context.Response.ContentType = SyndicationResourceHandler.ContentFormatAsMimeType(resource.Format);
            context.Response.AppendHeader("Content-Disposition", SyndicationResourceHandler.GetContentDisposition(resource.Format));

            //------------------------------------------------------------
            //	Save XML representation of resource to output stream
            //------------------------------------------------------------
            SyndicationResourceSaveSettings settings = new SyndicationResourceSaveSettings();

            settings.AutoDetectExtensions = true;
            settings.MinimizeOutputSize   = false;

            resource.Save(context.Response.OutputStream, settings);

            //------------------------------------------------------------
            //	Modify response caching expiration information
            //------------------------------------------------------------
            this.ModifyCacheExpiration(context);
        }
        /// <summary>
        /// Enables a factory to reuse an existing HTTP handler instance.
        /// </summary>
        /// <param name="handler">The <see cref="IHttpHandler"/> object to reuse.</param>
        public void ReleaseHandler(IHttpHandler handler)
        {
            //------------------------------------------------------------
            //	Local members
            //------------------------------------------------------------
            SyndicationResourceHandler syndicationHandler = null;

            //------------------------------------------------------------
            //	Verify handler is reusable
            //------------------------------------------------------------
            if (handler.IsReusable)
            {
                lock (factoryHandlerLock)
                {
                    if (factoryHandlers.Count < handlerPoolLimit)
                    {
                        syndicationHandler = handler as SyndicationResourceHandler;

                        if (syndicationHandler != null)
                        {
                            factoryHandlers.Push(syndicationHandler);
                        }
                    }
                }
            }
        }
        //============================================================
        //	PROTECTED METHODS
        //============================================================
        #region OnPreRender(EventArgs e)
        /// <summary>
        /// Raises the <see cref="Control.PreRender">PreRender</see> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> object that contains the event data.</param>
        /// <remarks>
        ///     <para>This method notifies the server control to perform any necessary pre-rendering steps prior to saving view state and rendering content.</para>
        ///     <para>
        ///         During this step in the ASP.NET page life-cycle, the <see cref="SyndicationAutoDiscoveryHyperlink"/> will attempt to add
        ///         a <i><link rel="alternate" type="{MIME Type}" title="{Text}" href="{NavigateUrl}" /></i> to the page header section if
        ///         it is available to be modified.
        ///     </para>
        ///     <para>
        ///         The MIME media type of the link will be automatically selected based on the <see cref="Format">format</see>
        ///         unless the <see cref="MediaType">media type</see> has been explicitly specified.
        ///     </para>
        ///     <para>
        ///         The <i>title</i> attribute will only be rendered if the control's <see cref="Text"/> property has been specified.
        ///     </para>
        /// </remarks>
        protected override void OnPreRender(EventArgs e)
        {
            //------------------------------------------------------------
            //	Local members
            //------------------------------------------------------------
            string mimeType = String.Empty;
            string href     = String.Empty;
            string title    = String.Empty;

            //------------------------------------------------------------
            //	Do not render control is invisible or disabled
            //------------------------------------------------------------
            if (!this.Visible || !this.Enabled)
            {
                base.OnPreRender(e);
                return;
            }

            //------------------------------------------------------------
            //	As the page header control collection cannot be
            //  modified during the PreRender phase, exit this event
            //  handler to prevent raising an exception.
            //------------------------------------------------------------
            if (this.Parent is System.Web.UI.HtmlControls.HtmlHead)
            {
                base.OnPreRender(e);
                return;
            }
            else if (this.Parent is System.Web.UI.WebControls.ContentPlaceHolder && this.Parent.Parent is System.Web.UI.HtmlControls.HtmlHead)
            {
                base.OnPreRender(e);
                return;
            }

            //------------------------------------------------------------
            //	Render auto-discovery link
            //------------------------------------------------------------
            href = this.NavigateUrl != null?this.NavigateUrl.ToString() : String.Empty;

            mimeType = SyndicationResourceHandler.ContentFormatAsMimeType(this.Format);
            if (!String.IsNullOrEmpty(this.Text))
            {
                title = this.Text;
            }

            if (this.Page.Header != null)
            {
                string controlContent = String.Format(null, "\r\n<link rel=\"alternate\" type=\"{0}\" href=\"{1}\" />", mimeType, href);
                if (!String.IsNullOrEmpty(title))
                {
                    controlContent = String.Format(null, "\r\n<link rel=\"alternate\" type=\"{0}\" href=\"{1}\" title=\"{2}\" />", mimeType, href, title);
                }
                LiteralControl link = new LiteralControl(controlContent);

                this.Page.Header.Controls.Add(link);
            }

            base.OnPreRender(e);
        }
        /// <summary>
        /// Outputs server control content to a provided <see cref="HtmlTextWriter"/> object and stores tracing information about the control if tracing is enabled.
        /// </summary>
        /// <param name="writer">The <see cref="HtmlTextWriter"/> object that receives the control content.</param>
        /// <remarks>
        ///     <para>
        ///         The MIME media type of the link will be automatically selected based on the <see cref="Format">format</see>
        ///         unless the <see cref="MediaType">media type</see> has been explicitly specified.
        ///     </para>
        ///     <para>
        ///         The <i>title</i> attribute will only be rendered if the control's <see cref="Text"/> property has been specified.
        ///     </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">The <paramref name="writer"/> is a null reference (Nothing in Visual Basic).</exception>
        public override void RenderControl(HtmlTextWriter writer)
        {
            //------------------------------------------------------------
            //	Local members
            //------------------------------------------------------------
            string mimeType = String.Empty;
            string href     = String.Empty;
            string title    = String.Empty;

            //------------------------------------------------------------
            //	Validate parameter
            //------------------------------------------------------------
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            //------------------------------------------------------------
            //	Do not render control is invisible or disabled
            //------------------------------------------------------------
            if (!this.Enabled || !this.Visible)
            {
                return;
            }

            //------------------------------------------------------------
            //	Determine if link is positioned in HTML head
            //------------------------------------------------------------
            if (this.Parent is System.Web.UI.HtmlControls.HtmlHead)
            {
                //------------------------------------------------------------
                //	Render auto-discovery link
                //------------------------------------------------------------
                href = this.NavigateUrl != null?this.NavigateUrl.ToString() : String.Empty;

                mimeType = SyndicationResourceHandler.ContentFormatAsMimeType(this.Format);
                if (!String.IsNullOrEmpty(this.Text))
                {
                    title = this.Text;
                }

                writer.AddAttribute(HtmlTextWriterAttribute.Rel, "alternate");
                writer.AddAttribute(HtmlTextWriterAttribute.Type, mimeType);
                writer.AddAttribute(HtmlTextWriterAttribute.Href, href);
                if (!String.IsNullOrEmpty(title))
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Title, title);
                }

                writer.RenderBeginTag(HtmlTextWriterTag.Link);
                writer.RenderEndTag();
                writer.WriteLine();
            }
        }
        /// <summary>
        /// Processes conditional GET header information for the supplied <see cref="ISyndicationResource"/>.
        /// </summary>
        /// <param name="context">
        ///     An <see cref="HttpContext"/> object that provides references to the intrinsic server objects
        ///     (for example, <b>Request</b>, <b>Response</b>, <b>Session</b>, and <b>Server</b>) used to service HTTP requests.
        /// </param>
        /// <param name="resource">The <see cref="ISyndicationResource"/> that is used when determining if conditional GET operation requirements were met.</param>
        /// <remarks>
        ///     <para>
        ///         This  method will retrieve conditional GET information from the request headers, and if present, will set the appropriate
        ///         response header information and status for the supplied <paramref name="resource"/>. If a modification date is available for
        ///         the supplied <paramref name="resource"/>, the conditional GET header information will be set so that clients may optionally
        ///         cache this infomration when making future requests.
        ///     </para>
        ///     <para>If a conditional GET operation was fulflled, no additional processing or modification of the response should be performed.</para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">The <paramref name="context"/> is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="resource"/> is a null reference (Nothing in Visual Basic).</exception>
        private static void ProcessConditionalGetInformation(HttpContext context, ISyndicationResource resource)
        {
            //------------------------------------------------------------
            //	Local members
            //------------------------------------------------------------
            string eTag                 = String.Empty;
            string ifModifiedSince      = String.Empty;
            bool   resourceIsUnmodified = false;

            //------------------------------------------------------------
            //	Validate parameters
            //------------------------------------------------------------
            Guard.ArgumentNotNull(context, "context");
            Guard.ArgumentNotNull(resource, "resource");

            //------------------------------------------------------------
            //	Perform conditional GET processing
            //------------------------------------------------------------
            eTag            = context.Request.Headers["If-None-Match"];
            ifModifiedSince = context.Request.Headers["if-modified-since"];

            if (!String.IsNullOrEmpty(eTag) || !String.IsNullOrEmpty(ifModifiedSince))
            {
                DateTime lastModified = SyndicationResourceHandler.GetLastModificationDate(resource);

                if (lastModified == DateTime.MinValue)
                {
                    return;
                }

                if (!String.IsNullOrEmpty(eTag))
                {
                    //------------------------------------------------------------
                    //	Determine if not modified by comparing last modified date-time
                    //------------------------------------------------------------
                    resourceIsUnmodified = eTag.Equals(lastModified.Ticks.ToString(CultureInfo.InvariantCulture));
                }
                else if (!String.IsNullOrEmpty(ifModifiedSince))
                {
                    //------------------------------------------------------------
                    //	Determine if not modified by comparing if modified since date-time
                    //------------------------------------------------------------
                    if (ifModifiedSince.IndexOf(";", StringComparison.OrdinalIgnoreCase) > -1)
                    {
                        ifModifiedSince = ifModifiedSince.Split(';').GetValue(0).ToString().Trim();    // Wed, 29 Dec 2004 18:34:27 GMT; length=126275
                    }

                    DateTime ifModifiedDate;
                    if (DateTime.TryParse(ifModifiedSince, out ifModifiedDate))
                    {
                        resourceIsUnmodified = (lastModified <= ifModifiedDate);
                    }
                }

                //------------------------------------------------------------
                //	Set conditional GET response information
                //------------------------------------------------------------
                if (resourceIsUnmodified)
                {
                    context.Response.StatusCode      = 304;
                    context.Response.SuppressContent = true;
                    context.Response.End();     // HTTP handler execution stops.
                }
                else
                {
                    if (lastModified <= DateTime.Now)
                    {
                        context.Response.Cache.SetLastModified(lastModified);
                    }
                    else
                    {
                        context.Response.Cache.SetLastModified(context.Timestamp);
                    }
                    context.Response.Cache.SetETag(lastModified.Ticks.ToString(CultureInfo.InvariantCulture));
                }
            }
        }
        //============================================================
        //	PUBLIC METHODS
        //============================================================
        #region GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        /// <summary>
        /// Returns an instance of a class that implements the <see cref="IHttpHandler"/> interface.
        /// </summary>
        /// <param name="context">
        ///     An instance of the <see cref="HttpContext"/> class that provides references to
        ///     intrinsic server objects (for example, <b>Request</b>, <b>Response</b>, <b>Session</b>, and <b>Server</b>) used to service HTTP requests.
        /// </param>
        /// <param name="requestType">The HTTP data transfer method (<b>GET</b> or <b>POST</b>) that the client uses.</param>
        /// <param name="url">The <see cref="HttpRequest.RawUrl">RawUrl</see> of the requested resource.</param>
        /// <param name="pathTranslated">The <see cref="HttpRequest.PhysicalApplicationPath">PhysicalApplicationPath</see> to the requested resource.</param>
        /// <returns>A new <see cref="SyndicationResourceHandler"/> object that processes the request.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="context"/> is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="requestType"/> is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="requestType"/> is an empty string.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="url"/> is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="url"/> is an empty string.</exception>
        /// <exception cref="HttpException">The factory was unable to create a <see cref="SyndicationResourceHandler"/> for the request.</exception>
        public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        {
            //------------------------------------------------------------
            //	Local members
            //------------------------------------------------------------
            SyndicationResourceHandler handler = null;

            //------------------------------------------------------------
            //	Validate parameters
            //------------------------------------------------------------
            Guard.ArgumentNotNull(context, "context");
            Guard.ArgumentNotNullOrEmptyString(requestType, "requestType");
            Guard.ArgumentNotNullOrEmptyString(url, "url");

            //------------------------------------------------------------
            //	Return reusable handler if available
            //------------------------------------------------------------
            lock (factoryHandlerLock)
            {
                if (factoryHandlers.Count > 0)
                {
                    handler = (SyndicationResourceHandler)factoryHandlers.Pop();
                    return(handler);
                }
            }

            //------------------------------------------------------------
            //	Attempt to create handler
            //------------------------------------------------------------
            try
            {
                handler = (SyndicationResourceHandler)Activator.CreateInstance(typeof(SyndicationResourceHandler));

                //------------------------------------------------------------
                //	Get factory name
                //------------------------------------------------------------
                string fullName    = url.Substring(url.LastIndexOf('/') + 1);
                string factoryName = fullName.Substring(0, fullName.IndexOf('.'));

                //------------------------------------------------------------
                //	Set syndication format of handler based on factory path
                //------------------------------------------------------------
                if (String.Compare(factoryName, "Apml", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    handler.Format = SyndicationContentFormat.Apml;
                }
                else if (String.Compare(factoryName, "Atom", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    handler.Format = SyndicationContentFormat.Atom;
                }
                else if (String.Compare(factoryName, "BlogML", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    handler.Format = SyndicationContentFormat.BlogML;
                }
                else if (String.Compare(factoryName, "Opml", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    handler.Format = SyndicationContentFormat.Opml;
                }
                else if (String.Compare(factoryName, "Rsd", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    handler.Format = SyndicationContentFormat.Rsd;
                }
                else if (String.Compare(factoryName, "Rss", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    handler.Format = SyndicationContentFormat.Rss;
                }

                return(handler);
            }
            catch (Exception exception)
            {
                //------------------------------------------------------------
                //	Rethrow exception as HttpException with param information
                //------------------------------------------------------------
                throw new HttpException(String.Format(null, "The SyndicationHttpHandlerFactory was unable to create a handler for requestType='{0}', url='{1}', pathTranslated='{2}'.", requestType, url, pathTranslated), exception);
            }
        }