MapPathBasedVirtualPathProvider.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Hosting / MapPathBasedVirtualPathProvider.cs / 1305376 / MapPathBasedVirtualPathProvider.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * Implementation of VirtualPathProvider based on the metabase and the standard 
 * file system.  This is what ASP.NET uses by default.
 */ 

namespace System.Web.Hosting {

using System; 
using System.IO;
using System.Collections; 
using System.Collections.Specialized; 
using System.Globalization;
using System.Configuration; 
using System.Web.Util;
using System.Web.Configuration;
using System.Web.Caching;
using System.Web.Compilation; 
using Util=System.Web.UI.Util;
using System.Security.Permissions; 
using System.Web.Security; 

internal class MapPathBasedVirtualPathProvider: VirtualPathProvider { 

    public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) {

        HashCodeCombiner hashCodeCombiner = new HashCodeCombiner(); 

        // Calculate the hash based on the time stamps of all the virtual paths 
        foreach (string virtualDependency in virtualPathDependencies) { 
            string physicalDependency = HostingEnvironment.MapPathInternal(virtualDependency);
            hashCodeCombiner.AddFile(physicalDependency); 
        }

        return hashCodeCombiner.CombinedHashString;
    } 

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) { 
 
        if (virtualPathDependencies == null)
            return null; 

        StringCollection physicalDependencies = null;

        // Get the list of physical dependencies 
        foreach (string virtualDependency in virtualPathDependencies) {
            string physicalDependency = HostingEnvironment.MapPathInternal(virtualDependency); 
 
            if (physicalDependencies == null)
                physicalDependencies = new StringCollection(); 

            physicalDependencies.Add(physicalDependency);
        }
 
        if (physicalDependencies == null)
            return null; 
 
        // Copy the list of physical dependencies into an array
        string[] physicalDependenciesArray = new string[physicalDependencies.Count]; 
        physicalDependencies.CopyTo(physicalDependenciesArray, 0);

        return new CacheDependency(0, physicalDependenciesArray, utcStart);
    } 

    private string CreateCacheKey(bool isFile, string physicalPath) { 
        // Need different prefixes for file/directory lookups 
        if (isFile)
            return CacheInternal.PrefixMapPathVPPFile + physicalPath; 
        else
            return CacheInternal.PrefixMapPathVPPDir + physicalPath;
    }
 
    private bool CacheLookupOrInsert(string virtualPath, bool isFile) {
        string physicalPath = HostingEnvironment.MapPathInternal(virtualPath); 
        bool doNotCache = CachedPathData.DoNotCacheUrlMetadata; 
        string cacheKey = null;
 
        if (!doNotCache) {
            cacheKey = CreateCacheKey(isFile, physicalPath);
            // tri-state:
            //       * null means it's not cached 
            //       * true means it's cached and it exists
            //       * false means it's cached and it doesn't exist 
            bool? cacheValue = HttpRuntime.CacheInternal[cacheKey] as bool?; 
            if (cacheValue != null) {
                return cacheValue.Value; 
            }
        }

        bool exists = (isFile) ? File.Exists(physicalPath) : Directory.Exists(physicalPath); 

        if (doNotCache) { 
            return exists; 
        }
 
        // Setup a cache entry for this so we don't hit the file system every time
        CacheDependency dep = null;
        // Code based on similar logic from FileAuthorizationModule.
        // If file does not exist, but it's path is beneath the app root, we will cache it and 
        // use the first existing directory as the cache depenedency path.  If it does not exist
        // and it's not beneath the app root, we cannot cache it. 
        string existingDir = (exists) ? physicalPath : FileUtil.GetFirstExistingDirectory(AppRoot, physicalPath); 
        if (existingDir != null) {
            dep = new CacheDependency(existingDir); 
            TimeSpan slidingExp = CachedPathData.UrlMetadataSlidingExpiration;
            HttpRuntime.CacheInternal.UtcInsert(cacheKey, exists, dep, Cache.NoAbsoluteExpiration, slidingExp);
        }
 
        return exists;
    } 
 
    private static string _AppRoot;
    private static string AppRoot { 
        get {
            string appRoot = _AppRoot;
            if (appRoot == null) {
                InternalSecurityPermissions.AppPathDiscovery.Assert(); 
                appRoot = Path.GetFullPath(HttpRuntime.AppDomainAppPathInternal);
                appRoot = FileUtil.RemoveTrailingDirectoryBackSlash(appRoot); 
                _AppRoot = appRoot; 
            }
            return appRoot; 
        }
    }

    public override bool FileExists(string virtualPath) { 
        return CacheLookupOrInsert(virtualPath, true);
    } 
 
    public override bool DirectoryExists(string virtualDir) {
        return CacheLookupOrInsert(virtualDir, false); 
    }

    public override VirtualFile GetFile(string virtualPath) {
        return new MapPathBasedVirtualFile(virtualPath); 
    }
 
    public override VirtualDirectory GetDirectory(string virtualDir) { 
        return new MapPathBasedVirtualDirectory(virtualDir);
    } 
}

