#region License
/*
* Copyright 2002-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Web.UI;
using Common.Logging;
using Spring.Context;
#endregion
namespace Spring.Web.Support{
/// <summary>
/// Support Class providing a method to ensure a control has been intercepted
/// </summary>
/// <author>Erich Eichinger</author>
internal sealed class ControlInterceptor
{
private class NoOpInterceptionStrategy : IInterceptionStrategy
{
private ILog Log = LogManager.GetLogger( typeof( NoOpInterceptionStrategy ) );
public bool Intercept( IApplicationContext defaultApplicationContext, ControlAccessor ctlAccessor,
ControlCollectionAccessor ctlColAccessor )
{
return true;
}
}
/// <summary>
/// Holds all available interception strategies
/// </summary>
private static readonly IInterceptionStrategy[] s_availableInterceptionStrategies = new IInterceptionStrategy[]
{
new InterceptControlCollectionStrategy()
, new InterceptControlCollectionOwnerStrategy()
};
/// <summary>
/// The last resort interception strategy...
/// </summary>
private static readonly IInterceptionStrategy s_noopInterceptionStrategy = new NoOpInterceptionStrategy();
/// <summary>
/// Holds a control.GetType()->IInterceptionStrategy table.
/// </summary>
private static readonly Hashtable s_cachedInterceptionStrategies = new Hashtable();
/// <summary>
/// Holds well-known Type/Strategy mappings.
/// </summary>
private static readonly Hashtable s_knownInterceptionStrategies = new Hashtable();
static ControlInterceptor()
{
s_knownInterceptionStrategies[typeof( ControlCollection )] = s_availableInterceptionStrategies[1];
}
private ControlInterceptor()
{
}
/// <summary>
/// Ensures, a control has been intercepted to support Web-DI. If not, the control will be intercepted.
/// </summary>
public static void EnsureControlIntercepted( IApplicationContext defaultApplicationContext, Control control )
{
if (control is LiteralControl)
{
return; // nothing more to do
}
// check control itself
if (IsDependencyInjectionAware( defaultApplicationContext, control ))
{
return; // nothing more to do
}
// check control's ControlCollection
EnsureControlCollectionIntercepted( defaultApplicationContext, control );
}
private static void EnsureControlCollectionIntercepted( IApplicationContext defaultApplicationContext, Control control )
{
// check the collection
ControlAccessor ctlAccessor = new ControlAccessor( control );
ControlCollection childControls = ctlAccessor.Controls;
if (IsDependencyInjectionAware( defaultApplicationContext, childControls ))
{
return; // nothing more to do
}
// check, if the collection's owner has already been intercepted
ControlCollectionAccessor ctlColAccessor = new ControlCollectionAccessor( childControls );
if (IsDependencyInjectionAware( defaultApplicationContext, ctlColAccessor.Owner ))
{
return; // nothing more to do
}
// lookup strategy in cache
IInterceptionStrategy strategy = null;
lock (s_cachedInterceptionStrategies)
{
strategy = (IInterceptionStrategy)s_cachedInterceptionStrategies[control.GetType()];
}
if (strategy != null)
{
strategy.Intercept( defaultApplicationContext, ctlAccessor, ctlColAccessor );
}
else
{
// nothing in cache - try well-known strategies for owner resp. child collection type
strategy = (IInterceptionStrategy)s_knownInterceptionStrategies[control.GetType()];
if (strategy == null)
{
strategy = (IInterceptionStrategy)s_knownInterceptionStrategies[childControls.GetType()];
}
// try intercept using well-known strategy
if (strategy != null)
{
bool bOk = strategy.Intercept( defaultApplicationContext, ctlAccessor, ctlColAccessor );
if (!bOk)
{
strategy = null;
}
}
// not well-known or didn't work out
if (strategy == null)
{
// probe for a strategy
bool bOk = false;
for (int i = 0; i < s_availableInterceptionStrategies.Length; i++)
{
strategy = s_availableInterceptionStrategies[i];
bOk = strategy.Intercept( defaultApplicationContext, ctlAccessor, ctlColAccessor );
if (bOk)
break;
}
if (!bOk)
{
LogManager.GetLogger( typeof( ControlInterceptor ) ).Warn( string.Format( "dependency injection not supported for control type {0}", ctlAccessor.GetTarget().GetType() ) );
strategy = s_noopInterceptionStrategy;
}
}
lock (s_cachedInterceptionStrategies)
{
s_cachedInterceptionStrategies[control.GetType()] = strategy;
}
}
}
private static bool IsDependencyInjectionAware( IApplicationContext defaultApplicationContext, object o )
{
ISupportsWebDependencyInjection diAware = o as ISupportsWebDependencyInjection;
if (diAware != null)
{
// If the ControlCollection is alread DI-aware ensure appContext is set
if (diAware.DefaultApplicationContext == null)
{
diAware.DefaultApplicationContext = defaultApplicationContext;
}
return true; // nothing more to do
}
return false;
}
}
}
|