Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / TrustUi / MS / Internal / documents / Application / Document.cs / 1 / Document.cs

    //------------------------------------------------------------------------------ 
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved. 
//
//  
//  Defines the common contract for all underlying documents in XpsViewer.
//  
// 
// History:
//  08/28/2005: [....]: Initial implementation. 
//-----------------------------------------------------------------------------

using System;
using System.IO; 
using System.Security;
 
namespace MS.Internal.Documents.Application 
{
///  
/// Defines the common contract for all underlying documents in XpsViewer.
/// 
/// 
/// Responsibility: 
/// This class imposes a contract which provides for:
/// 
///  - chaining dependencies 
///  - expose stream which providers may manipulate at each level
///  - disposing of resources in order of dependency 
///
/// Design Comments:
/// Packages are dependent on EncryptedPackages who are dependent on FileStreams
/// however all these classes are very different in function.  However they 
/// share a need for understanding dependencies and all use streams (some
/// consuming, some publshing and others both). 
/// 
/// Providing a chain ensures dependent operations are executed in order.
/// 
/// The design of exsiting components also requires us to define three common
/// types of streams (Source - the original data, Workspace - a type of change
/// log, Destination - the place to save changes).
/// 
/// Examples:
///  - FileController need to substitue streams as as we can not edit in 
///    place and may not be able to re-open files on some OSes (hence 
///    IsRebindNeed).
/// 
///  - Protected documents need to decrypt the underlying FileStream before
///    passing them up to the PackageDocument. (hence Source).
///
///  - As Package does not allow us to discard changes we need a seperate stream 
///    for working on packages (hence Workspace).
/// 
///  - When Protected documents have a key change (PublishLicense) they need 
///    to read from the source, and write to the destination at the same time
///    (hence Destination & IsFileCopySafe). 
/// 
internal abstract class Document : IChainOfDependenciesNode, IDisposable
{
    #region Constructors 
    //-------------------------------------------------------------------------
    // Constructors 
    //------------------------------------------------------------------------- 

    ///  
    /// Constructor allows the chaining of dependencies.
    /// 
    /// A document we are dependent on.
    internal Document(Document dependency) 
    {
        _dependency = dependency; 
    } 
    #endregion Constructors
 
    #region Finalizers
    //--------------------------------------------------------------------------
    // Finalizers
    //------------------------------------------------------------------------- 

    ~Document() 
    { 
#if DEBUG
        // our code should be explicitly disposing this is to catch bad code 
        AssertIfNotDisposed();
#endif
        this.Dispose(true);
    } 
    #endregion
 
    #region IChainOfDependenciesNode Members 
    //--------------------------------------------------------------------------
    // IChainOfDependenciesNode Members 
    //--------------------------------------------------------------------------

    /// 
    ///  
    /// 
    Document IChainOfDependenciesNode.Dependency 
    { 
        get
        { 
#if DEBUG
            ThrowIfDisposed();
#endif
            return _dependency; 
        }
    } 
    #endregion IChainOfDependenciesNode Members 

    #region IDisposable Members 
    //-------------------------------------------------------------------------
    // IDisposable Members
    //--------------------------------------------------------------------------
 
    /// 
    ///  
    ///  
    public void Dispose()
    { 
        Trace.SafeWrite(
            Trace.File,
            "{0}.Dispose called.",
            this); 
#if DEBUG
        Trace.SafeWriteIf( 
            !_isDisposed, 
            Trace.File,
            "{0} document is being disposed.", 
            this);
#endif
        this.Dispose(true);
        GC.SuppressFinalize(this); 
    }
 
    ///  
    /// 
    ///  
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        { 
#if DEBUG
            ThrowIfDisposed(); 
            _isDisposed = true; 
#endif
            if (_dependency != null) 
            {
                _dependency.Dispose();
                _dependency = null;
            } 
        }
    } 
    #endregion IDisposable Members 

    #region Internal Properties 
    //-------------------------------------------------------------------------
    // Internal Properties
    //-------------------------------------------------------------------------
 
    /// 
    /// A stream with the data for the source document. 
    ///  
    internal abstract Stream Source
    { 
        get;
    }

    ///  
    /// A stream to store working information for edits.
    ///  
    internal abstract Stream Workspace 
    {
        get; 
    }

    /// 
    /// A stream to publish the changes to when saving. 
    /// 
    internal abstract Stream Destination 
    { 
        get;
    } 

