371 lines
13 KiB
C#
371 lines
13 KiB
C#
|
//----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Activation
|
||
|
{
|
||
|
using System.Collections.Generic;
|
||
|
using System.Configuration;
|
||
|
using System.Net;
|
||
|
using System.Runtime;
|
||
|
using System.Security;
|
||
|
using System.Security.Authentication.ExtendedProtection;
|
||
|
using System.Security.Permissions;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.ServiceModel.Description;
|
||
|
using System.ServiceModel.Dispatcher;
|
||
|
|
||
|
class AspNetEnvironment
|
||
|
{
|
||
|
static readonly object thisLock = new object();
|
||
|
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
static volatile AspNetEnvironment current;
|
||
|
static bool isEnabled;
|
||
|
|
||
|
static bool? isApplicationDomainHosted;
|
||
|
|
||
|
protected AspNetEnvironment()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public static AspNetEnvironment Current
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (current == null)
|
||
|
{
|
||
|
lock (thisLock)
|
||
|
{
|
||
|
if (current == null)
|
||
|
{
|
||
|
current = new AspNetEnvironment();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return current;
|
||
|
}
|
||
|
// AspNetEnvironment.Current is set by System.ServiceModel.Activation when it is brought into memory through
|
||
|
// the ASP.Net hosting environment. It is the only "real" implementer of this class.
|
||
|
protected set
|
||
|
{
|
||
|
Fx.Assert(!isEnabled, "should only be explicitly set once");
|
||
|
Fx.Assert(value != null, "should only be set to a valid environment");
|
||
|
current = value;
|
||
|
isEnabled = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static bool Enabled
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return isEnabled;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool RequiresImpersonation
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return AspNetCompatibilityEnabled;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual bool AspNetCompatibilityEnabled
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// subclass will check AspNetCompatibility mode
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual string ConfigurationPath
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// these ideally would be replaced with public APIs
|
||
|
public virtual bool IsConfigurationBased
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// subclass will check ServiceActivationElement presence
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual string CurrentVirtualPath
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// subclass will use calculation from HostingManager.CreateService
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual string XamlFileBaseLocation
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// subclass will use calculation from HostingManager.CreateService
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual bool UsingIntegratedPipeline
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual string WebSocketVersion
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Indicates if the WebSocket module is loaded. When IIS hosted, it throws an exception when called before we determined if the module is loaded or not.
|
||
|
public bool IsWebSocketModuleLoaded
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.WebSocketVersion != null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual void AddHostingBehavior(ServiceHostBase serviceHost, ServiceDescription description)
|
||
|
{
|
||
|
// subclass will add HostedBindingBehavior
|
||
|
}
|
||
|
|
||
|
public virtual bool IsWindowsAuthenticationConfigured()
|
||
|
{
|
||
|
// subclass will check Asp.Net authentication mode
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public virtual List<Uri> GetBaseAddresses(Uri addressTemplate)
|
||
|
{
|
||
|
// subclass will provide multiple base address support
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// check if ((System.Web.Configuration.WebContext)configHostingContext).ApplicationLevel == WebApplicationLevel.AboveApplication
|
||
|
public virtual bool IsWebConfigAboveApplication(object configHostingContext)
|
||
|
{
|
||
|
// there are currently only two known implementations of HostingContext, so we are
|
||
|
// pretty much guaranteed to be hosted in ASP.Net here. However, it may not be
|
||
|
// through our BuildProvider, so we still need to do some work in the base class.
|
||
|
// The HostedAspNetEnvironment subclass can perform more efficiently using reflection
|
||
|
return SystemWebHelper.IsWebConfigAboveApplication(configHostingContext);
|
||
|
}
|
||
|
public virtual void EnsureCompatibilityRequirements(ServiceDescription description)
|
||
|
{
|
||
|
// subclass will ensure AspNetCompatibilityRequirementsAttribute is in the behaviors collection
|
||
|
}
|
||
|
|
||
|
public virtual bool TryGetFullVirtualPath(out string virtualPath)
|
||
|
{
|
||
|
// subclass will use the virtual path from the compiled string
|
||
|
virtualPath = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public virtual string GetAnnotationFromHost(ServiceHostBase host)
|
||
|
{
|
||
|
// subclass will return "Website name\Application Virtual Path|\relative service virtual path|serviceName"
|
||
|
return string.Empty;
|
||
|
}
|
||
|
|
||
|
public virtual void EnsureAllReferencedAssemblyLoaded()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public virtual BaseUriWithWildcard GetBaseUri(string transportScheme, Uri listenUri)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public virtual void ValidateHttpSettings(string virtualPath, bool isMetadataListener, bool usingDefaultSpnList, ref AuthenticationSchemes supportedSchemes, ref ExtendedProtectionPolicy extendedProtectionPolicy, ref string realm)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// returns whether or not the caller should use the hosted client certificate mapping
|
||
|
public virtual bool ValidateHttpsSettings(string virtualPath, ref bool requireClientCertificate)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public virtual void ProcessNotMatchedEndpointAddress(Uri uri, string endpointName)
|
||
|
{
|
||
|
// subclass will throw as appropriate for compat mode
|
||
|
}
|
||
|
|
||
|
public virtual void ValidateCompatibilityRequirements(AspNetCompatibilityRequirementsMode compatibilityMode)
|
||
|
{
|
||
|
// validate that hosting settings are compatible with the requested requirements
|
||
|
if (compatibilityMode == AspNetCompatibilityRequirementsMode.Required)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.Hosting_CompatibilityServiceNotHosted)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual IAspNetMessageProperty GetHostingProperty(Message message)
|
||
|
{
|
||
|
// subclass will gen up a HostingMessageProperty
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public virtual IAspNetMessageProperty GetHostingProperty(Message message, bool removeFromMessage)
|
||
|
{
|
||
|
// subclass will return the hosting property from the message
|
||
|
// and remove it from the message's properties.
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public virtual void PrepareMessageForDispatch(Message message)
|
||
|
{
|
||
|
// subclass will wrap ReceiveContext for Busy Count
|
||
|
}
|
||
|
|
||
|
public virtual void ApplyHostedContext(TransportChannelListener listener, BindingContext context)
|
||
|
{
|
||
|
// subclass will push hosted information to the transport listeners
|
||
|
}
|
||
|
|
||
|
internal virtual void AddMetadataBindingParameters(Uri listenUri, KeyedByTypeCollection<IServiceBehavior> serviceBehaviors, BindingParameterCollection bindingParameters)
|
||
|
{
|
||
|
bindingParameters.Add(new ServiceMetadataExtension.MetadataBindingParameter());
|
||
|
}
|
||
|
|
||
|
internal virtual bool IsMetadataListener(BindingParameterCollection bindingParameters)
|
||
|
{
|
||
|
return bindingParameters.Find<ServiceMetadataExtension.MetadataBindingParameter>() != null;
|
||
|
}
|
||
|
|
||
|
public virtual void IncrementBusyCount()
|
||
|
{
|
||
|
// subclass will increment HostingEnvironment.BusyCount
|
||
|
}
|
||
|
|
||
|
public virtual void DecrementBusyCount()
|
||
|
{
|
||
|
// subclass will decrement HostingEnvironment.BusyCount
|
||
|
}
|
||
|
public virtual bool TraceIncrementBusyCountIsEnabled()
|
||
|
{
|
||
|
// subclass will return true if tracing for IncrementBusyCount is enabled.
|
||
|
//kept as a separate check from TraceIncrementBusyCount to avoid creating source string if Tracing is not enabled.
|
||
|
return false;
|
||
|
}
|
||
|
public virtual bool TraceDecrementBusyCountIsEnabled()
|
||
|
{
|
||
|
// subclass will return true if tracing for DecrementBusyCount is enabled.
|
||
|
//kept as a separate check from TraceDecrementBusyCount to avoid creating source string if Tracing is not enabled.
|
||
|
return false;
|
||
|
}
|
||
|
public virtual void TraceIncrementBusyCount(string data)
|
||
|
{
|
||
|
//callers are expected to check if TraceIncrementBusyCountIsEnabled() is true
|
||
|
//before calling this method
|
||
|
|
||
|
// subclass will emit trace for IncrementBusyCount
|
||
|
// data is emitted in the Trace as the source of the call to Increment.
|
||
|
}
|
||
|
|
||
|
public virtual void TraceDecrementBusyCount(string data)
|
||
|
{
|
||
|
//callers are expected to check if TraceDecrementBusyCountIsEnabled() is true
|
||
|
//before calling this method
|
||
|
|
||
|
// subclass will emit trace for DecrementBusyCount
|
||
|
// data is emitted in the Trace as the source of the call to Decrement.
|
||
|
}
|
||
|
public virtual object GetConfigurationSection(string sectionPath)
|
||
|
{
|
||
|
// subclass will interact with web.config system
|
||
|
return ConfigurationManager.GetSection(sectionPath);
|
||
|
}
|
||
|
|
||
|
// Be sure to update UnsafeGetSection if you modify this method
|
||
|
[Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetSectionFromConfigurationManager which elevates.")]
|
||
|
[SecurityCritical]
|
||
|
public virtual object UnsafeGetConfigurationSection(string sectionPath)
|
||
|
{
|
||
|
// subclass will interact with web.config system
|
||
|
return UnsafeGetSectionFromConfigurationManager(sectionPath);
|
||
|
}
|
||
|
|
||
|
public virtual AuthenticationSchemes GetAuthenticationSchemes(Uri baseAddress)
|
||
|
{
|
||
|
// subclass will grab settings from the metabase
|
||
|
return AuthenticationSchemes.None;
|
||
|
}
|
||
|
|
||
|
public virtual bool IsSimpleApplicationHost
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// subclass will grab settings from the ServiceHostingEnvironment
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Asserts ConfigurationPermission in order to fetch config from ConfigurationManager,"
|
||
|
+ "caller must guard return value.")]
|
||
|
[SecurityCritical]
|
||
|
[ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
|
||
|
static object UnsafeGetSectionFromConfigurationManager(string sectionPath)
|
||
|
{
|
||
|
return ConfigurationManager.GetSection(sectionPath);
|
||
|
}
|
||
|
|
||
|
public virtual bool IsWithinApp(string absoluteVirtualPath)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal static bool IsApplicationDomainHosted()
|
||
|
{
|
||
|
if (!AspNetEnvironment.isApplicationDomainHosted.HasValue)
|
||
|
{
|
||
|
lock (AspNetEnvironment.thisLock)
|
||
|
{
|
||
|
if (!AspNetEnvironment.isApplicationDomainHosted.HasValue)
|
||
|
{
|
||
|
bool isApplicationDomainHosted = false;
|
||
|
if (AspNetEnvironment.Enabled)
|
||
|
{
|
||
|
isApplicationDomainHosted = AspNetEnvironment.IsSystemWebAssemblyLoaded();
|
||
|
}
|
||
|
AspNetEnvironment.isApplicationDomainHosted = isApplicationDomainHosted;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return AspNetEnvironment.isApplicationDomainHosted.Value;
|
||
|
}
|
||
|
|
||
|
private static bool IsSystemWebAssemblyLoaded()
|
||
|
{
|
||
|
const string systemWebName = "System.Web,";
|
||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||
|
{
|
||
|
if (assembly.FullName.StartsWith(systemWebName, StringComparison.OrdinalIgnoreCase))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|