//******************************************************************************************************
// 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 (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());
}
}
[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
}
}