    /// 
    /// An underlying document we are dependent on.
    ///  
    internal Document Dependency
    { 
        get 
        {
#if DEBUG 
            ThrowIfDisposed();
#endif
            return _dependency;
        } 
    }
 
    ///  
    /// When true copying the data at the file level is valid.
    ///  
    internal bool IsFileCopySafe
    {
        get
        { 
#if DEBUG
            ThrowIfDisposed(); 
#endif 
            return ChainOfDependencies.GetLast(this)._isCopySafe;
        } 
        set
        {
#if DEBUG
            ThrowIfDisposed(); 
#endif
            ChainOfDependencies.GetLast(this)._isCopySafe = value; 
        } 
    }
 
    /// 
    /// When true, the destination file is exactly identical to the source file
    /// byte-for-byte.
    ///  
    /// 
    /// Critical for set: 
    ///  - can be used for security decisions to determine what actions we 
    ///    perform on the destination file
    ///  
    internal bool IsDestinationIdenticalToSource
    {
        get
        { 
#if DEBUG
            ThrowIfDisposed(); 
#endif 
            return ChainOfDependencies.GetLast(this)._isDestinationIdenticalToSource.Value;
        } 

        [SecurityCritical]
        set
        { 
#if DEBUG
            ThrowIfDisposed(); 
#endif 
            ChainOfDependencies.GetLast(this)._isDestinationIdenticalToSource.Value = value;
        } 
    }

    /// 
    /// When true the source data has changed and we should rebind. 
    /// 
    internal bool IsRebindNeeded 
    { 
        get
        { 
#if DEBUG
            ThrowIfDisposed();
#endif
            return ChainOfDependencies.GetLast(this)._isRebindNeeded; 
        }
        set 
        { 
#if DEBUG
            ThrowIfDisposed(); 
#endif
            ChainOfDependencies.GetLast(this)._isRebindNeeded = value;
        }
    } 

    ///  
    /// When true the source location has changed and we should reload. 
    /// 
    internal bool IsReloadNeeded 
    {
        get
        {
#if DEBUG 
            ThrowIfDisposed();
#endif 
            return ChainOfDependencies.GetLast(this)._isReloadNeeded; 
        }
        set 
        {
#if DEBUG
            ThrowIfDisposed();
#endif 
            ChainOfDependencies.GetLast(this)._isReloadNeeded = value;
        } 
    } 

    ///  
    /// The location of this document.
    /// 
    ///
    /// Critical: 
    ///  - this is the location that this document represents
    ///  - may contain path information which we do not want to leak 
    /// 
    internal Uri Uri
    { 
        [SecurityCritical]
        get
        {
#if DEBUG 
            ThrowIfDisposed();
#endif 
            return ChainOfDependencies.GetLast(this)._uri.Value; 
        }
 
        [SecurityCritical]
        set
        {
#if DEBUG 
            ThrowIfDisposed();
#endif 
            ChainOfDependencies.GetLast(this)._uri = new SecurityCriticalData(value); 
        }
    } 

    #endregion Internal Properties

    #region Private Methods 
    //-------------------------------------------------------------------------
    // Private Methods 
    //-------------------------------------------------------------------------- 
#if DEBUG
    ///  
    /// Will assert if any documents are left undisposed in the application
    /// domain.
    /// 
    private void AssertIfNotDisposed() 
    {
        Invariant.Assert( 
            _isDisposed, 
            string.Format(
                System.Globalization.CultureInfo.CurrentCulture, 
                "{0} was not disposed.",
                this));
    }
 
    /// 
    /// Will throw if the object has been disposed. 
    ///  
    /// 
    private void ThrowIfDisposed() 
    {
        if (_isDisposed)
        {
            throw new ObjectDisposedException(this.GetType().Name); 
        }
    } 
#endif 
    #endregion Private Methods
 
    #region Private Fields
    //-------------------------------------------------------------------------
    // Private Fields
    //-------------------------------------------------------------------------- 

    /// 
    /// Critical: 
    ///  - this is the location that this document represents which shouldn't
    ///    be disclosed. 
    ///
    private SecurityCriticalData _uri;

    private bool _isCopySafe = true; 

    ///  
    ///  Critical for set: 
    ///   - can be used for security decisions to determine what actions we
    ///     perform on the destination file 
    /// 
    private SecurityCriticalDataForSet _isDestinationIdenticalToSource;
    private bool _isRebindNeeded;
    private bool _isReloadNeeded; 

    private Document _dependency; 
 
#if DEBUG
    private bool _isDisposed; 
#endif
    #endregion Private Fields
}
} 

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