File: Serialization\Manager\NullPackagingPolicy.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\ReachFramework\ReachFramework.csproj (ReachFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
/*++
 
    Abstract:
        This file contains the implementation of an instance of the policy
        that bypasses the physical file as the target of the serialization
        process. the intension here is to be able to profile performance
        of different components in the system.
 
--*/
using System.Collections;
using System.Xml;
using System.IO;
using System.Globalization;
using System.Windows.Xps.Packaging;
using System.Printing;
 
namespace System.Windows.Xps.Serialization
{
    /// <summary>
    /// A class implementing a Xps specific packaging policy
    /// </summary>
    internal class NullPackagingPolicy :
                 BasePackagingPolicy
    {
        #region Constructor
 
        /// <summary>
        /// instantiate a NullPackagingPolicy class
        /// </summary>
        public
        NullPackagingPolicy(
            ):
        base()
        {
            Initialize();
 
            _fontResourceStream             = null;
            _imageResourceStream            = null;
            _colorContextResourceStream     = null;
            _resourceDictionaryResourceStream  = null;
 
 
            _fontAcquireMode                = ResourceAcquireMode.NoneAcquired;
            _fontsCache   = new Hashtable(11);
 
            InitializeResourceReferences();
 
            _resourcePolicy = new XpsResourcePolicy(XpsResourceSharing.NoResourceSharing);
            _resourcePolicy.RegisterService(new XpsImageSerializationService(),
                                            typeof(XpsImageSerializationService));
            _resourcePolicy.RegisterService(new XpsFontSerializationService(this),
                                            typeof(XpsFontSerializationService));
        }
 
        #endregion Constructor
 
        #region Public Methods
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XmlWriter
        AcquireXmlWriterForFixedDocumentSequence(
            )
        {
            XmlWriter xmlWriter = null;
 
            if(_currentDocumentSequenceWriterRef == 0)
            {
                //
                // We would simulate an inmemory object for the sequence and populate it with data
                //
                _currentFixedDocumentSequenceWriter = new StringWriter(CultureInfo.InvariantCulture);
                _currentDSWriter                    = new XmlTextWriter(_currentFixedDocumentSequenceWriter);
            }
 
            _currentDocumentSequenceWriterRef++;
 
            xmlWriter = _currentDSWriter as XmlWriter;
 
            return xmlWriter;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseXmlWriterForFixedDocumentSequence(
            )
        {
            if(_currentFixedDocumentSequenceWriter!=null &&
               _currentDocumentSequenceWriterRef>0)
            {
                _currentDocumentSequenceWriterRef--;
 
                if(_currentDocumentSequenceWriterRef == 0)
                {
                    //
                    // if any of the other low level writer exist, then
                    // throw an exception or is it better if we just close
                    // them and consider that if any additional call on them
                    // would be the one that throws the expcetion
                    //
                    //_currentFixedDocumentSequenceWriter.Commit();
                    Initialize();
                    InitializeResourceReferences();
                }
            }
            else
            {
                throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
            }
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XmlWriter
        AcquireXmlWriterForFixedDocument(
            )
        {
            XmlWriter xmlWriter = null;
 
            if(_currentFixedDocumentWriterRef == 0)
            {
                //
                // We need to create the corresponding part in the Xps package
                // and then acquire the writer
                //
                if(_currentFixedDocumentSequenceWriter != null)
                {
                    _currentFixedDocumentWriter = new StringWriter(CultureInfo.InvariantCulture);
                    _currentFDWriter            = new XmlTextWriter(_currentFixedDocumentWriter);
                }
            }
 
            _currentFixedDocumentWriterRef++;
 
            xmlWriter = _currentFDWriter as XmlWriter;
 
            return xmlWriter;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseXmlWriterForFixedDocument(
            )
        {
            if(_currentFixedDocumentWriter!=null &&
               _currentFixedDocumentWriterRef>0)
            {
                _currentFixedDocumentWriterRef--;
 
                if(_currentFixedDocumentWriterRef == 0)
                {
                    //
                    // if any of the other low level writer exist, then
                    // throw an exception or is it better if we just close
                    // them and consider that if any additional call on them
                    // would be the one that throws the expcetion
                    //
                    //_currentFixedDocumentWriter.Commit();
                    //
                    // All current lower references should be cleared
                    //
                    _currentFixedDocumentWriter  = null;
                    _currentFixedPageWriter      = null;
                    _currentFixedPageWriterRef   = 0;
                    InitializeResourceReferences();
                }
            }
            else
            {
                throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
            }
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XmlWriter
        AcquireXmlWriterForFixedPage(
            )
        {
            XmlWriter xmlWriter = null;
 
            if(_currentFixedPageWriterRef == 0)
            {
                //
                // We need to create the corresponding part in the Xps package
                // and then acquire the writer
                //
                if(_currentFixedDocumentWriter != null)
                {
                    _currentFixedPageWriter      = new StringWriter(CultureInfo.InvariantCulture);
                    _currentFPWriter             = new XmlTextWriter(_currentFixedPageWriter);
                    _linkTargetStream            = new List <String>();
                    _resourceStream              = new StringWriter(CultureInfo.InvariantCulture);
                    _resourceXmlWriter           = new XmlTextWriter(_resourceStream);
                    _resourceDictionaryStream    = new StringWriter(CultureInfo.InvariantCulture);
                    _resourceDictionaryXmlWriter = new XmlTextWriter(_resourceDictionaryStream);
                    _pageStream                  = new StringWriter(CultureInfo.InvariantCulture);
                    _pageXmlWriter               = new XmlTextWriter(_pageStream);
                }
            }
 
            _currentFixedPageWriterRef++;
 
            xmlWriter = _currentFPWriter;
 
            return xmlWriter;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseXmlWriterForFixedPage(
            )
        {
            if(_currentFixedPageWriter!=null &&
               _currentFixedPageWriterRef>0)
            {
                _currentFixedPageWriterRef--;
 
                if(_currentFixedPageWriterRef == 0)
                {
                    //
                    // if any of the other low level writer exist, then
                    // throw an exception or is it better if we just close
                    // them and consider that if any additional call on them
                    // would be the one that throws the expcetion
                    //
                    //_currentFixedPageWriter.Commit();
                    //
                    // All current lower references should be cleared
                    //
                    _currentFixedPageWriter      = null;
                    _linkTargetStream            = null;
                    _resourceStream              = null;
                    _resourceXmlWriter           = null;
                    _resourceDictionaryStream    = null;
                    _resourceDictionaryXmlWriter = null;
                    _pageStream                  = null;
                    _pageXmlWriter               = null;
 
                    InitializeResourceReferences();
                }
            }
            else
            {
                throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
            }
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XpsResourceStream
        AcquireResourceStreamForXpsFont(
            )
        {
            XpsResourceStream resourceStream = null;
 
            if(_fontAcquireMode != ResourceAcquireMode.MultipleAcquired)
            {
                if(_fontAcquireMode == ResourceAcquireMode.NoneAcquired)
                {
                    _fontAcquireMode = ResourceAcquireMode.SingleAcquired;
                }
 
                if(_currentXpsFontRef == 0)
                {
                    //
                    // We need to create the corresponding part in the Xps package
                    // and then acquire the Stream
                    //
                    Stream fontStream = null;
 
                    if(_currentFixedPageWriter != null)
                    {
                        //
                        // Create a new Font Stream
                        //
                        fontStream = new MemoryStream();
                    }
                    else
                    {
                        throw new XpsSerializationException(SR.ReachSerialization_NoFixedPageWriter);
                    }
 
                    //
                    // retreive the appropriate stream and uri from the reach package api layer
                    //
                    if(fontStream !=null)
                    {
                         _fontResourceStream = new XpsResourceStream(fontStream,
                                                                  new Uri("package/font",UriKind.Relative));
                         //
                         // This is to handle PSharp bug claiming we do not dispose
                         // this class.  We can not dipose because ownership has been handed off.
                         // thus we set it to null
                         //
                         fontStream = null;
                    }
                    else
                    {
                        //
                        // throw the appropriate exception
                        //
                    }
                }
 
                _currentXpsFontRef++;
 
                resourceStream = _fontResourceStream;
 
            }
            else
            {
                //
                // throw the appropraite exception
                //
            }
 
            return resourceStream;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XpsResourceStream
        AcquireResourceStreamForXpsFont(
            String resourceId
            )
        {
            XpsResourceStream resourceStream = null;
 
            if(_fontAcquireMode != ResourceAcquireMode.SingleAcquired)
            {
                if(_fontAcquireMode == ResourceAcquireMode.NoneAcquired)
                {
                    _fontAcquireMode = ResourceAcquireMode.MultipleAcquired;
                }
 
                ResourceStreamCacheItem resourceStreamCacheItem = (ResourceStreamCacheItem)_fontsCache[resourceId];
 
                if(resourceStreamCacheItem == null)
                {
                    resourceStreamCacheItem = new ResourceStreamCacheItem();
 
                    //
                    // We need to create the corresponding part in the Xps package
                    // and then acquire the Stream
                    //
                    if(_currentFixedPageWriter != null)
                    {
                        //XpsFont reachFont = _currentFixedPageWriter.AddFont(resourceId);
 
                        Stream fontStream = new MemoryStream();
 
                        if(fontStream !=null)
                        {
                            resourceStreamCacheItem.XpsResource = null;
                            //
                            // retreive the appropriate stream and uri from the reach package api layer
                            //
                            _fontResourceStream = new XpsResourceStream(fontStream,
                                                                     new Uri("package/font",UriKind.Relative));
                                                  
                            resourceStreamCacheItem.XpsResourceStream = _fontResourceStream;
    
                            _fontsCache[resourceId] = resourceStreamCacheItem;
 
                            resourceStream = _fontResourceStream;
                            //
                            // This is to handle PSharp bug claiming we do not dispose
                            // this class.  We can not dipose because ownership has been handed off.
                            // thus we set it to null
                            //
                            fontStream = null;
                        }
                        else
                        {
                            //
                            // throw the appropriate exception
                            //
                        }
 
                    }
                    else
                    {
                        throw new XpsSerializationException(SR.ReachSerialization_NoFixedPageWriter);
                    }
                }
                else
                {
                    resourceStream = resourceStreamCacheItem.XpsResourceStream;
                    resourceStreamCacheItem.IncRef();
                }
            }
            else
            {
                //
                // throw the appropraite exception
                //
            }
 
            return resourceStream;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseResourceStreamForXpsFont(
            )
        {
            if(_fontAcquireMode == ResourceAcquireMode.SingleAcquired)
            {
                if(_currentXpsFontRef>0)
                {
                    _currentXpsFontRef--;
 
                    if(_currentXpsFontRef == 0)
                    {
                        _fontResourceStream.Initialize();
                        _fontResourceStream = null;
                        _fontAcquireMode    = ResourceAcquireMode.NoneAcquired;
                    }
                }
                else
                {
                    throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
                }
            }
            else
            {
                //
                // throw the appropriate exception
                //
            }
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseResourceStreamForXpsFont(
            String resourceId
            )
        {
            if(_fontAcquireMode == ResourceAcquireMode.MultipleAcquired)
            {
                ResourceStreamCacheItem resourceStreamCacheItem = (ResourceStreamCacheItem)_fontsCache[resourceId];
 
                if(resourceStreamCacheItem != null)
                {
                    if(resourceStreamCacheItem.Release() == 0)
                    {
                        //resourceStreamCacheItem.XpsResource.Commit();
                        _fontsCache.Remove(resourceId);
 
                        if(_fontsCache.Count == 0)
                        {
                            _fontAcquireMode = ResourceAcquireMode.NoneAcquired;
                        }
                    }
                }
                else
                {
                    throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
                }
            }
            else
            {
                //
                // throw the appropriate exception
                //
            }
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XpsResourceStream
        AcquireResourceStreamForXpsImage(
            String resourceId
            )
        {
            XpsResourceStream resourceStream = null;
 
            if(_currentXpsImageRef == 0)
            {
                //
                // We need to create the corresponding part in the Xps package
                // and then acquire the Stream
                //
                if(_currentFixedPageWriter != null)
                {
                     _imageResourceStream = new XpsResourceStream(new MemoryStream(),
                                                               new Uri("package/image",UriKind.Relative));
                }
                else
                {
                    //
                    // throw the appropriate exception
                    //
                }
            }
 
            _currentXpsImageRef++;
 
            resourceStream = _imageResourceStream;
 
            return resourceStream;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseResourceStreamForXpsImage(
            )
        {
            if(_currentXpsImageRef>0)
            {
                _currentXpsImageRef--;
 
                if(_currentXpsImageRef == 0)
                {
                    //_currentXpsImage.Commit();
                    _imageResourceStream.Initialize();
                    _imageResourceStream = null;
                }
            }
            else
            {
                throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
            }
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XpsResourceStream
        AcquireResourceStreamForXpsColorContext(
            String resourceId
            )
        {
            XpsResourceStream resourceStream = null;
 
            if(_currentXpsColorContextRef == 0)
            {
                //
                // We need to create the corresponding part in the Xps package
                // and then acquire the Stream
                //
                if(_currentFixedPageWriter != null)
                {
                     _colorContextResourceStream = new XpsResourceStream(new MemoryStream(),
                                                               new Uri("package/colorcontext",UriKind.Relative));
                }
                else
                {
                    //
                    // throw the appropriate exception
                    //
                }
            }
 
            _currentXpsColorContextRef++;
 
            resourceStream = _colorContextResourceStream;
 
            return resourceStream;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseResourceStreamForXpsColorContext(
            )
        {
            if(_currentXpsColorContextRef>0)
            {
                _currentXpsColorContextRef--;
 
                if(_currentXpsColorContextRef == 0)
                {
                    //_currentXpsColorContext.Commit();
                    _colorContextResourceStream.Initialize();
                    _colorContextResourceStream = null;
                }
            }
            else
            {
                throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
            }
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        XpsResourceStream
        AcquireResourceStreamForXpsResourceDictionary(
            String resourceId
            )
        {
            XpsResourceStream resourceStream = null;
 
            if(_currentXpsResourceDictionaryRef == 0)
            {
                //
                // We need to create the corresponding part in the Xps package
                // and then acquire the Stream
                //
                if(_currentFixedPageWriter != null)
                {
                     _resourceDictionaryResourceStream = new XpsResourceStream(new MemoryStream(),
                                                               new Uri("package/colorcontext",UriKind.Relative));
                }
                else
                {
                    //
                    // throw the appropriate exception
                    //
                }
            }
 
            _currentXpsResourceDictionaryRef++;
 
            resourceStream = _resourceDictionaryResourceStream;
 
            return resourceStream;
        }
 
        /// <Summary>
        ///
        /// </Summary>
        public
        override
        void
        ReleaseResourceStreamForXpsResourceDictionary(
            )
        {
            if(_currentXpsResourceDictionaryRef>0)
            {
                _currentXpsResourceDictionaryRef--;
 
                if(_currentXpsResourceDictionaryRef == 0)
                {
                    //_currentXpsResourceDictionary.Commit();
                    _resourceDictionaryResourceStream.Initialize();
                    _resourceDictionaryResourceStream = null;
                }
            }
            else
            {
                throw new XpsSerializationException(SR.ReachSerialization_CannotReleaseXmlWriter);
            }
        }
 
        /// <summary>
        /// This method adds a relationship to the current active
        /// page using the specified target and relationship name.
        /// </summary>
        /// <param name="targetUri">
        /// Uri to Target for relationship.
        /// </param>
        /// <param name="relationshipName">
        /// Relationship name to add.
        /// </param>
        public
        override
        void
        RelateResourceToCurrentPage(
            Uri targetUri,
            string relationshipName
            )
        {
        }
 
        /// <summary>
        /// This method adds a relationship to the current active
        /// document using the specified target and relationship name.
        /// </summary>
        /// <param name="targetUri">
        /// Uri to Target for relationship.
        /// </param>
        public
        override
        void
        RelateRestrictedFontToCurrentDocument(
            Uri targetUri
            )
        {
        }
 
        /// <summary>
        /// Persists the PrintTicket to the packaging layer
        /// </summary>
        /// <exception cref="ArgumentNullException">printTicket is NULL.</exception>
        /// <param name="printTicket">
        /// Caller supplied PrintTicket.
        /// </param>
        public
        override
        void
        PersistPrintTicket(
            PrintTicket printTicket
            )
        {
            ArgumentNullException.ThrowIfNull(printTicket);
 
            //
            // We need to figure out at which level of the package
            // is this printTicket targeted
            //
            if(_currentFixedPageWriter != null)
            {
                _pagePrintTicket = printTicket.Clone();
            }
            else if(_currentFixedDocumentWriter != null)
            {
                _documentPrintTicket = printTicket.Clone();
            }
            else if(_currentFixedDocumentSequenceWriter != null)
            {
                _documentSequencePrintTicket = printTicket.Clone();
            }
        }
 
        /// <summary>
        ///
        /// </summary>
        public
        override
        XmlWriter
        AcquireXmlWriterForPage(
            )
        {
            return _pageXmlWriter;
        }
 
        /// <summary>
        ///
        /// </summary>
        public
        override
        void
        PreCommitCurrentPage(
            )
        {
            _resourceXmlWriter.Flush();
            _pageXmlWriter.Flush();
 
            if(_resourceXmlWriter.ToString().Length > 0)
            {
                _resourceDictionaryXmlWriter.WriteStartElement(XpsS0Markup.PageResources);
                _resourceDictionaryXmlWriter.WriteStartElement(XpsS0Markup.ResourceDictionary);
 
                _resourceDictionaryXmlWriter.WriteRaw(_resourceStream.ToString());
 
                _resourceDictionaryXmlWriter.WriteEndElement();
                _resourceDictionaryXmlWriter.WriteEndElement();
 
                _resourceDictionaryXmlWriter.Flush();
 
                _currentFPWriter.WriteRaw(_resourceDictionaryStream.ToString());
            }
 
 
            //
            // Join resource and page stream into main stream
            //
            _currentFPWriter.WriteRaw(_pageStream.ToString());
        }
 
        /// <summary>
        ///
        /// </summary>
        public
        override
        XmlWriter
        AcquireXmlWriterForResourceDictionary(
            )
        {
            return _resourceDictionaryXmlWriter;
        }
 
        /// <summary>
        ///
        /// </summary>
        public
        override
        IList<String>
        AcquireStreamForLinkTargets(
            )
        {
            return _linkTargetStream;
        }
        
        #endregion Public Methods
 
        #region Public Properties
 
        /// <summary>
        ///
        /// </summary>
        public
        override
        Uri
        CurrentFixedDocumentUri
        {
            get
            {
                //return _currentFixedDocumentWriter.Uri;
                return null;
            }
        }
 
        /// <summary>
        ///
        /// </summary>
        public
        override
        Uri
        CurrentFixedPageUri
        {
            get
            {
                //return _currentFixedPageWriter.Uri;
                return null;
            }
        }
 
 
        #endregion Public Properties
 
        #region Private Methods
 
        private
        void
        Initialize(
            )
        {
            _currentFixedDocumentSequenceWriter  = null;
            _currentFixedDocumentWriter          = null;
            _currentFixedPageWriter              = null;
            _currentDocumentSequenceWriterRef    = 0;
            _currentFixedDocumentWriterRef       = 0;
            _currentFixedPageWriterRef           = 0;
        }
 
        private
        void
        InitializeResourceReferences(
            )
        {
            _currentXpsFontRef            = 0;
            _currentXpsImageRef           = 0;
            _currentXpsColorContextRef    = 0;
            _currentXpsResourceDictionaryRef = 0;
 
            if(_fontResourceStream!=null)
            {
                _fontResourceStream.Initialize();
            }
 
            if(_imageResourceStream!=null)
            {
                _imageResourceStream.Initialize();
            }
 
            if(_colorContextResourceStream!=null)
            {
                _colorContextResourceStream.Initialize();
            }
 
            if(_resourceDictionaryResourceStream!=null)
            {
                _resourceDictionaryResourceStream.Initialize();
            }
 
 
            _fontAcquireMode = ResourceAcquireMode.NoneAcquired;
        }
 
      
        #endregion Private Methods
 
        #region Private Data
 
        private
        StringWriter                _currentFixedDocumentSequenceWriter;
 
        private
        StringWriter                _currentFixedDocumentWriter;
 
        private
        StringWriter                _currentFixedPageWriter;
 
        private
        int                         _currentDocumentSequenceWriterRef;
 
        private
        int                         _currentFixedDocumentWriterRef;
 
        private
        int                         _currentFixedPageWriterRef;
 
        private
        XmlTextWriter               _currentDSWriter;
 
        private
        XmlWriter                   _currentFDWriter;
 
        private
        XmlWriter                   _currentFPWriter;
 
        private
        int                         _currentXpsFontRef;
 
        private
        int                         _currentXpsImageRef;
 
        private
        int                         _currentXpsColorContextRef;
 
        private
        int                         _currentXpsResourceDictionaryRef;
 
        private
        XpsResourceStream           _fontResourceStream;
 
        private
        XpsResourceStream           _imageResourceStream;
 
        private
        XpsResourceStream           _colorContextResourceStream;
 
        private
        XpsResourceStream           _resourceDictionaryResourceStream;
 
        private
        ResourceAcquireMode         _fontAcquireMode;
 
 
        //
        // ------------------------- Extra Page Resources -------------------
        //
        private
        IList<String>                _linkTargetStream;
 
        private
        StringWriter                _pageStream;
 
        private
        StringWriter                _resourceStream;
 
        private
        StringWriter                _resourceDictionaryStream;
 
        private
        System.Xml.XmlWriter        _pageXmlWriter;
 
        private
        System.Xml.XmlWriter        _resourceXmlWriter;
 
        private
        System.Xml.XmlWriter        _resourceDictionaryXmlWriter;
 
        private
        PrintTicket                 _documentSequencePrintTicket;
 
        private
        PrintTicket                 _documentPrintTicket;
 
        private
        PrintTicket                 _pagePrintTicket;
 
        private
        Hashtable                   _fontsCache;
 
        private
        XpsResourcePolicy         _resourcePolicy;
 
 
        internal enum ResourceAcquireMode
        {
            NoneAcquired     = 0,
            SingleAcquired   = 1,
            MultipleAcquired = 2
        };
 
        #endregion Private Data
    };
}