610 lines
26 KiB
C#
610 lines
26 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="HealthMonitoringSectionHelper.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.Web.Configuration {
|
||
|
using System;
|
||
|
using System.Xml;
|
||
|
using System.Configuration;
|
||
|
using System.Collections.Specialized;
|
||
|
using System.Collections;
|
||
|
using System.Globalization;
|
||
|
using System.IO;
|
||
|
using System.Text;
|
||
|
using System.ComponentModel;
|
||
|
using System.Web.Hosting;
|
||
|
using System.Web.Util;
|
||
|
using System.Web.Configuration;
|
||
|
using System.Web.Management;
|
||
|
using System.Web.Compilation;
|
||
|
using System.Security.Permissions;
|
||
|
|
||
|
internal class HealthMonitoringSectionHelper {
|
||
|
static HealthMonitoringSectionHelper s_helper;
|
||
|
|
||
|
static RuleInfoComparer s_ruleInfoComparer = new RuleInfoComparer();
|
||
|
|
||
|
HealthMonitoringSection _section;
|
||
|
internal ProviderInstances _providerInstances;
|
||
|
internal Hashtable _customEvaluatorInstances;
|
||
|
internal ArrayList _ruleInfos;
|
||
|
bool _enabled;
|
||
|
|
||
|
// Cached matched rules for system events. For details, see comments for s_eventArrayDimensionSizes
|
||
|
// in WebEventCodes.cs
|
||
|
static ArrayList[,] _cachedMatchedRules;
|
||
|
|
||
|
#if DBG
|
||
|
// Because we assume no two different event type will use the same event code, in debug mode
|
||
|
// we use this hashtable to make sure our assumption is true.
|
||
|
Hashtable _cachedTypeOfMatchedRulesSystem = new Hashtable();
|
||
|
#endif
|
||
|
|
||
|
// Cached matched rules based on WebBaseEvent Hashcode, and is for non-system events.
|
||
|
Hashtable _cachedMatchedRulesForCustomEvents;
|
||
|
|
||
|
static internal HealthMonitoringSectionHelper GetHelper() {
|
||
|
if (s_helper == null) {
|
||
|
s_helper = new HealthMonitoringSectionHelper();
|
||
|
}
|
||
|
|
||
|
return s_helper;
|
||
|
}
|
||
|
|
||
|
HealthMonitoringSectionHelper() {
|
||
|
|
||
|
// Handle config exceptions so we can still log messages to the event log.
|
||
|
try {
|
||
|
_section = RuntimeConfig.GetAppConfig().HealthMonitoring;
|
||
|
}
|
||
|
catch(Exception e) {
|
||
|
// If InitializationException has not already been set, then this exception
|
||
|
// is happening because the <healthMonitoring> section has an error.
|
||
|
// By setting InitializationException, we allow the exception to be displayed in the response.
|
||
|
// If InitializationException is already set, ignore this exception so we can
|
||
|
// display the original in the response.
|
||
|
if (HttpRuntime.InitializationException == null) {
|
||
|
HttpRuntime.InitializationException = e;
|
||
|
}
|
||
|
_section = RuntimeConfig.GetAppLKGConfig().HealthMonitoring;
|
||
|
// WOS 1965670: if we fail to get the section throw the previous error
|
||
|
if (_section == null) {
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_enabled = _section.Enabled;
|
||
|
|
||
|
if (!_enabled) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// First run some basic sanity check
|
||
|
BasicSanityCheck();
|
||
|
|
||
|
// Init some class members
|
||
|
_ruleInfos = new ArrayList();
|
||
|
_customEvaluatorInstances = new Hashtable();
|
||
|
_providerInstances = new ProviderInstances(_section);
|
||
|
_cachedMatchedRulesForCustomEvents = new Hashtable(new WebBaseEventKeyComparer());
|
||
|
_cachedMatchedRules = new ArrayList[WebEventCodes.GetEventArrayDimensionSize(0),
|
||
|
WebEventCodes.GetEventArrayDimensionSize(1)];
|
||
|
|
||
|
BuildRuleInfos();
|
||
|
|
||
|
_providerInstances.CleanupUninitProviders();
|
||
|
}
|
||
|
|
||
|
internal bool Enabled {
|
||
|
get { return _enabled; }
|
||
|
}
|
||
|
|
||
|
internal HealthMonitoringSection HealthMonitoringSection {
|
||
|
get { return _section; }
|
||
|
}
|
||
|
|
||
|
[FileIOPermission(SecurityAction.Assert, Unrestricted = true)]
|
||
|
void BasicSanityCheck() {
|
||
|
Type type;
|
||
|
|
||
|
foreach (ProviderSettings providerSettings in _section.Providers) {
|
||
|
// Make sure the type is valid.
|
||
|
type = ConfigUtil.GetType(providerSettings.Type, "type", providerSettings);
|
||
|
|
||
|
// Make sure the type support WebEventProvider
|
||
|
HandlerBase.CheckAssignableType(providerSettings.ElementInformation.Properties["type"].Source,
|
||
|
providerSettings.ElementInformation.Properties["type"].LineNumber,
|
||
|
typeof(WebEventProvider), type);
|
||
|
|
||
|
}
|
||
|
|
||
|
foreach (EventMappingSettings eventMappingSettings in _section.EventMappings) {
|
||
|
// Make sure the type is valid.
|
||
|
type = ConfigUtil.GetType(eventMappingSettings.Type, "type", eventMappingSettings);
|
||
|
|
||
|
// Make sure startEventCode <= endEventCode
|
||
|
if (!(eventMappingSettings.StartEventCode <= eventMappingSettings.EndEventCode)) {
|
||
|
string attribute;
|
||
|
|
||
|
// We don't know which one was specified unless we test it
|
||
|
attribute = "startEventCode";
|
||
|
if (eventMappingSettings.ElementInformation.Properties[attribute].LineNumber == 0) {
|
||
|
attribute = "endEventCode";
|
||
|
Debug.Assert(eventMappingSettings.ElementInformation.Properties[attribute].LineNumber != 0,
|
||
|
"eventMappingSettings.ElementInformation.Properties[attribute].LineNumber != 0");
|
||
|
}
|
||
|
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Event_name_invalid_code_range),
|
||
|
eventMappingSettings.ElementInformation.Properties[attribute].Source, eventMappingSettings.ElementInformation.Properties[attribute].LineNumber);
|
||
|
}
|
||
|
|
||
|
// Make sure the type support WebBaseEvent
|
||
|
HandlerBase.CheckAssignableType(eventMappingSettings.ElementInformation.Properties["type"].Source,
|
||
|
eventMappingSettings.ElementInformation.Properties["type"].LineNumber,
|
||
|
typeof(System.Web.Management.WebBaseEvent), type);
|
||
|
|
||
|
// It's a valid type. Might as well save it.
|
||
|
eventMappingSettings.RealType = type;
|
||
|
}
|
||
|
|
||
|
foreach (RuleSettings rule in _section.Rules) {
|
||
|
|
||
|
// Go thru all the Rules, and make sure all referenced provider, eventName
|
||
|
// and profile exist.
|
||
|
|
||
|
string provider = rule.Provider;
|
||
|
if (!String.IsNullOrEmpty(provider)) {
|
||
|
ProviderSettings providerSettings = _section.Providers[provider];
|
||
|
if (providerSettings == null) {
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Health_mon_provider_not_found, provider),
|
||
|
rule.ElementInformation.Properties["provider"].Source,
|
||
|
rule.ElementInformation.Properties["provider"].LineNumber);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
string profile = rule.Profile;
|
||
|
if (!String.IsNullOrEmpty(profile)) {
|
||
|
if (_section.Profiles[profile] == null) {
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Health_mon_profile_not_found, profile),
|
||
|
rule.ElementInformation.Properties["profile"].Source,
|
||
|
rule.ElementInformation.Properties["profile"].LineNumber);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (_section.EventMappings[rule.EventName] == null) {
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Event_name_not_found, rule.EventName),
|
||
|
rule.ElementInformation.Properties["eventName"].Source, rule.ElementInformation.Properties["eventName"].LineNumber);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void DisplayRuleInfo(RuleInfo ruleInfo) {
|
||
|
#if DEBUG
|
||
|
Debug.Trace("BuildRuleInfos", "====================== Rule Info =======================");
|
||
|
Debug.Trace("BuildRuleInfos", "name:" + ruleInfo._ruleSettings.Name);
|
||
|
Debug.Trace("BuildRuleInfos", "type:" + ruleInfo._eventMappingSettings.RealType.Name);
|
||
|
Debug.Trace("BuildRuleInfos", "minInstances:" + ruleInfo._minInstances);
|
||
|
Debug.Trace("BuildRuleInfos", "maxLimit:" + ruleInfo._maxLimit);
|
||
|
Debug.Trace("BuildRuleInfos", "minInterval:" + ruleInfo._minInterval);
|
||
|
Debug.Trace("BuildRuleInfos", "provider:" + ruleInfo._ruleSettings.Provider);
|
||
|
Debug.Trace("BuildRuleInfos", "referenced provider:" + (ruleInfo._referencedProvider == null ? String.Empty : ruleInfo._referencedProvider.GetType().Name));
|
||
|
Debug.Trace("BuildRuleInfos", "=========================================================");
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void BuildRuleInfos() {
|
||
|
Debug.Trace("BuildRuleInfos", "BuildRuleInfos called");
|
||
|
|
||
|
// Each ruleInfo is an object that takes the information
|
||
|
// stored in a ruleSettings and merge it with values from profileSettings.
|
||
|
|
||
|
// At the end, we'll sort the rules based on type (most specific type last)
|
||
|
|
||
|
foreach (RuleSettings ruleSettings in _section.Rules) {
|
||
|
RuleInfo ruleInfo = CreateRuleInfo(ruleSettings);
|
||
|
DisplayRuleInfo(ruleInfo);
|
||
|
_ruleInfos.Add(ruleInfo);
|
||
|
}
|
||
|
|
||
|
_ruleInfos.Sort(s_ruleInfoComparer);
|
||
|
}
|
||
|
|
||
|
RuleInfo CreateRuleInfo(RuleSettings ruleSettings) {
|
||
|
RuleInfo ruleInfo = new RuleInfo(ruleSettings, _section);
|
||
|
|
||
|
// Inherit values from profile
|
||
|
MergeValuesWithProfile(ruleInfo);
|
||
|
|
||
|
// Find out which provider it's referencing
|
||
|
InitReferencedProvider(ruleInfo);
|
||
|
|
||
|
// Initialize the cutom evaluator type
|
||
|
InitCustomEvaluator(ruleInfo);
|
||
|
|
||
|
return ruleInfo;
|
||
|
}
|
||
|
|
||
|
void InitReferencedProvider(RuleInfo ruleInfo) {
|
||
|
String providerName;
|
||
|
WebEventProvider provider;
|
||
|
|
||
|
Debug.Assert(ruleInfo._referencedProvider == null, "ruleInfo._referencedProvider == null");
|
||
|
|
||
|
providerName = ruleInfo._ruleSettings.Provider;
|
||
|
if (String.IsNullOrEmpty(providerName)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
provider = _providerInstances[providerName];
|
||
|
Debug.Assert(provider != null, "provider != null");
|
||
|
|
||
|
ruleInfo._referencedProvider = provider;
|
||
|
}
|
||
|
|
||
|
void MergeValuesWithProfile(RuleInfo ruleInfo) {
|
||
|
ProfileSettings profileSettings = null;
|
||
|
|
||
|
if (ruleInfo._ruleSettings.ElementInformation.Properties["profile"].ValueOrigin != PropertyValueOrigin.Default) {
|
||
|
profileSettings = _section.Profiles[ruleInfo._ruleSettings.Profile];
|
||
|
Debug.Assert(profileSettings != null, "profileSettings != null");
|
||
|
}
|
||
|
|
||
|
if (profileSettings != null && ruleInfo._ruleSettings.ElementInformation.Properties["minInstances"].ValueOrigin == PropertyValueOrigin.Default) {
|
||
|
ruleInfo._minInstances = profileSettings.MinInstances;
|
||
|
}
|
||
|
else {
|
||
|
ruleInfo._minInstances = ruleInfo._ruleSettings.MinInstances;
|
||
|
}
|
||
|
|
||
|
if (profileSettings != null && ruleInfo._ruleSettings.ElementInformation.Properties["maxLimit"].ValueOrigin == PropertyValueOrigin.Default) {
|
||
|
ruleInfo._maxLimit = profileSettings.MaxLimit;
|
||
|
}
|
||
|
else {
|
||
|
ruleInfo._maxLimit = ruleInfo._ruleSettings.MaxLimit;
|
||
|
}
|
||
|
|
||
|
if (profileSettings != null && ruleInfo._ruleSettings.ElementInformation.Properties["minInterval"].ValueOrigin == PropertyValueOrigin.Default) {
|
||
|
ruleInfo._minInterval = profileSettings.MinInterval;
|
||
|
}
|
||
|
else {
|
||
|
ruleInfo._minInterval = ruleInfo._ruleSettings.MinInterval;
|
||
|
}
|
||
|
|
||
|
if (profileSettings != null && ruleInfo._ruleSettings.ElementInformation.Properties["custom"].ValueOrigin == PropertyValueOrigin.Default) {
|
||
|
ruleInfo._customEvaluator = profileSettings.Custom;
|
||
|
ruleInfo._customEvaluatorConfig = profileSettings;
|
||
|
}
|
||
|
else {
|
||
|
ruleInfo._customEvaluator = ruleInfo._ruleSettings.Custom;
|
||
|
ruleInfo._customEvaluatorConfig = ruleInfo._ruleSettings;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void InitCustomEvaluator(RuleInfo ruleInfo) {
|
||
|
string customEvaluator = ruleInfo._customEvaluator;
|
||
|
|
||
|
if (customEvaluator == null ||
|
||
|
customEvaluator.Trim().Length == 0) {
|
||
|
ruleInfo._customEvaluatorType = null;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ruleInfo._customEvaluatorType = ConfigUtil.GetType(ruleInfo._customEvaluator,
|
||
|
"custom", ruleInfo._customEvaluatorConfig);
|
||
|
|
||
|
// Make sure the type support WebBaseEvent
|
||
|
HandlerBase.CheckAssignableType(ruleInfo._customEvaluatorConfig.ElementInformation.Properties["custom"].Source,
|
||
|
ruleInfo._customEvaluatorConfig.ElementInformation.Properties["custom"].LineNumber,
|
||
|
typeof(System.Web.Management.IWebEventCustomEvaluator), ruleInfo._customEvaluatorType);
|
||
|
|
||
|
// Create a public instance of the custom evaluator
|
||
|
if (_customEvaluatorInstances[ruleInfo._customEvaluatorType] == null) {
|
||
|
_customEvaluatorInstances[ruleInfo._customEvaluatorType] = HttpRuntime.CreatePublicInstance(ruleInfo._customEvaluatorType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Find the corresponding array of RuleInfo based on the fired event
|
||
|
internal ArrayList FindFiringRuleInfos(Type eventType, int eventCode) {
|
||
|
ArrayList foundFiringRuleInfos;
|
||
|
bool systemEvent = eventCode < WebEventCodes.WebExtendedBase;
|
||
|
CustomWebEventKey customWebEventKey = null;
|
||
|
object lockObject;
|
||
|
int index0 = 0, index1 = 0;
|
||
|
|
||
|
#if DBG
|
||
|
if (systemEvent) {
|
||
|
Type type;
|
||
|
|
||
|
type = (Type)_cachedTypeOfMatchedRulesSystem[eventCode];
|
||
|
if (type == null) {
|
||
|
lock(_cachedTypeOfMatchedRulesSystem) {
|
||
|
type = (Type)_cachedTypeOfMatchedRulesSystem[eventCode];
|
||
|
if (type == null) {
|
||
|
_cachedTypeOfMatchedRulesSystem[eventCode] = eventType;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (type != null) {
|
||
|
Debug.Assert(type == eventType,
|
||
|
"For system events, we assume each event code will map only to one event type. " +
|
||
|
"Eventcode= " + eventCode + "; stored type= " + type.ToString() +
|
||
|
"; raised event type= " + eventType);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// First, we look at the cache to see if we find the array.
|
||
|
if (systemEvent) {
|
||
|
WebEventCodes.GetEventArrayIndexsFromEventCode(eventCode, out index0, out index1);
|
||
|
foundFiringRuleInfos = _cachedMatchedRules[index0, index1];
|
||
|
}
|
||
|
else {
|
||
|
customWebEventKey = new CustomWebEventKey(eventType, eventCode);
|
||
|
foundFiringRuleInfos = (ArrayList)_cachedMatchedRulesForCustomEvents[customWebEventKey];
|
||
|
}
|
||
|
|
||
|
if (foundFiringRuleInfos != null) {
|
||
|
return foundFiringRuleInfos;
|
||
|
}
|
||
|
|
||
|
if (systemEvent) {
|
||
|
lockObject = _cachedMatchedRules;
|
||
|
}
|
||
|
else {
|
||
|
lockObject = _cachedMatchedRulesForCustomEvents;
|
||
|
}
|
||
|
|
||
|
lock (lockObject) {
|
||
|
|
||
|
if (systemEvent) {
|
||
|
foundFiringRuleInfos = _cachedMatchedRules[index0, index1];
|
||
|
}
|
||
|
else {
|
||
|
Debug.Assert(customWebEventKey != null);
|
||
|
foundFiringRuleInfos = (ArrayList)_cachedMatchedRulesForCustomEvents[customWebEventKey];
|
||
|
}
|
||
|
|
||
|
if (foundFiringRuleInfos != null) {
|
||
|
return foundFiringRuleInfos;
|
||
|
}
|
||
|
|
||
|
// Not found in cache.
|
||
|
|
||
|
ArrayList matchedRules = new ArrayList();
|
||
|
|
||
|
// Go thru the sorted ruleInfo array and look for matching ruleInfo,
|
||
|
// starting from the most specific type.
|
||
|
for (int i = _ruleInfos.Count - 1; i >= 0; i--) {
|
||
|
RuleInfo curRule = (RuleInfo)_ruleInfos[i];
|
||
|
|
||
|
// Now see if the current rule matches the raised event
|
||
|
if (curRule.Match(eventType, eventCode)) {
|
||
|
matchedRules.Add(new FiringRuleInfo(curRule));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Then for each matched rule, we need to figure out if the provider it
|
||
|
// uses is also used by other rules. We need this info because if multiple rules are
|
||
|
// using the same provider, we fire the event to the provider only once.
|
||
|
int count = matchedRules.Count;
|
||
|
for (int i = 0; i < count; i++) {
|
||
|
FiringRuleInfo info1 = (FiringRuleInfo)matchedRules[i];
|
||
|
|
||
|
if (info1._ruleInfo._referencedProvider != null) {
|
||
|
for (int j = i + 1; j < count; j++) {
|
||
|
|
||
|
FiringRuleInfo info2 = (FiringRuleInfo)matchedRules[j];
|
||
|
if (info2._ruleInfo._referencedProvider != null && // ignore null-provider
|
||
|
info2._indexOfFirstRuleInfoWithSameProvider == -1 && // ignore rules that were marked already
|
||
|
info1._ruleInfo._referencedProvider == info2._ruleInfo._referencedProvider) { // they are pointing to the same provider
|
||
|
|
||
|
// We'll remember the index of the first rule info that share the same
|
||
|
// provider. For details on how this index is used, please see
|
||
|
// WebBaseEvent.RaiseInternal.
|
||
|
if (info1._indexOfFirstRuleInfoWithSameProvider == -1) {
|
||
|
info1._indexOfFirstRuleInfoWithSameProvider = i;
|
||
|
}
|
||
|
|
||
|
info2._indexOfFirstRuleInfoWithSameProvider = i;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
Debug.Trace("FindRuleInfos", "------------------------------------------------");
|
||
|
Debug.Trace("FindRuleInfos", "Find ruleInfos for event with type=" + eventType.ToString() +
|
||
|
", EventCode=" + eventCode);
|
||
|
|
||
|
foreach(FiringRuleInfo info in matchedRules) {
|
||
|
Debug.Trace("FindRuleInfos", "Provider=" + info._ruleInfo._ruleSettings.Provider +
|
||
|
"; eventNameType=" + info._ruleInfo._eventMappingSettings.RealType.ToString() +
|
||
|
"; _indexOfFirstRuleInfoWithSameProvider=" + info._indexOfFirstRuleInfoWithSameProvider);
|
||
|
}
|
||
|
Debug.Trace("FindRuleInfos", "------------------------------------------------");
|
||
|
#endif
|
||
|
|
||
|
// save matchedRules in the cache
|
||
|
if (systemEvent) {
|
||
|
_cachedMatchedRules[index0, index1] = matchedRules;
|
||
|
}
|
||
|
else {
|
||
|
Debug.Assert(customWebEventKey != null);
|
||
|
_cachedMatchedRulesForCustomEvents[customWebEventKey] = matchedRules;
|
||
|
}
|
||
|
|
||
|
return matchedRules;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class RuleInfo {
|
||
|
internal string _customEvaluator;
|
||
|
internal ConfigurationElement _customEvaluatorConfig;
|
||
|
|
||
|
// The following properties are cached here for performance reason
|
||
|
internal int _minInstances;
|
||
|
internal int _maxLimit;
|
||
|
internal TimeSpan _minInterval; // in seconds
|
||
|
|
||
|
internal RuleSettings _ruleSettings;
|
||
|
|
||
|
internal WebEventProvider _referencedProvider;
|
||
|
|
||
|
internal Type _customEvaluatorType;
|
||
|
|
||
|
internal EventMappingSettings _eventMappingSettings;
|
||
|
|
||
|
internal RuleFiringRecord _ruleFiringRecord;
|
||
|
|
||
|
internal RuleInfo(RuleSettings ruleSettings, HealthMonitoringSection section) {
|
||
|
_eventMappingSettings = section.EventMappings[ruleSettings.EventName];
|
||
|
|
||
|
_ruleSettings = ruleSettings;
|
||
|
_ruleFiringRecord = new RuleFiringRecord(this);
|
||
|
}
|
||
|
|
||
|
internal bool Match(Type eventType, int eventCode) {
|
||
|
// Fail if the type doesn't match.
|
||
|
if (!(eventType.Equals(_eventMappingSettings.RealType) ||
|
||
|
eventType.IsSubclassOf(_eventMappingSettings.RealType))) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Fail if the event code doesn't match
|
||
|
if (!(_eventMappingSettings.StartEventCode <= eventCode &&
|
||
|
eventCode <= _eventMappingSettings.EndEventCode)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class FiringRuleInfo {
|
||
|
internal RuleInfo _ruleInfo;
|
||
|
internal int _indexOfFirstRuleInfoWithSameProvider;
|
||
|
|
||
|
internal FiringRuleInfo(RuleInfo ruleInfo) {
|
||
|
_ruleInfo = ruleInfo;
|
||
|
_indexOfFirstRuleInfoWithSameProvider = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class ProviderInstances {
|
||
|
internal Hashtable _instances; // case-insensitive because the providers collection is too.
|
||
|
|
||
|
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
|
||
|
internal ProviderInstances(HealthMonitoringSection section) {
|
||
|
// Build the array of providers
|
||
|
// Don't create an instance yet, but only store the providerInfo in the HashTable.
|
||
|
_instances = CollectionsUtil.CreateCaseInsensitiveHashtable(section.Providers.Count);
|
||
|
|
||
|
foreach (object obj in section.Providers) {
|
||
|
ProviderSettings settings = (ProviderSettings)obj;
|
||
|
|
||
|
// Please note we are storing the ProviderSettings in the hashtable.
|
||
|
// But if we create an instance of that provider, we will replace
|
||
|
// that string with a provider object.
|
||
|
_instances.Add(settings.Name, settings);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WebEventProvider GetProviderInstance(string providerName) {
|
||
|
WebEventProvider provider;
|
||
|
object o;
|
||
|
|
||
|
o = _instances[providerName];
|
||
|
if (o == null) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
ProviderSettings providerSettings = o as ProviderSettings;
|
||
|
|
||
|
if (providerSettings != null) {
|
||
|
// If what we got is still a ProviderSettings, it means we haven't created an instance
|
||
|
// of it yet.
|
||
|
Type type;
|
||
|
string typeName = providerSettings.Type;
|
||
|
|
||
|
type = BuildManager.GetType(typeName, false);
|
||
|
Debug.Assert(type != null, "type != null");
|
||
|
|
||
|
if (typeof(IInternalWebEventProvider).IsAssignableFrom(type)) {
|
||
|
provider = (WebEventProvider)HttpRuntime.CreateNonPublicInstance(type);
|
||
|
}
|
||
|
else {
|
||
|
provider = (WebEventProvider)HttpRuntime.CreatePublicInstance(type);
|
||
|
}
|
||
|
|
||
|
using (new ProcessImpersonationContext()) {
|
||
|
try {
|
||
|
provider.Initialize(providerSettings.Name, providerSettings.Parameters);
|
||
|
}
|
||
|
catch (ConfigurationErrorsException) {
|
||
|
throw;
|
||
|
}
|
||
|
catch (ConfigurationException e) {
|
||
|
throw new ConfigurationErrorsException(e.Message, providerSettings.ElementInformation.Properties["type"].Source,
|
||
|
providerSettings.ElementInformation.Properties["type"].LineNumber);
|
||
|
}
|
||
|
catch {
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Debug.Trace("ProviderInstances", "Create a provider instance: " +
|
||
|
"name=" + providerSettings.Name + ";type=" + typeName);
|
||
|
|
||
|
_instances[providerName] = provider;
|
||
|
}
|
||
|
else {
|
||
|
provider = o as WebEventProvider;
|
||
|
Debug.Assert(provider != null, "provider != null");
|
||
|
}
|
||
|
|
||
|
return provider;
|
||
|
}
|
||
|
|
||
|
internal WebEventProvider this[String name] {
|
||
|
get {
|
||
|
return GetProviderInstance(name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Cleanup each provider for which we have NOT created an instance.
|
||
|
internal void CleanupUninitProviders() {
|
||
|
ArrayList list = new ArrayList();
|
||
|
|
||
|
foreach (DictionaryEntry de in _instances) {
|
||
|
if (de.Value is ProviderSettings) {
|
||
|
list.Add(de.Key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach (object o in list) {
|
||
|
Debug.Trace("ProviderInstances", "Remove " + (string)o + " from providers");
|
||
|
_instances.Remove(o);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool ContainsKey(string name) {
|
||
|
return _instances.ContainsKey(name);
|
||
|
}
|
||
|
|
||
|
public IDictionaryEnumerator GetEnumerator() {
|
||
|
return _instances.GetEnumerator();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|