|
using System;
using System.Collections.Concurrent;
using System.Configuration;
using System.Web;
using System.Web.Compilation;
using System.Web.Configuration;
using System.Web.Hosting;
using Microsoft.Build.Utilities;
// Helper class to use 2.0 root config as necessary. Each helper method will
// go through RuntimeConfig (the original code path), except in the
// case of building and targeting 2.0/3.5.
internal class MTConfigUtil {
private static readonly ConcurrentDictionary<Tuple<Type, VirtualPath>, ConfigurationSection> s_sections =
new ConcurrentDictionary<Tuple<Type, VirtualPath>, ConfigurationSection>();
private static readonly ConcurrentDictionary<VirtualPath, Configuration> s_configurations =
new ConcurrentDictionary<VirtualPath, Configuration>();
private static string s_machineConfigPath;
private static VirtualPath s_appVirtualPath;
// We only need to use the root config of 2.0 if we are building (and
// not during runtime) and targeting 2.0 or 3.5.
static private bool? s_useMTConfig;
static private bool UseMTConfig {
get {
if (s_useMTConfig == null) {
s_useMTConfig = BuildManagerHost.InClientBuildManager &&
(MultiTargetingUtil.IsTargetFramework20 || MultiTargetingUtil.IsTargetFramework35);
}
return s_useMTConfig.Value;
}
}
// Counterpart for RuntimeConfig.GetAppConfig().Profile;
static internal ProfileSection GetProfileAppConfig() {
if (!UseMTConfig) {
return RuntimeConfig.GetAppConfig().Profile;
}
return GetAppConfig<ProfileSection>();
}
// Counterpart for RuntimeConfig.GetAppConfig().Pages;
static internal PagesSection GetPagesAppConfig() {
if (!UseMTConfig) {
return RuntimeConfig.GetAppConfig().Pages;
}
return GetAppConfig<PagesSection>();
}
// Counterpart for RuntimeConfig.GetConfig().Pages;
static internal PagesSection GetPagesConfig() {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig().Pages;
}
return GetConfig<PagesSection>();
}
// Counterpart for RuntimeConfig.GetConfig(string).Pages
static internal PagesSection GetPagesConfig(string vpath) {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig(vpath).Pages;
}
return GetConfig<PagesSection>(vpath);
}
// Counterpart for RuntimeConfig.GetConfig(VirtualPath).Pages
static internal PagesSection GetPagesConfig(VirtualPath vpath) {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig(vpath).Pages;
}
return GetConfig<PagesSection>(vpath);
}
// Counterpart for RuntimeConfig.GetConfig(HttpContext).Pages
static internal PagesSection GetPagesConfig(HttpContext context) {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig(context).Pages;
}
return GetConfig<PagesSection>(context);
}
// Counterpart for RuntimeConfig.GetConfig().Compilation
static internal CompilationSection GetCompilationConfig() {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig().Compilation;
}
return GetConfig<CompilationSection>();
}
// Counterpart for RuntimeConfig.GetAppConfig().Compilation
static internal CompilationSection GetCompilationAppConfig() {
if (!UseMTConfig) {
return RuntimeConfig.GetAppConfig().Compilation;
}
return GetAppConfig<CompilationSection>();
}
// Counterpart for RuntimeConfig.GetConfig(string).Compilation
static internal CompilationSection GetCompilationConfig(string vpath) {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig(vpath).Compilation;
}
return GetConfig<CompilationSection>(vpath);
}
// Counterpart for RuntimeConfig.GetConfig(VirtualPath).Compilation
static internal CompilationSection GetCompilationConfig(VirtualPath vpath) {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig(vpath).Compilation;
}
return GetConfig<CompilationSection>(vpath);
}
// Counterpart for RuntimeConfig.GetConfig(HttpContext).Compilation
static internal CompilationSection GetCompilationConfig(HttpContext context) {
if (!UseMTConfig) {
return RuntimeConfig.GetConfig(context).Compilation;
}
return GetConfig<CompilationSection>(context);
}
// Counterpart to RuntimeConfig.GetConfig()
static private S GetConfig<S>() where S : ConfigurationSection {
HttpContext context = HttpContext.Current;
if (context != null) {
return GetConfig<S>(context);
}
else {
return GetAppConfig<S>();
}
}
// Counterpart to RuntimeConfig.GetAppConfig()
static private S GetAppConfig<S>() where S : ConfigurationSection {
return GetConfig<S>((VirtualPath) null);
}
// Counterpart to RuntimeConfig.GetConfig(HttpContext)
static private S GetConfig<S>(HttpContext context) where S : ConfigurationSection {
return GetConfig<S>(context.ConfigurationPath);
}
// Counterpart to RuntimeConfig.GetConfig(string)
static private S GetConfig<S>(string vpath) where S : ConfigurationSection{
return GetConfig<S>(VirtualPath.CreateNonRelativeAllowNull(vpath));
}
// Counterpart to RuntimeConfig.GetConfig(VirtualPath)
static private S GetConfig<S>(VirtualPath vpath) where S : ConfigurationSection {
Tuple<Type, VirtualPath> key = new Tuple<Type, VirtualPath>(typeof(S), vpath);
ConfigurationSection result;
if (!s_sections.TryGetValue(key, out result)) {
result = GetConfigHelper<S>(vpath);
s_sections.TryAdd(key, result);
}
return result as S;
}
// Actual method performing to work to retrieve the required ConfigurationSection.
static private S GetConfigHelper<S>(VirtualPath vpath) where S : ConfigurationSection{
string physicalPath = null;
if (vpath == null || !vpath.IsWithinAppRoot) {
// If virtual path is null or outside the application root, we use the application level config.
vpath = HostingEnvironment.ApplicationVirtualPathObject;
physicalPath = HostingEnvironment.ApplicationPhysicalPath;
}
else {
// If it is not a directory, use the directory as the vpath
if (!vpath.DirectoryExists()) {
vpath = vpath.Parent;
}
physicalPath = HostingEnvironment.MapPath(vpath);
}
Configuration config = GetConfiguration(vpath, physicalPath);
// Retrieve the specified section
if (typeof(S) == typeof(CompilationSection)) {
return config.GetSection("system.web/compilation") as S;
}
else if (typeof(S) == typeof(PagesSection)) {
return config.GetSection("system.web/pages") as S;
}
else if (typeof(S) == typeof(ProfileSection)) {
return config.GetSection("system.web/profile") as S;
}
throw new InvalidOperationException(SR.GetString(SR.Config_section_not_supported, typeof(S).FullName));
}
static private string MachineConfigPath {
get {
if (s_machineConfigPath == null) {
s_machineConfigPath = ToolLocationHelper.GetPathToDotNetFrameworkFile(@"config\machine.config", TargetDotNetFrameworkVersion.Version20);
if (string.IsNullOrEmpty(s_machineConfigPath)) {
string message = SR.GetString(SR.Downlevel_requires_35);
throw new InvalidOperationException(message);
}
}
return s_machineConfigPath;
}
}
static private Configuration GetConfiguration(VirtualPath vpath, string physicalPath) {
Configuration result;
if (!s_configurations.TryGetValue(vpath, out result)) {
result = GetConfigurationHelper(vpath, physicalPath);
s_configurations.TryAdd(vpath, result);
}
return result;
}
static private Configuration GetConfigurationHelper(VirtualPath vpath, string physicalPath) {
// Set up the configuration file map
string machineConfigPath = MachineConfigPath;
WebConfigurationFileMap fileMap = new WebConfigurationFileMap(machineConfigPath);
// Set up file maps for the current directory and parent directories up to application root
VirtualPath currentVPath = vpath;
while (currentVPath != null && currentVPath.IsWithinAppRoot) {
string vpathString = currentVPath.VirtualPathStringNoTrailingSlash;
if (physicalPath == null) {
physicalPath = HostingEnvironment.MapPath(currentVPath);
}
fileMap.VirtualDirectories.Add(vpathString, new VirtualDirectoryMapping(physicalPath, IsAppRoot(currentVPath)));
currentVPath = currentVPath.Parent;
physicalPath = null;
}
Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, vpath.VirtualPathStringNoTrailingSlash, HostingEnvironment.SiteName);
return config;
}
static private bool IsAppRoot(VirtualPath path) {
if (s_appVirtualPath == null) {
s_appVirtualPath = VirtualPath.Create(HttpRuntime.AppDomainAppVirtualPathObject.VirtualPathStringNoTrailingSlash);
}
var vpath = VirtualPath.Create(path.VirtualPathStringNoTrailingSlash);
return s_appVirtualPath.Equals(vpath);
}
}
|