internal class MapPathBasedVirtualFile: VirtualFile {
 
    private string _physicalPath;
    private FindFileData _ffd; 
 
    internal MapPathBasedVirtualFile(string virtualPath) : base(virtualPath) { }
 
    internal MapPathBasedVirtualFile(string virtualPath, string physicalPath,
        FindFileData ffd) : base(virtualPath) {

        _physicalPath = physicalPath; 
        _ffd = ffd;
    } 
 
    private void EnsureFileInfoObtained() {
 
        // Get the physical path and FindFileData on demand
        if (_physicalPath == null) {
            Debug.Assert(_ffd == null);
            _physicalPath = HostingEnvironment.MapPathInternal(VirtualPath); 
            FindFileData.FindFile(_physicalPath, out _ffd);
        } 
    } 

    public override string Name { 
        get {
            EnsureFileInfoObtained();

            // If for whatever reason we couldn't get the FindFileData, just call the base (VSWhidbey 501294) 
            if (_ffd == null)
                return base.Name; 
 
            return _ffd.FileNameLong;
        } 
    }

    public override Stream Open() {
        EnsureFileInfoObtained(); 

        TimeStampChecker.AddFile(VirtualPath, _physicalPath); 
 
        return new FileStream(_physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
    } 

    internal string PhysicalPath {
        get {
            EnsureFileInfoObtained(); 
            return _physicalPath;
        } 
    } 
}
 
internal class MapPathBasedVirtualDirectory: VirtualDirectory {

    public MapPathBasedVirtualDirectory(string virtualPath) : base(virtualPath) { }
 
    public override IEnumerable Directories {
        get { 
            return new MapPathBasedVirtualPathCollection( 
                System.Web.VirtualPath.CreateNonRelative(VirtualPath), RequestedEntryType.Directories);
        } 
    }

    public override IEnumerable Files {
        get { 
            return new MapPathBasedVirtualPathCollection(
                System.Web.VirtualPath.CreateNonRelative(VirtualPath), RequestedEntryType.Files); 
        } 
    }
 
    public override IEnumerable Children {
        get {
            return new MapPathBasedVirtualPathCollection(
                System.Web.VirtualPath.CreateNonRelative(VirtualPath), RequestedEntryType.All); 
        }
    } 
} 

internal enum RequestedEntryType { 
    Files,
    Directories,
    All
} 

internal class MapPathBasedVirtualPathCollection: MarshalByRefObject, IEnumerable { 
 
    private VirtualPath _virtualPath;
    private RequestedEntryType _requestedEntryType; 

    internal MapPathBasedVirtualPathCollection(VirtualPath virtualPath, RequestedEntryType requestedEntryType) {
        _virtualPath = virtualPath;
        _requestedEntryType = requestedEntryType; 
    }
 
    public override Object InitializeLifetimeService(){ 
        return null; // never expire lease
    } 

    IEnumerator IEnumerable.GetEnumerator() {
        return new MapPathBasedVirtualPathEnumerator(_virtualPath, _requestedEntryType);
    } 
}
 
internal class MapPathBasedVirtualPathEnumerator : MarshalByRefObject, IEnumerator, IDisposable { 
    VirtualPath              _virtualPath;           // virtual path we are enumerating
    Hashtable                _exclude;               // names of files and dirs to exclude 
    Hashtable                _virtualPaths;          // names of virtual directories to include
    IEnumerator              _fileEnumerator;        // the physical file enumerator
    IEnumerator              _virtualEnumerator;     // the virtual file enumerator
    bool                     _useFileEnumerator;     // use the file enumerator 
    RequestedEntryType       _requestedEntryType;
    ProcessHostServerConfig  _processHostServerConfig; // only used with ProcessHostServerConfig 
 
