DocumentManager.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 / TrustUi / MS / Internal / documents / Application / DocumentManager.cs / 1 / DocumentManager.cs

                            //------------------------------------------------------------------------------ 
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved. 
//
//  
/// Exposes the basic operations that can be performed on documents. (Open,
/// EnableEdit, Save) 
//  
//
// History: 
//  08/28/2005: [....]: Initial implementation.
//-----------------------------------------------------------------------------

using System; 
using System.Collections.Generic;
using System.IO; 
using System.Security; 

using MS.Internal.PresentationUI; 

namespace MS.Internal.Documents.Application
{
///  
/// Exposes the basic operations that can be performed on documents. (Open,
/// EnableEdit, Save) 
///  
/// 
/// Responsibility: 
/// The class is responsible for delegating the work to the appropriate
/// controller(s) in the order needed based on document dependencies.
///
/// Design Comments: 
/// Packages are dependent on EncryptedPackages who are dependent on FileStreams
/// however all these classes are very different in function. 
/// 
/// By design once a controller has reported handling a document it will not be
/// given to other controllers.  A controller should not see documents they are 
/// not in the dependency chain for.
///
/// Example: FileController should never see RightsDocument.
///  
[FriendAccessAllowed]
internal sealed class DocumentManager 
    : ChainOfResponsiblity 
{
    #region Constructors 
    //-------------------------------------------------------------------------
    // Constructors
    //-------------------------------------------------------------------------
 
    /// 
    /// Will construct a DocumentManager using the provided controllers. 
    ///  
    /// Controllers in order of responsiblity from
    /// top to bottom. 
    internal DocumentManager(params IDocumentController[] controllers)
        : base(controllers) { }
    #endregion Constructors
 
    #region Internal Methods
    //-------------------------------------------------------------------------- 
    // Internal Methods 
    //-------------------------------------------------------------------------
 
    /// 
    /// Creates the default chain of controllers.  (PackageController,
    /// RightsController and FileController)
    ///  
    /// A DocumentManager.
    ///  
    /// This exists because of a a design compromise; see SaveAs below. 
    ///
    /// This compromise breaks encapsulation, because we have an understanding of 
    /// begin used within a navigation application.
    /// 
    internal static DocumentManager CreateDefault()
    { 
        if (_singleton == null)
        { 
            _controllers.Add(new HostedController()); 
            _controllers.Add(new PackageController());
            _controllers.Add(new RightsController()); 
            _controllers.Add(new FileController());

            _singleton = new DocumentManager(
                _controllers.ToArray()); 

            Trace.SafeWrite(Trace.File, "DocumentManager singleton created."); 
        } 

        return _singleton; 
    }

    /// 
    /// Creates the default chain of documents.  (PackageDocument, 
    /// RightsDocument and FileDocument)
    ///  
    /// A Document. 
    /// 
    /// Critical: 
    ///  - sets Document.Uri which is critical
    /// NotSafe:
    ///  - only the caller can assert that this is the source of the request
    ///  
    [SecurityCritical]
    internal static PackageDocument CreateDefaultDocument( 
        Uri source, CriticalFileToken fileToken) 
    {
        // because we have a fileToken we might be able to save 
        _canSave = true;

        PackageDocument doc = new PackageDocument(
            new RightsDocument( 
            new FileDocument(fileToken)));
 
        doc.Uri = source; 

        return doc; 
    }

    /// 
    /// Creates the default chain of documents.  (PackageDocument, 
    /// RightsDocument and FileDocument)
    ///  
    /// A Document. 
    /// 
    /// Critical: 
    ///  - call FileDocument ctor which uses stream as source
    ///  - sets Document.Uri which is critical
    /// NotSafe:
    ///  - origin of stream is known only to caller 
    ///  - only the caller can assert that this is the source of the request
    ///  
    [SecurityCritical] 
    internal static PackageDocument CreateDefaultDocument(
        Uri source, Stream stream) 
    {
        PackageDocument doc = new PackageDocument(
            new RightsDocument(
            new FileDocument(stream))); 

        doc.Uri = source; 
 
        return doc;
    } 

    /// 
    /// Allows IDocumentControllers to be properly cleaned up when created
    /// by the factory method of this class. 
    /// 
    internal static void CleanUp() 
    { 
        foreach (IDocumentController controller in _controllers)
        { 
            IDisposable disposable = controller as IDisposable;

            if (disposable != null)
            { 
                disposable.Dispose();
            } 
        } 
    }
 
    /// 
    /// Will enable editing for the document.
    /// 
    /// A document. 
    internal void EnableEdit(Document document)
    { 
        if (document == null) 
        {
            document = _current; 
        }

        if (!_isEditEnabled)
        { 
            _isEditEnabled = OrderByLeastDependent(DispatchEnableEdit, document);
        } 
    } 

    ///  
    /// Will open the specified document.
    /// 
    /// A document.
    /// True if the operation succeeded 
    internal bool Open(Document document)
    { 
        ThrowIfNull(document); 

        _current = document; 
        // since we just loaded the document, it is now unmodified from the saved version
        _isModified = false;
        return OrderByLeastDependent(DispatchOpen, document);
    } 

    ///  
    /// Will save the current document to a user-specified location. 
    /// 
    /// True if the operation succeeded 
    internal bool SaveAs(Document document)
    {
        if (document == null)
        { 
            document = _current;
        } 
 
        bool result = OrderByLeastDependent(DispatchSaveAsPreperation, document);
 
        if (result)
        {
            result = OrderByMostDependent(DispatchSaveCommit, document);
        } 

        if (result) 
        { 
            // since we just saved the document, it is now unmodified from the saved version
            _isModified = false; 
            result = OrderByLeastDependent(DispatchRebind, document);
        }

        return result; 
    }
 
    ///  
    /// Will save the specified document.
    ///  
    /// A document.
    /// True if the operation succeeded
    internal bool Save(Document document)
    { 
        if (document == null)
        { 
            document = _current; 
        }
 
        bool result = OrderByLeastDependent(DispatchSavePreperation, document);

        if (result)
        { 
            result = OrderByMostDependent(DispatchSaveCommit, document);
        } 
 
        // We always Rebind even if the Commit failed -- if we fail we still
        // need to Rebind the original document. 
        OrderByLeastDependent(DispatchRebind, document);
        // since we just saved the document, it is now unmodified from the saved version
        _isModified = false;
 
        return result;
    } 
 
    /// 
    /// This event handler is called to notify us that the document was modified. 
    /// 
    /// sender of the event (not used)
    /// arguments of the event (not used)
    internal static void OnModify(Object sender, EventArgs args) 
    {
        _isModified = true; 
    } 

    ///  
    /// Forces the given document to reload.
    /// 
    /// The document
    /// True if the operation succeeded 
    internal bool Reload(Document document)
    { 
        if (document == null) 
        {
            document = _current; 
        }

        // Set IsReloadNeeded to force reloading the document
        document.IsReloadNeeded = true; 

        // Dispatch a rebind operation, which will cause a reload 
        return OrderByLeastDependent(DispatchRebind, document); 
    }
 
    #endregion Internal Methods

    #region Internal Properties
    //-------------------------------------------------------------------------- 
    // Internal Properties
    //-------------------------------------------------------------------------- 
 
    /// 
    /// Gets or sets whether saving to the source of the document may be possible. 
    /// 
    /// 
    /// Currently we only support saving when opened by a file Uri.
    ///  
    internal bool CanSave
    { 
        get 
        {
            return _canSave; 
        }
        set
        {
            _canSave = value; 
        }
    } 
 
    /// 
    /// This property returns true if the document has been modified from the 
    /// version on disk (and therefore it makes sense for the user to save it).
    /// This property combines modification information from multiple sources.
    /// 
    ///  
    /// Some changes are reflected in Package.IsDirty -- all other changes
    /// will notify us by writing to this property.  The document is considered 
    /// modified if it is modified either according to the PackageDocument or 
    /// our internal flag.
    ///  
    internal bool IsModified
    {
        get
        { 
            PackageDocument doc = _current as PackageDocument;
            // If we don't have a PackageDocument (for example, if we are viewing 
            // a read-only file), then only our internal flag is used. 
            if (doc == null || doc.Package == null)
            { 
                return _isModified;
            }
            else
            { 
                return doc.Package.IsDirty || _isModified;
            } 
        } 
    }
 
    #endregion Internal Properties

    #region Private Methods
    //------------------------------------------------------------------------- 
    // Private Methods
    //-------------------------------------------------------------------------- 
 
    /// 
    /// Invokes EnableEdit on the controller provided using the document given. 
    /// 
    /// The controller to perform the action.
    /// The document to perform it on.
    /// True if handled by controller. 
    private static bool DispatchEnableEdit
        (IDocumentController controller, Document document) 
    { 
        if ((document.Dependency != null) && (document.Dependency.Workspace == null))
        { 
            Trace.SafeWrite(
                Trace.File,
                "Skipping EnableEdit for {0} because dependent Stream is null.",
                controller); 
            return true;
        } 
        return controller.EnableEdit(document); 
    }
 
    /// 
    /// Invokes Open on the controller provided using the document given.
    /// 
    /// The controller to perform the action. 
    /// The document to perform it on.
    /// True if handled by controller. 
    private static bool DispatchOpen 
        (IDocumentController controller, Document document)
    { 
        if ((document.Dependency != null) && (document.Dependency.Source == null))
        {
            Trace.SafeWrite(
                Trace.File, 
                "Skipping Open for {0} because dependent Stream is null.",
                controller); 
            return true; 
        }
        return controller.Open(document); 
    }

    /// 
    /// Invokes Rebind on the controller provided using the document given. 
    /// 
    /// The controller to perform the action. 
    /// The document to perform it on. 
    /// True if handled by controller.
    private static bool DispatchRebind 
    (IDocumentController controller, Document document)
    {
        if ((document.Dependency != null) && (document.Dependency.Source == null))
        { 
            Trace.SafeWrite(
                Trace.File, 
                "Skipping Rebind for {0} because dependent Stream is null.", 
                controller);
            return true; 
        }
        return controller.Rebind(document);
    }
 
    /// 
    /// Invokes SaveAsPreperation on the controller provided using the document 
    /// given. 
    /// 
    /// The controller to perform the action. 
    /// The document to perform it on.
    /// True if handled by controller.
    private static bool DispatchSaveAsPreperation
        (IDocumentController controller, Document document) 
    {
        if ((document.Dependency != null) && (document.Dependency.Destination == null)) 
        { 
            Trace.SafeWrite(
                Trace.File, 
                "Skipping SaveAsPreperation for {0} because dependent Stream is null.",
                controller);
            return true;
        } 
        return controller.SaveAsPreperation(document);
    } 
 
    /// 
    /// Invokes SaveCommit on the controller provided using the document given. 
    /// 
    /// The controller to perform the action.
    /// The document to perform it on.
    /// True if handled by controller. 
    private static bool DispatchSaveCommit
        (IDocumentController controller, Document document) 
    { 
        if ((document.Dependency != null) && (document.Dependency.Destination == null))
        { 
            Trace.SafeWrite(
                Trace.File,
                "Skipping SaveCommit for {0} because dependent Stream is null.",
                controller); 
            return true;
        } 
        return controller.SaveCommit(document); 
    }
 
    /// 
    /// Invokes SavePreperation on the controller provided using the document
    /// given.
    ///  
    /// The controller to perform the action.
    /// The document to perform it on. 
    /// True if handled by controller. 
    private static bool DispatchSavePreperation
        (IDocumentController controller, Document document) 
    {
        if ((document.Dependency != null) && (document.Dependency.Destination == null))
        {
            Trace.SafeWrite( 
                Trace.File,
                "Skipping SavePreperation for {0} because dependent Stream is null.", 
                controller); 
            return true;
        } 
        return controller.SavePreperation(document);
    }

    ///  
    /// Invokes the action from the top of the document dependency chain to the
    /// bottom, for each provider under it in the chain. 
    ///  
    /// 
    /// OrderByMostDependent is implement in the ChainOfDependency 
    /// (not a GoF pattern), it walks the tree of dependencies in this case the
    /// most dependent would be first.  The Chain of Responsiblity pattern is
    /// invoke by the inherited member 'Dispatch' which is called for each
    /// dependency. 
    /// 
    /// The action to perform. 
    /// The document to perform it on. 
    private bool OrderByMostDependent(DispatchDelegate action, Document document)
    { 
        return ChainOfDependencies.OrderByMostDependent(
            document,
            delegate(Document member)
            { 
                return this.Dispatch(delegate(
                    IDocumentController controller, 
                    Document subject) 
                {
                    return action(controller, subject); 
                },
                member);
            });
    } 

    ///  
    /// Invokes the action from the bottom of the document dependency chain up 
    /// to the top, for each provider under it in the chain.
    ///  
    /// 
    /// OrderByLeastDependent is implement in the ChainOfDependency
    /// (not a GoF pattern), it walks the tree of dependencies in this case the
    /// least dependent would be first.  The Chain of Responsiblity pattern is 
    /// invoke by the inherited member 'Dispatch' which is called for each
    /// dependency. 
    ///  
    /// The action to perform.
    /// The document to perform it on. 
    private bool OrderByLeastDependent(DispatchDelegate action, Document document)
    {
        return ChainOfDependencies.OrderByLeastDependent(
            document, 
            delegate(Document member)
            { 
                return this.Dispatch(delegate( 
                    IDocumentController controller,
                    Document subject) 
                {
                    return action(controller, subject);
                },
                member); 
            });
    } 
 
    /// 
    /// Will throw if the document is null. 
    /// 
    /// 
    /// The document to validate.
    private static void ThrowIfNull(Document document) 
    {
        if (document == null) 
        { 
            throw new ArgumentNullException("document");
        } 
    }
    #endregion Private Methods

    #region Private Delegates 
    //-------------------------------------------------------------------------
    // Private Delegates 
    //------------------------------------------------------------------------- 

    ///  
    /// Defines the delegate for actions invoked by DocumentManager.
    /// 
    /// The controller to perform the action.
    /// The document to perform it on. 
    /// True if handled by controller.
    private delegate bool DispatchDelegate( 
        IDocumentController controller, Document document); 
    #endregion Private Delegates
 
    #region Private Fields
    //-------------------------------------------------------------------------
    // Private Fields
    //-------------------------------------------------------------------------- 

    // Fields below simply prevents undesired user experience, they do not 
    // impact security constraints nor are they used as protection 

    private static Document _current; 
    private static DocumentManager _singleton;
    private static bool _canSave;
    private static bool _isEditEnabled;
    private static bool _isModified; 
    private static List _controllers =
        new List(); 
    #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