//****************************************************************************************************** // EmbeddedResourceProvider.cs - Gbtc // // Copyright © 2016, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this // file except in compliance with the License. You may obtain a copy of the License a // // http://opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 08/04/2016 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Web.Caching; using System.Web.Compilation; using System.Web.Hosting; using GSF.Reflection; namespace GSF.Web.Embedded { /// /// Represents a that allows access to embedded resources. /// /// /// /// This provider responds to requests for embedded resources when the virtual path begins with an "@", e.g., /// http://localhost/@GSF.Web.Model.Scripts.gsf.web.client.js /// /// /// To use, add the following to the Global.asax.cs Application_Start function: /// /// // Add additional virtual path provider to allow access to embedded resources /// EmbeddedResourceProvider.Register(); /// /// Then add the namespace paths to the embedded resources for which you need access to the Web.config <system.webServer> section: /// /// <system.webServer> /// <handlers> /// <!-- Add embedded resource handler for GSF script resources using slash delimiters --> /// <add name="EmbeddedResourceHandler-GSFScripts" path="@GSF/Web/Model/Scripts/*" verb="*" type="System.Web.StaticFileHandler" allowPathInfo="true" /> /// <!-- Add embedded resource handler for GSF view resources using slash delimiters --> /// <add name="EmbeddedResourceHandler-GSFViews" path="@GSF/Web/Model/Views/*" verb="*" type="System.Web.StaticFileHandler" allowPathInfo="true" /> /// <!-- Add embedded resource handler for GSF handler resources using slash delimiters --> /// <add name="EmbeddedResourceHandler-GSFHandlers" path="@GSF/Web/Model/Handlers/*" verb="*" type="System.Web.UI.SimpleHandlerFactory" allowPathInfo="true" /> /// <!-- Add embedded resource handler for fully qualified type names using dot delimiters (this should be defined last) --> /// <add name="EmbeddedResourceHandler-FQName" path="@*" verb="*" type="System.Web.StaticFileHandler" allowPathInfo="true" /> /// </handlers> /// </system.webServer> /// /// /// public class EmbeddedResourceProvider : VirtualPathProvider { #region [ Members ] // Nested Types private class EmbeddedResource : VirtualFile { public EmbeddedResource(string virtualPath) : base(virtualPath) { } public override Stream Open() => WebExtensions.OpenEmbeddedResourceStream(ParseResourceNameFromVirtualPath(VirtualPath)); } #endregion #region [ Methods ] /// /// Gets a value that indicates whether a file exists in the virtual file system. /// /// true if the file exists in the virtual file system; otherwise, false. /// The path to the virtual file. /// /// Any virtual path that begins with an @ symbol is assumed to be an embedded resource where /// the path represents the namespace hierarchy in either slash or dot notation. /// public override bool FileExists(string virtualPath) { return WebExtensions.EmbeddedResourceExists(ParseResourceNameFromVirtualPath(virtualPath)) || Previous.FileExists(virtualPath); } /// /// Gets a file from the virtual file system. /// /// An implementation of the class that represents a file in the virtual file system. /// The path to the virtual file. public override VirtualFile GetFile(string virtualPath) { return WebExtensions.EmbeddedResourceExists(ParseResourceNameFromVirtualPath(virtualPath)) ? new EmbeddedResource(virtualPath) : Previous.GetFile(virtualPath); } /// /// Gets a value that indicates whether a directory exists in the virtual file system. /// /// true if the directory exists in the virtual file system; otherwise, false. /// The path to the virtual directory. public override bool DirectoryExists(string virtualDir) { // Assume any given resource path exists - GetFile will validate full namespace for resource return IsEmbeddedResource(virtualDir) || Previous.DirectoryExists(virtualDir); } /// /// Gets a virtual directory from the virtual file system. /// /// A descendant of the class that represents a directory in the virtual file system. /// The path to the virtual directory. public override VirtualDirectory GetDirectory(string virtualDir) { return Previous.GetDirectory(virtualDir); } /// /// Creates a cache dependency based on the specified virtual paths. /// /// A object for the specified virtual resources. /// The path to the primary virtual resource. /// An array of paths to other resources required by the primary virtual resource. /// The UTC time at which the virtual resources were read. public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) { return IsEmbeddedResource(virtualPath) ? null : Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart); } #endregion #region [ Static ] /// /// Registers the within a . /// /// /// This function will properly register the even when being run from /// within a pre-compiled web application. /// public static void Register() { #if MONO HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedResourceProvider()); #else if (BuildManager.IsPrecompiledApp) { // HACK: Call internal registration function for virtual path provider in pre-compiled web application Type hostingEnvironment = AssemblyInfo.FindType("System.Web.Hosting.HostingEnvironment"); if ((object)hostingEnvironment == null) throw new InvalidOperationException("Failed to register EmbeddedResourceProvider: could not find type \"System.Web.Hosting.HostingEnvironment\"."); MethodInfo internalRegisterVirtualPathProvider = hostingEnvironment.GetMethod("RegisterVirtualPathProviderInternal", BindingFlags.NonPublic | BindingFlags.Static); if ((object)internalRegisterVirtualPathProvider == null) throw new InvalidOperationException("Failed to register EmbeddedResourceProvider: could not find internal static method \"System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProviderInternal()\"."); internalRegisterVirtualPathProvider.Invoke(null, new object[] { new EmbeddedResourceProvider() }); } else { HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedResourceProvider()); } #endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static string ParseResourceNameFromVirtualPath(string virtualPath) { return virtualPath.Substring(virtualPath.IndexOf('@') + 1).Replace('/', '.'); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsEmbeddedResource(string virtualPath) { return virtualPath.StartsWith("@") || virtualPath.Contains("/@"); } #endregion } }