    internal MapPathBasedVirtualPathEnumerator(VirtualPath virtualPath, RequestedEntryType requestedEntryType) {
 
        if (virtualPath.IsRelative) {
            throw new ArgumentException(SR.GetString(SR.Invalid_app_VirtualPath), "virtualPath");
        }
 
        _virtualPath = virtualPath;
        _requestedEntryType = requestedEntryType; 
 
        string physicalPath;
        if (!ServerConfig.UseServerConfig) { 
            // Use the hosting environment to map the virtual path
            physicalPath = _virtualPath.MapPathInternal();
        }
        else { 
            IServerConfig serverConfig = ServerConfig.GetInstance();
            _processHostServerConfig = serverConfig as ProcessHostServerConfig; 
 
            // Use serverConfig to map the virtual path
            physicalPath = serverConfig.MapPath(null, _virtualPath); 

            if (_requestedEntryType != RequestedEntryType.Files) {
                // For MetabaseServerConfig, get the subdirs that are not in the application, and add them to the exclude list.
                if (_processHostServerConfig == null) { 
                    string [] virtualSubdirsNotInApp = serverConfig.GetVirtualSubdirs(_virtualPath, false);
                    if (virtualSubdirsNotInApp != null) { 
                        _exclude = new Hashtable(StringComparer.OrdinalIgnoreCase); 
                        foreach (string subdir in virtualSubdirsNotInApp) {
                            _exclude[subdir] = subdir; 
                        }
                    }
                }
 
                // Get subdirs that are virtual directories, and record their physical mappings.
                // Ignore the virtualPaths if we only need files, since it only contains directories 
                string [] virtualSubdirsInApp = serverConfig.GetVirtualSubdirs(_virtualPath, true); 
                if (virtualSubdirsInApp != null) {
                    _virtualPaths = new Hashtable(StringComparer.OrdinalIgnoreCase); 
                    foreach (string subdir in virtualSubdirsInApp) {
                        VirtualPath subpath = _virtualPath.SimpleCombineWithDir(subdir);
                        string subPhysicalPath = serverConfig.MapPath(null, subpath);
                        if (FileUtil.DirectoryExists(subPhysicalPath)) { 
                            _virtualPaths[subdir] = new MapPathBasedVirtualDirectory(subpath.VirtualPathString);
                        } 
                    } 

                    // Create enumerator for the virtual paths 
                    _virtualEnumerator = _virtualPaths.Values.GetEnumerator();
                }
            }
        } 

        // Create an enumerator for the physical files and directories at this path 
        _fileEnumerator = FileEnumerator.Create(physicalPath); 

        // Reset the enumerator. Note that we don't support the Reset method. 
        _useFileEnumerator = false;
    }

    public override Object InitializeLifetimeService(){ 
        return null; // never expire lease
    } 
 
    // Dispose the file enumerator
    void IDisposable.Dispose() { 
        if (_fileEnumerator != null) {
            ((IDisposable)_fileEnumerator).Dispose();
            _fileEnumerator = null;
        } 
    }
 
    // First MoveNext() with the file enumerator, then with the virtual directories 
    // that have not been enumerated.
    bool IEnumerator.MoveNext() { 
        bool more = false;

        if (_virtualEnumerator != null)
            more = _virtualEnumerator.MoveNext(); 

        if (!more) { 
            _useFileEnumerator = true; 
            for (;;) {
                more = _fileEnumerator.MoveNext(); 
                if (!more)
                    break;

                FileData fileData = (FileData) _fileEnumerator.Current; 

                // Ignore all hidden files and directories 
                if (fileData.IsHidden) 
                    continue;
 
                // Ignore it if it's not of the right type (i.e. directory vs file)
                if (fileData.IsDirectory) {
                    if (_requestedEntryType == RequestedEntryType.Files)
                        continue; 

                    // Check whether the file is the same as a virtual path 
                    // that we have already enumerated 
                    string name = fileData.Name;
                    if (_virtualPaths != null && _virtualPaths.Contains(name)) 
                        continue;

                    // Check whether the file should be excluded because it is
                    // not part of this app. 

                    // MetabaseServerConfig 
                    if (_exclude != null && _exclude.Contains(name)) 
                        continue;
 
                    // ProcessHostServerConfig
                    if (_processHostServerConfig != null && !_processHostServerConfig.IsWithinApp(UrlPath.SimpleCombine(_virtualPath.VirtualPathString, name))) {
                        continue;
                    } 
                }
                else { 
                    if (_requestedEntryType == RequestedEntryType.Directories) 
                        continue;
                } 

                // We've found the file
                break;
            } 
        }
 
        return more; 
    }
 
    internal VirtualFileBase Current {
        get {
            if (_useFileEnumerator) {
                FileData fileData = (FileData) _fileEnumerator.Current; 
                VirtualPath childVirtualPath;
                if (fileData.IsDirectory) { 
                    childVirtualPath = _virtualPath.SimpleCombineWithDir(fileData.Name); 
                    return new MapPathBasedVirtualDirectory(childVirtualPath.VirtualPathString);
                } 
                else {
                    childVirtualPath = _virtualPath.SimpleCombine(fileData.Name);
                    FindFileData ffd = fileData.GetFindFileData();
                    return new MapPathBasedVirtualFile(childVirtualPath.VirtualPathString, fileData.FullName, ffd); 
                }
            } 
            else { 
                return (VirtualFileBase) _virtualEnumerator.Current;
            } 
        }
    }

    object IEnumerator.Current { 
        get { return Current; }
    } 
 
    void IEnumerator.Reset() {
        // We don't support reset, though it would be easy to add if needed 
        throw new InvalidOperationException();
    }
}
 
#if NO
// TEST CODE 
 
public class TestEnum {
 
    public static void Enum(HttpResponse response) {
        VirtualDirectory vdir = HostingEnvironment.VirtualPathProvider.GetDirectory(
            "~");
        EnumRecursive(response, vdir); 
    }
 
    static void EnumRecursive(HttpResponse response, VirtualDirectory vdir) { 
        foreach (VirtualFile vfile in vdir.Files) {
            response.Write("File: " + vfile.VirtualPath + "
\r\n"); } foreach (VirtualDirectory childVdir in vdir.Directories) { response.Write("Directory: " + childVdir.VirtualPath + "
\r\n"); EnumRecursive(response, childVdir); } } } #endif } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.

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