You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,381 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="IndividualDeviceConfig.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Comment this out to get a version that doesn't need synchronized
|
||||
// access. This can be used for profiling, to compare whether the lock
|
||||
// or the late writing is more useful.
|
||||
|
||||
using System;
|
||||
using System.Web.Configuration;
|
||||
using System.Configuration;
|
||||
using System.Xml;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Web;
|
||||
using System.Web.Util;
|
||||
using System.Threading;
|
||||
using System.Web.Mobile;
|
||||
|
||||
namespace System.Web.UI.MobileControls
|
||||
{
|
||||
|
||||
// Data structure for an individual device configuration.
|
||||
// Included predicates, page adapter type, and a list of
|
||||
// control/controlAdapter pairs.
|
||||
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
||||
internal class IndividualDeviceConfig
|
||||
{
|
||||
internal delegate bool DeviceQualifiesDelegate(HttpContext context);
|
||||
|
||||
private String _name;
|
||||
private readonly ControlsConfig _controlsConfig;
|
||||
private DeviceQualifiesDelegate _deviceQualifiesPredicate;
|
||||
private Type _pageAdapterType;
|
||||
private IWebObjectFactory _pageAdapterFactory;
|
||||
|
||||
// Parent device configuration.
|
||||
|
||||
private IndividualDeviceConfig _parentConfig;
|
||||
private String _parentConfigName;
|
||||
|
||||
// ControlType --> ControlAdapterType mapping (one of these
|
||||
// per individual device config)
|
||||
private readonly Hashtable _controlAdapterTypes = new Hashtable();
|
||||
|
||||
// ControlType --> ControlAdapterType mapping cache, used to
|
||||
// store mappings that are derived from a complex lookup (one of these
|
||||
// per individual device config)
|
||||
private readonly Hashtable _controlAdapterLookupCache = new Hashtable();
|
||||
|
||||
// Provide synchronized access to the hashtable, allowing
|
||||
// multiple readers but just one writer. Here we have one per
|
||||
// device config.
|
||||
private readonly ReaderWriterLock _controlAdapterTypesLock = new ReaderWriterLock();
|
||||
|
||||
// The highest level to check.
|
||||
|
||||
private static readonly Type _baseControlType = typeof(System.Web.UI.Control);
|
||||
|
||||
|
||||
// This constructor takes both a delegate that chooses this
|
||||
// device, and a Type to instantiate the appropriate page
|
||||
// adapter with.
|
||||
internal IndividualDeviceConfig(ControlsConfig controlsConfig,
|
||||
String name,
|
||||
DeviceQualifiesDelegate deviceQualifiesDelegate,
|
||||
Type pageAdapterType,
|
||||
String parentConfigName)
|
||||
{
|
||||
_controlsConfig = controlsConfig;
|
||||
_name = name;
|
||||
_deviceQualifiesPredicate = deviceQualifiesDelegate;
|
||||
_parentConfigName = parentConfigName;
|
||||
_parentConfig = null;
|
||||
PageAdapterType = pageAdapterType;
|
||||
}
|
||||
|
||||
// This constructor takes just a page adapter for situations
|
||||
// where device selection isn't necessary (e.g., the designer).
|
||||
internal IndividualDeviceConfig(Type pageAdapterType) : this(null, null, null, pageAdapterType, null)
|
||||
{
|
||||
}
|
||||
|
||||
// Given a context, see if this device config should handle
|
||||
// the given device. If there is no predicate, return true.
|
||||
internal /*public*/ bool DeviceQualifies(HttpContext context)
|
||||
{
|
||||
return _deviceQualifiesPredicate == null ?
|
||||
true :
|
||||
_deviceQualifiesPredicate(context);
|
||||
}
|
||||
|
||||
// Register an adapter with the given control.
|
||||
internal /*public*/ void AddControl(Type controlType,
|
||||
Type adapterType)
|
||||
{
|
||||
// Don't need to synchronize, as this is only being called
|
||||
// from one thread -- the configuration section handler.
|
||||
_controlAdapterTypes[controlType] = FactoryGenerator.StaticFactoryGenerator.GetFactory(adapterType);
|
||||
}
|
||||
|
||||
private Type PageAdapterType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _pageAdapterType;
|
||||
}
|
||||
set {
|
||||
_pageAdapterType = value;
|
||||
if (value != null) {
|
||||
Debug.Assert(typeof(IPageAdapter).IsAssignableFrom(value));
|
||||
_pageAdapterFactory =
|
||||
(IWebObjectFactory)FactoryGenerator.StaticFactoryGenerator.GetFactory(_pageAdapterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal DeviceQualifiesDelegate DeviceQualifiesPredicate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _deviceQualifiesPredicate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_deviceQualifiesPredicate = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected IWebObjectFactory LookupControl(Type controlType)
|
||||
{
|
||||
return LookupControl(controlType, false);
|
||||
}
|
||||
|
||||
private IWebObjectFactory LookupControl(Type controlType, bool lookInTypeCache)
|
||||
{
|
||||
IWebObjectFactory factory;
|
||||
|
||||
factory = (IWebObjectFactory)_controlAdapterTypes[controlType];
|
||||
if (factory == null && lookInTypeCache)
|
||||
{
|
||||
// Grab reader lock...
|
||||
using (new ReaderWriterLockResource(_controlAdapterTypesLock,
|
||||
false))
|
||||
{
|
||||
factory = (IWebObjectFactory)_controlAdapterLookupCache[controlType];
|
||||
}
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
// Create a new page adapter for the device.
|
||||
internal /*public*/ IPageAdapter NewPageAdapter()
|
||||
{
|
||||
IPageAdapter a = _pageAdapterFactory.CreateInstance() as IPageAdapter;
|
||||
|
||||
if (a == null)
|
||||
{
|
||||
throw new Exception(
|
||||
SR.GetString(SR.IndividualDeviceConfig_TypeMustSupportInterface,
|
||||
_pageAdapterType.FullName, "IPageAdapter"));
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
// Given a control's type, create a control adapter for it.
|
||||
|
||||
internal virtual IControlAdapter NewControlAdapter(Type originalControlType)
|
||||
{
|
||||
IWebObjectFactory factory = GetAdapterFactory(originalControlType);
|
||||
|
||||
// Should return non-null, or throw an exception.
|
||||
Debug.Assert(factory != null);
|
||||
|
||||
IControlAdapter a = (IControlAdapter) factory.CreateInstance();
|
||||
return a;
|
||||
}
|
||||
|
||||
// Given a control's type, returns the adapter type to be used.
|
||||
// Note that it's legal to not register an adapter type for each
|
||||
// control type.
|
||||
//
|
||||
// This lookup uses the following steps:
|
||||
//
|
||||
// (1) Look up the control type directly, to see if an adapter type
|
||||
// has been registered for it.
|
||||
// (2) Walk up the control inheritance chain, to see if an adapter type
|
||||
// has been registered for the class. For example, if the passed
|
||||
// control type is a validator, check BaseValidator, Label,
|
||||
// TextControl, and finally MobileControl.
|
||||
// (3) If no adapter type has still been found, call the parent configuration,
|
||||
// if any, to look up the adapter type. For example, the CHTML device
|
||||
// configuration would call the HTML device configuration.
|
||||
// (4) If an adapter type is found, but is not explicitly registered for
|
||||
// the passed control type, add an entry to the table, so that
|
||||
// subsequent requests do not need to walk the hierarchy.
|
||||
|
||||
protected IWebObjectFactory GetAdapterFactory(Type originalControlType)
|
||||
{
|
||||
Debug.Assert(_parentConfigName == null);
|
||||
|
||||
Type controlType = originalControlType;
|
||||
IWebObjectFactory factory = LookupControl(controlType, true); // Look in type cache
|
||||
|
||||
// Walk up hierarchy looking for registered adapters.
|
||||
// Stop when we get to the base control.
|
||||
|
||||
while (factory == null && controlType != _baseControlType)
|
||||
{
|
||||
factory = LookupControl(controlType);
|
||||
if (factory == null)
|
||||
{
|
||||
controlType = controlType.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
// Could not find one in the current hierarchy. So, look it up in
|
||||
// the parent config if there is one.
|
||||
|
||||
if (factory == null && _parentConfig != null)
|
||||
{
|
||||
factory = _parentConfig.GetAdapterFactory(originalControlType);
|
||||
}
|
||||
|
||||
if (factory == null)
|
||||
{
|
||||
throw new Exception(
|
||||
SR.GetString(SR.IndividualDeviceConfig_ControlWithIncorrectPageAdapter,
|
||||
controlType.FullName, _pageAdapterType.FullName));
|
||||
|
||||
}
|
||||
|
||||
if (controlType != originalControlType)
|
||||
{
|
||||
// Add to lookup cache, so the next lookup won't require
|
||||
// traversing the hierarchy.
|
||||
|
||||
// Grab writer lock...
|
||||
using (new ReaderWriterLockResource(_controlAdapterTypesLock,
|
||||
true))
|
||||
{
|
||||
_controlAdapterLookupCache[originalControlType] = factory;
|
||||
}
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
internal /*public*/ String Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
internal /*public*/ String ParentConfigName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _parentConfigName;
|
||||
}
|
||||
set
|
||||
{
|
||||
_parentConfigName = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal /*public*/ IndividualDeviceConfig ParentConfig
|
||||
{
|
||||
get
|
||||
{
|
||||
return _parentConfig;
|
||||
}
|
||||
set
|
||||
{
|
||||
_parentConfig = value;
|
||||
}
|
||||
}
|
||||
|
||||
private enum FixupState { NotFixedUp, FixingUp, FixedUp };
|
||||
private FixupState _fixup = FixupState.NotFixedUp;
|
||||
|
||||
internal /*public*/ void FixupInheritance(IndividualDeviceConfig referrer, XmlNode configNode)
|
||||
{
|
||||
if (_fixup == FixupState.FixedUp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_fixup == FixupState.FixingUp)
|
||||
{
|
||||
Debug.Assert(referrer != null);
|
||||
|
||||
// Circular reference
|
||||
throw new Exception(SR.GetString(SR.MobileControlsSectionHandler_CircularReference,
|
||||
referrer.Name));
|
||||
}
|
||||
|
||||
_fixup = FixupState.FixingUp;
|
||||
|
||||
if (ParentConfigName != null)
|
||||
{
|
||||
Debug.Assert(ParentConfigName.Length != 0 && ParentConfig == null);
|
||||
|
||||
ParentConfig = _controlsConfig.GetDeviceConfig(ParentConfigName);
|
||||
|
||||
if (ParentConfig == null)
|
||||
{
|
||||
throw new ConfigurationErrorsException(
|
||||
SR.GetString(SR.MobileControlsSectionHandler_DeviceConfigNotFound,
|
||||
ParentConfigName),
|
||||
configNode);
|
||||
}
|
||||
|
||||
// Make sure parent is fixed up.
|
||||
|
||||
ParentConfig.FixupInheritance(this, configNode);
|
||||
|
||||
if (PageAdapterType == null)
|
||||
{
|
||||
PageAdapterType = ParentConfig.PageAdapterType;
|
||||
}
|
||||
|
||||
if (DeviceQualifiesPredicate == null)
|
||||
{
|
||||
DeviceQualifiesPredicate = ParentConfig.DeviceQualifiesPredicate;
|
||||
}
|
||||
|
||||
Debug.Assert(PageAdapterType != null);
|
||||
Debug.Assert(DeviceQualifiesPredicate != null);
|
||||
|
||||
// Reset this since we don't need it any longer.
|
||||
ParentConfigName = null;
|
||||
}
|
||||
|
||||
_fixup = FixupState.FixedUp;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
||||
internal class ReaderWriterLockResource : IDisposable
|
||||
{
|
||||
private ReaderWriterLock _lock;
|
||||
private bool _writerLock;
|
||||
|
||||
internal /*public*/ ReaderWriterLockResource(ReaderWriterLock theLock, bool writerLock)
|
||||
{
|
||||
_lock = theLock;
|
||||
_writerLock = writerLock;
|
||||
if (_writerLock)
|
||||
{
|
||||
_lock.AcquireWriterLock(Timeout.Infinite);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lock.AcquireReaderLock(Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
/*public*/ void IDisposable.Dispose()
|
||||
{
|
||||
if (_writerLock)
|
||||
{
|
||||
_lock.ReleaseWriterLock();
|
||||
}
|
||||
else
|
||||
{
|
||||
_lock.ReleaseReaderLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user