PackageStore.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / IO / Packaging / PackageStore.cs / 1 / PackageStore.cs

                            //------------------------------------------------------------------------------ 
//
//  Copyright (c) Microsoft Corporation, 2005
//
//  File:          PackageStore.cs 
//
//  Description:   Collection of packages to be used with PackWebRequest. 
// 
// History:
//  07/25/2005: [....]: Created. 
//-----------------------------------------------------------------------------

using System;
using System.Collections; 
using System.Collections.Specialized;
using System.IO; 
using System.IO.Packaging; 
using System.Security;
using System.Security.Permissions; 
using System.Windows.Navigation;

using MS.Internal.PresentationCore;     // for ExceptionStringTable
 
namespace System.IO.Packaging
{ 
 
    // Note: we purposely didn't make this class a dictionary to limit the access
    //  to the packages in the store 
    //
    /// 
    /// PackageStore: Collection of packages to be used with PackWebRequest.
    /// PackWebRequest will use a package from PackageStore if package uri matches 
    /// to obtain the requested part stream
    /// This mechanism can be used so that PackWebRequest wouldn't open a package 
    /// multiple times to load different resources from the same package. 
    /// 
    ///  
    /// Note: Packages placed in PackageStore can be used in multi threading environment if it is used in
    ///  conjunction with Xaml Parser (XmlReader.Load). It is up to an application to do proper locking on the package
    ///  when it accesses the package directly.
    /// Note: The access to the packages obtained from PackageStore is not limited (or the access level is same 
    ///  as the one that is used to do open). It is up to an application to do proper action in modifying or closing
    ///  packages. 
    ///  
    /// 
    ///     Critical:  This class serves as a deposity of packages to be re-used with PackWebRequest 
    ///      This affects where we load resources. This class is marked as SecurityCritical
    ///      to ensure that:
    ///         1. No PT code can add/get/remove custom type of Package since the platform code (PackWebRequest) will
    ///             execute the custom Package (untrusted code) 
    ///         2. Allow PT code to add/get/remove only the well-known platform Package type (trusted code): ZipPackage
    ///    TreatAsSafe: These are public methods. 
    /// 
    [SecurityCritical(SecurityCriticalScope.Everything)]
    public static class PackageStore 
    {
        static PackageStore()
        {
            _globalLock = new Object(); 
        }
 
        #region public Methods 

        // 
        /// 
        /// Retrieves a package from the store for the given Uri.
        /// 
        /// key uri 
        /// Package
        ///  
        ///  
        /// 
        /// 
        /// Demands EnvironmentPermission() if package is custom type of Package.
        /// This prevents Partially Trusted callers from performing this operation on custom type of Package.
        ///
        public static Package GetPackage(Uri uri) 
        {
            ValidatePackageUri(uri); 
 
            lock (_globalLock)
            { 
                Package package = null;

                if (_packages != null && _packages.Contains(uri))
                { 
                    package = (Package) _packages[uri];
                    DemandSecurityPermissionIfCustomPackage(package); 
                } 

                return package; 
            }
        }

        ///  
        /// Adds a uri, package pair to the package store.
        ///  
        /// key uri 
        /// package
        ///  
        /// 
        /// If a package with the uri is already in the store,it throws an exception.
        /// The package will not be automatically replaced within the store.
        ///  
        ///
        /// Demands EnvironmentPermission() if package is custom type of Package. 
        /// This prevents Partially Trusted callers from performing this operation. However, Partially Trusted callers can still 
        /// add well-known platform Package type (ZipPackage) to PackageStore.
        /// the application's PackageStore. 
        ///
        public static void AddPackage(Uri uri, Package package)
        {
            // Allow well known platform Package to be added into PackageStore under Partial Trust. 
            // Otherwise, demand Environment Permission to make sure only Full Trust app can add a custom Package
            DemandSecurityPermissionIfCustomPackage(package); 
 
            ValidatePackageUri(uri);
 
            // There are well-known package types that are only for internal use (for resource loading)
            //  (i.e. ResourceContainer - "application://" and SiteOriginContainer - "siteoforigin://"
            // Adding packages with such key uri will have no effect on PackWebRequest since
            //  they cannot be overriden. So, calling this method with such key Uris should be prevented 
            //  However, uri.Equal cannot be used here since the key Uris are used as a pack Uri form and
            //  only PackUriHelper.ComparePackUri can do the proper comparison of pack Uris. 
 
            Uri packUri = PackUriHelper.Create(uri);
 
            if (PackUriHelper.ComparePackUri(packUri, BaseUriHelper.PackAppBaseUri) == 0
                    || PackUriHelper.ComparePackUri(packUri, BaseUriHelper.SiteOfOriginBaseUri) == 0)
            {
                throw new ArgumentException(SR.Get(SRID.NotAllowedPackageUri), "uri"); 
            }
 
            if (package == null) 
            {
                throw new ArgumentNullException("package"); 
            }

            lock (_globalLock)
            { 
                if (_packages == null)
                { 
                    _packages = new HybridDictionary(2); 
                }
 
                if (_packages.Contains(uri))
                {
                    throw new InvalidOperationException(SR.Get(SRID.PackageAlreadyExists));
                } 

                _packages.Add(uri, package); 
            } 
        }
 
        /// 
        /// Removes a uri, package pair from the package store.
        /// 
        /// key uri 
        /// 
        ///  
        ///  
        ///
        /// Demands EnvironmentPermission() if package is custom type of Package. 
        /// This prevents Partially Trusted callers from performing this operation on custom type of Package.
        ///
        public static void RemovePackage(Uri uri)
        { 
            ValidatePackageUri(uri);
 
            lock (_globalLock) 
            {
                if (_packages != null) 
                {
                    DemandSecurityPermissionIfCustomPackage((Package) _packages[uri]);

                    // If the key doesn't exist, it is no op 
                    _packages.Remove(uri);
                } 
            } 
        }
 
        #endregion Public Methods

        #region Private Methods
 
        private static void ValidatePackageUri(Uri uri)
        { 
            if (uri == null) 
            {
                throw new ArgumentNullException("uri"); 
            }

            if (!uri.IsAbsoluteUri)
            { 
                throw new ArgumentException(SR.Get(SRID.UriMustBeAbsolute), "uri");
            } 
        } 

        private static void DemandSecurityPermissionIfCustomPackage(Package package) 
        {
            // Although ZipPackage is sealed and cannot be subclassed, we shouldn't depend on
            //  the "sealedness" of ZipPackage. Checking the object type is more reliable way
            //  than using "as" or "is" operator. 
            if (package != null && package.GetType() != typeof(ZipPackage))
            { 
                SecurityHelper.DemandEnvironmentPermission(); 
            }
        } 


        #endregion Private Methods
 
        #region Private Fields
 
        // We expect to have no more than 10 packages in the store 
        //  per AppDomain for our scenarios
        // ListDictionary is the best fit for this scenarios; otherwise we should be using 
        // Hashtable. HybridDictionary already has functionality of switching between
        //  ListDictionary and Hashtable depending on the size of the collection
        static private HybridDictionary _packages;
        static private Object _globalLock; 

        #endregion Private Fields 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK