added SPRNET-711, SPRNET-713 - MappingHandlerFactory for configuring custom IHttpHandler and IHttpHandlerFactory instances

This commit is contained in:
eeichinger
2008-10-13 23:18:44 +00:00
parent 054421552e
commit b6b4b370f9
18 changed files with 1014 additions and 102 deletions

View File

@@ -0,0 +1,20 @@
using System.Web;
/// <summary>
/// Summary description for NoOpHandler
/// </summary>
public class MyCustomHttpHandler : IHttpHandler
{
public string MessageText = "<unconfigured>";
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write(@"Response from MyCustomHttpHandler:" + MessageText);
}
public bool IsReusable
{
get { return true; }
}
}

View File

@@ -0,0 +1,49 @@
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title><%=Title%></title>
</head>
<body>
<h2><a href="../../Default.aspx">Welcome to Spring.NET Web Framework Quick Start Guide</a></h2>
<h2><a href="../Default.aspx">Dependency Injection</a></h2>
<div>
<form id="form1" runat="server">
<p>
The links below demonstrate dependency injection on custom handlers using <b>MappingHandlerFactory</b>.
The example code shows, how to map all url requests to spring and let MappingHandlerFactory resolve urls to
container-managed IHttpHandlerFactory or IHttpHandler objects.
</p>
<pre>
// web.config
&lt;httpHandlers&gt;
&lt;!-- map all requests to spring (just for demo - don't do this at home!) --&gt;
&lt;add verb=&quot;*&quot; path=&quot;*.*&quot; type=&quot;Spring.Web.Support.MappingHandlerFactory, Spring.Web&quot; /&gt;
&lt;/httpHandlers&gt;
// spring-objects.config
&lt;object type=&quot;Spring.Web.Support.MappingHandlerFactoryConfigurer, Spring.Web&quot;&gt;
&lt;property name=&quot;HandlerMap&quot;&gt;
&lt;dictionary&gt;
&lt;entry key=&quot;\.ashx$&quot; value=&quot;standardHandlerFactory&quot; /&gt;
&lt;!-- map any request ending with *.whatever to standardHandlerFactory --&gt;
&lt;entry key=&quot;\.whatever$&quot; value=&quot;specialHandlerFactory&quot; /&gt;
&lt;/dictionary&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;object name=&quot;standardHandlerFactory&quot; type=&quot;Spring.Web.Support.DefaultHandlerFactory, Spring.Web&quot; /&gt;
&lt;object name=&quot;specialHandlerFactory&quot; type=&quot;MySpecialHandlerFactoryImpl&quot; /&gt;
</pre>
<ul>
<li><a href="DemoHandler.ashx">DemoHandler.ashx</a></li>
<li><a href="AnotherCustomHandler.whatever">AnotherCustomHandler.whatever</a></li>
</ul>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<a href="DemoHandler.ashx">DemoHandler.ashx</a><br/>
<a href="AnotherCustomHandler.whatever">AnotherCustomHandler.whatever</a><br/>
</div>
</form>
</body>
</html>

View File

@@ -0,0 +1,30 @@
<%@ WebHandler Language="C#" Class="DemoHandler" %>
using System;
using System.Web;
public class DemoHandler : IHttpHandler
{
private string _outputText;
public string OutputText
{
get { return _outputText; }
set { _outputText = value; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("injected text:" + _outputText);
}
public bool IsReusable
{
get
{
return false;
}
}
}

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpHandlers>
<!--
the lines below map *any* request ending with *.ashx or *.whatever to the global(!) MappingHandlerFactory. Further "specialication"
of which handler to map to is done within MappingHandlerFactory's configuration - use MappingHandlerFactoryConfigurer for this (see below)
-->
<add verb="*" path="*.ashx" type="Spring.Web.Support.MappingHandlerFactory, Spring.Web" validate="true"/>
<add verb="*" path="*.whatever" type="Spring.Web.Support.MappingHandlerFactory, Spring.Web" validate="false"/>
</httpHandlers>
</system.web>
<spring>
<context>
<resource uri="config://spring/objects" />
</context>
<objects xmlns="http://www.springframework.net">
<!-- configures the global GenericHandlerFactory instance -->
<object name="mappingHandlerFactoryConfigurer" type="Spring.Web.Support.MappingHandlerFactoryConfigurer, Spring.Web">
<property name="HandlerMap">
<dictionary>
<!-- map any request ending with *.whatever to NoOpHandler -->
<entry key="\.whatever$" value="myCustomHandler" />
<entry key="\.ashx$" value="standardHandlerFactory" />
</dictionary>
</property>
</object>
<!--
uses the original System.Web.UI.SimpleHandlerFactory to create handler instances
and configures each handler using objectdefinitions matching the requestl url's filename
-->
<object name="standardHandlerFactory" type="Spring.Web.Support.DefaultHandlerFactory, Spring.Web" />
<!-- defines a standard singleton that will handle *.whatever requests -->
<object name="myCustomHandler" type="MyCustomHttpHandler, App_Code">
<property name="MessageText" value="This text is injected via Spring" />
</object>
<!--
used for configuring ~/DemoHandler.ashx custom handler
note, that this is an abstract definition because 'type' is not specified
-->
<object name="DemoHandler.ashx">
<property name="OutputText">
<value>This text is injected via Spring</value>
</property>
</object>
</objects>
</spring>
</configuration>

View File

@@ -17,6 +17,8 @@
<p>The inevitable "Hello World!" example demonstrates DI for pages, usercontrols and webcontrols</p>
<h3><a href="NestedContexts/Default.aspx">Nested Contexts</a></h3>
<p>This sample shows, how contexts are nested in webapplications</p>
<h3><a href="CustomHandlers/Default.aspx">Custom HTTP Handlers</a></h3>
<p>This sample shows, how to configure your custom IHttpHandler and IHttpHandlerFactory implementations</p>
</div>
</body>
</html>

View File

@@ -120,12 +120,13 @@ namespace Spring.Web.Script.Services
/// <summary>
/// Create a handler instance for the given URL.
/// </summary>
/// <param name="appContext">the application context corresponding to the current request</param>
/// <param name="context">The <see cref="HttpContext"/> instance for this request.</param>
/// <param name="requestType">The HTTP data transfer method (GET, POST, ...)</param>
/// <param name="url">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="rawUrl">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="physicalPath">The physical path of the requested resource.</param>
/// <returns>A handler instance for the current request.</returns>
protected override IHttpHandler CreateHandlerInstance( HttpContext context, string requestType, string url, string physicalPath )
protected override IHttpHandler CreateHandlerInstance( IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath )
{
throw new NotSupportedException();
}

View File

@@ -88,28 +88,28 @@ namespace Spring.Context.Support
/// </summary>
static WebSupportModule()
{
s_log = LogManager.GetLogger( typeof( WebSupportModule ) );
s_log = LogManager.GetLogger(typeof(WebSupportModule));
// register additional resource handler
ResourceHandlerRegistry.RegisterResourceHandler( WebUtils.DEFAULT_RESOURCE_PROTOCOL, typeof( WebResource ) );
ResourceHandlerRegistry.RegisterResourceHandler(WebUtils.DEFAULT_RESOURCE_PROTOCOL, typeof(WebResource));
// replace default IResource converter
TypeConverterRegistry.RegisterConverter( typeof( IResource ),
TypeConverterRegistry.RegisterConverter(typeof(IResource),
new ResourceConverter(
new ConfigurableResourceLoader( WebUtils.DEFAULT_RESOURCE_PROTOCOL ) ) );
new ConfigurableResourceLoader(WebUtils.DEFAULT_RESOURCE_PROTOCOL)));
// default to hybrid thread storage implementation
LogicalThreadContext.SetStorage( new HybridContextStorage() );
LogicalThreadContext.SetStorage(new HybridContextStorage());
s_log.Debug( "Set default resource protocol to 'web' and installed HttpContext-aware HybridContextStorage" );
s_log.Debug("Set default resource protocol to 'web' and installed HttpContext-aware HybridContextStorage");
}
/// <summary>
/// Registers this module for all events required by the Spring.Web framework
/// </summary>
public virtual void Init( HttpApplication app )
public virtual void Init(HttpApplication app)
{
lock (typeof( WebSupportModule ))
lock (typeof(WebSupportModule))
{
s_log.Debug( "Initializing Application instance" );
s_log.Debug("Initializing Application instance");
if (!s_isInitialized)
{
HttpModuleCollection modules = app.Modules;
@@ -118,7 +118,7 @@ namespace Spring.Context.Support
if (modules[moduleKey] is SessionStateModule)
{
#if !NET_1_1
HookSessionEvent( (SessionStateModule)modules[moduleKey] );
HookSessionEvent((SessionStateModule)modules[moduleKey]);
#else
HookSessionEvent11();
#endif
@@ -132,57 +132,92 @@ namespace Spring.Context.Support
VirtualEnvironment.SetInitialized();
}
app.PreRequestHandlerExecute += new EventHandler( OnPreRequestHandlerExecute );
app.EndRequest += new EventHandler( VirtualEnvironment.RaiseEndRequest );
app.PreRequestHandlerExecute += new EventHandler(OnConfigureHandler);
app.EndRequest += new EventHandler(VirtualEnvironment.RaiseEndRequest);
// ensure context is instantiated
IConfigurableApplicationContext appContext = WebApplicationContext.GetRootContext() as IConfigurableApplicationContext;
// configure this app + it's module instances
if (appContext == null)
{
throw new InvalidOperationException( "Implementations of IApplicationContext must also implement IConfigurableApplicationContext" );
throw new InvalidOperationException("Implementations of IApplicationContext must also implement IConfigurableApplicationContext");
}
HttpApplicationConfigurer.Configure( appContext, app );
HttpApplicationConfigurer.Configure(appContext, app);
}
#region IHttpHandler configuration
///<summary>
/// Configures the current IHttpHandler as specified by <see cref="Spring.Web.Support.PageHandlerFactory"/>.
///</summary>
private void OnPreRequestHandlerExecute( object sender, EventArgs e )
private void OnConfigureHandler(object sender, EventArgs e)
{
HandlerConfigurationMetaData hCfg = (HandlerConfigurationMetaData)LogicalThreadContext.GetData( CURRENTHANDLER_OBJECTDEFINITION );
HandlerConfigurationMetaData hCfg = (HandlerConfigurationMetaData)LogicalThreadContext.GetData(CURRENTHANDLER_OBJECTDEFINITION);
if (hCfg != null)
{
HttpApplication app = (HttpApplication)sender;
//app.Context.Handler =
ConfigureHandler( app.Context.Handler, hCfg.ApplicationContext, hCfg.ObjectDefinitionName, hCfg.IsContainerManaged );
// app.Context.Handler = // TODO: check, if this makes sense (EE)
ConfigureHandlerNow(app.Context.Handler, hCfg.ApplicationContext, hCfg.ObjectDefinitionName, hCfg.IsContainerManaged);
}
}
/// <summary>
/// Configures the specified handler instance using the object definition <paramref name="name"/>.
/// </summary>
/// <remarks>
/// TODO
/// </remarks>
/// <param name="context"></param>
/// <param name="handler"></param>
/// <param name="applicationContext"></param>
/// <param name="name"></param>
/// <param name="isContainerManaged"></param>
/// <returns></returns>
public static IHttpHandler ConfigureHandler(HttpContext context, IHttpHandler handler, IConfigurableApplicationContext applicationContext, string name, bool isContainerManaged)
{
if (context.Handler != null)
{
s_log.Debug(string.Format("previous handler is present - configuring handler now using application context '{0}' and name '{1}'", applicationContext, name));
// this is a Server.Execute() or Server.Transfer() request -> configure immediately
return ConfigureHandlerNow(handler, applicationContext, name, isContainerManaged);
}
else
{
// remember the resolved object definition name for applying it during PreRequestHandlerExecute
s_log.Debug(string.Format("no previous handler is present - defer handler configuration using application context '{0}' and name '{1}'", applicationContext, name));
SetCurrentHandlerConfiguration(applicationContext, name, isContainerManaged);
return handler;
}
}
///<summary>
/// TODO
///</summary>
///<param name="applicationContext"></param>
///<param name="name"></param>
///<param name="isContainerManaged"></param>
public static void SetCurrentHandlerConfiguration( IConfigurableApplicationContext applicationContext, string name, bool isContainerManaged )
private static void SetCurrentHandlerConfiguration(IConfigurableApplicationContext applicationContext, string name, bool isContainerManaged)
{
LogicalThreadContext.SetData( CURRENTHANDLER_OBJECTDEFINITION, new HandlerConfigurationMetaData(applicationContext, name, isContainerManaged) );
LogicalThreadContext.SetData(CURRENTHANDLER_OBJECTDEFINITION, new HandlerConfigurationMetaData(applicationContext, name, isContainerManaged));
}
///<summary>
/// TODO
///</summary>
///<param name="handler"></param>
///<param name="applicationContext"></param>
///<param name="name"></param>
///<param name="isContainerManaged"></param>
public static IHttpHandler ConfigureHandler( IHttpHandler handler, IConfigurableApplicationContext applicationContext, string name, bool isContainerManaged)
private static IHttpHandler ConfigureHandlerNow(IHttpHandler handler, IConfigurableApplicationContext applicationContext, string name, bool isContainerManaged)
{
if (isContainerManaged)
{
handler = (IHttpHandler)applicationContext.ObjectFactory.ConfigureObject( handler, name );
s_log.Debug(string.Format("configuring managed handler using application context '{0}' and name '{1}'", applicationContext, name));
handler = (IHttpHandler)applicationContext.ObjectFactory.ConfigureObject(handler, name);
}
else
{
s_log.Debug(string.Format("configuring unmanaged handler using application context '{0}' and name '{1}'", applicationContext, name));
// at a minimum we'll apply ObjectPostProcessors
handler = (IHttpHandler)applicationContext.ObjectFactory.ApplyObjectPostProcessorsBeforeInitialization(handler, name);
handler = (IHttpHandler)applicationContext.ObjectFactory.ApplyObjectPostProcessorsAfterInitialization(handler, name);
@@ -191,6 +226,8 @@ namespace Spring.Context.Support
return handler;
}
#endregion
/// <summary>
/// Disposes this instance
/// </summary>
@@ -201,15 +238,15 @@ namespace Spring.Context.Support
#region Session Handling Stuff
private static void OnCacheItemRemoved( string key, object value, CacheItemRemovedReason reason )
private static void OnCacheItemRemoved(string key, object value, CacheItemRemovedReason reason)
{
s_log.Debug( "end session " + key + " because of " + reason );
s_log.Debug("end session " + key + " because of " + reason);
try
{
HttpSessionState ss = CreateSessionState( key, value );
HttpSessionState ss = CreateSessionState(key, value);
VirtualEnvironment.RaiseEndSession( ss, reason );
VirtualEnvironment.RaiseEndSession(ss, reason);
}
catch (Exception ex)
{
@@ -217,51 +254,51 @@ namespace Spring.Context.Support
// are we on a current request?
if (HttpContext.Current != null)
{
s_log.Error( msg, ex );
s_log.Error(msg, ex);
}
else
{
// this is an async session timout - log as fatal since this is the thread's exit point!
s_log.Fatal( msg, ex );
s_log.Fatal(msg, ex);
}
}
finally
{
if (s_originalCallback != null)
{
s_originalCallback( key, value, reason );
s_originalCallback(key, value, reason);
}
}
}
#if !NET_1_1
private static void HookSessionEvent( SessionStateModule sessionStateModule )
private static void HookSessionEvent(SessionStateModule sessionStateModule)
{
// Hook only into InProcState - all others ignore SessionEnd anyway
object store = ExpressionEvaluator.GetValue( sessionStateModule, "_store" );
object store = ExpressionEvaluator.GetValue(sessionStateModule, "_store");
if ((store != null) && store.GetType().Name == "InProcSessionStateStore")
{
s_log.Debug( "attaching to InProcSessionStateStore" );
s_originalCallback = (CacheItemRemovedCallback)ExpressionEvaluator.GetValue( store, "_callback" );
ExpressionEvaluator.SetValue( store, "_callback", new CacheItemRemovedCallback( OnCacheItemRemoved ) );
s_log.Debug("attaching to InProcSessionStateStore");
s_originalCallback = (CacheItemRemovedCallback)ExpressionEvaluator.GetValue(store, "_callback");
ExpressionEvaluator.SetValue(store, "_callback", new CacheItemRemovedCallback(OnCacheItemRemoved));
CACHEKEYPREFIXLENGTH = (int)ExpressionEvaluator.GetValue( store, "CACHEKEYPREFIXLENGTH" );
CACHEKEYPREFIXLENGTH = (int)ExpressionEvaluator.GetValue(store, "CACHEKEYPREFIXLENGTH");
}
}
private static HttpSessionState CreateSessionState( string key, object state )
private static HttpSessionState CreateSessionState(string key, object state)
{
string id = key.Substring( CACHEKEYPREFIXLENGTH );
string id = key.Substring(CACHEKEYPREFIXLENGTH);
ISessionStateItemCollection sessionItems =
(ISessionStateItemCollection)ExpressionEvaluator.GetValue( state, "_sessionItems" );
(ISessionStateItemCollection)ExpressionEvaluator.GetValue(state, "_sessionItems");
HttpStaticObjectsCollection staticObjects =
(HttpStaticObjectsCollection)ExpressionEvaluator.GetValue( state, "_staticObjects" );
int timeout = (int)ExpressionEvaluator.GetValue( state, "_timeout" );
TypeRegistry.RegisterType( "SessionStateModule", typeof( SessionStateModule ) );
(HttpStaticObjectsCollection)ExpressionEvaluator.GetValue(state, "_staticObjects");
int timeout = (int)ExpressionEvaluator.GetValue(state, "_timeout");
TypeRegistry.RegisterType("SessionStateModule", typeof(SessionStateModule));
HttpCookieMode cookieMode =
(HttpCookieMode)ExpressionEvaluator.GetValue( null, "SessionStateModule.s_configCookieless" );
(HttpCookieMode)ExpressionEvaluator.GetValue(null, "SessionStateModule.s_configCookieless");
SessionStateMode stateMode =
(SessionStateMode)ExpressionEvaluator.GetValue( null, "SessionStateModule.s_configMode" );
(SessionStateMode)ExpressionEvaluator.GetValue(null, "SessionStateModule.s_configMode");
HttpSessionStateContainer container = new HttpSessionStateContainer(
id
, sessionItems
@@ -274,7 +311,7 @@ namespace Spring.Context.Support
);
return (HttpSessionState)Activator.CreateInstance(
typeof( HttpSessionState )
typeof(HttpSessionState)
, BindingFlags.Instance | BindingFlags.NonPublic
, null
, new object[] { container }

View File

@@ -125,6 +125,10 @@
<Compile Include="Util\ISessionState.cs" />
<Compile Include="Web\Support\DefaultResultFactory.cs" />
<Compile Include="Web\Support\DefaultResultWebNavigator.cs" />
<Compile Include="Web\Support\MappingHandlerFactory.cs" />
<Compile Include="Web\Support\MappingHandlerFactoryConfigurer.cs" />
<Compile Include="Web\Support\HandlerMap.cs" />
<Compile Include="Web\Support\HandlerMapEntry.cs" />
<Compile Include="Web\Support\IHierarchicalWebNavigator.cs" />
<Compile Include="Web\Support\IResult.cs" />
<Compile Include="Web\Support\IResultFactory.cs" />
@@ -132,7 +136,9 @@
<Compile Include="Web\Support\IWebNavigable.cs" />
<Compile Include="Web\Support\IWebNavigator.cs" />
<Compile Include="Web\Support\ResultFactoryRegistry.cs" />
<Compile Include="Web\Support\DefaultHandlerFactory.cs" />
<Compile Include="Web\Support\WebFormsResultWebNavigator.cs" />
<Compile Include="Web\Support\WebNavigableWebNavigatorAdapter.cs" />
<Compile Include="Web\UI\IValidationContainer.cs" />
<Compile Include="Web\Support\MimeMediaType.cs" />
<Compile Include="Web\Support\SharedStateResourceCache.cs">

View File

@@ -124,9 +124,14 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Util\ISessionState.cs" />
<Compile Include="Web\Support\DefaultHandlerFactory.cs" />
<Compile Include="Web\Support\DefaultResultFactory.cs" />
<Compile Include="Web\Support\HandlerMap.cs" />
<Compile Include="Web\Support\HandlerMapEntry.cs" />
<Compile Include="Web\Support\IResult.cs" />
<Compile Include="Web\Support\IResultFactory.cs" />
<Compile Include="Web\Support\MappingHandlerFactory.cs" />
<Compile Include="Web\Support\MappingHandlerFactoryConfigurer.cs" />
<Compile Include="Web\Support\ResultFactoryRegistry.cs" />
<Compile Include="Web\Support\WebFormsResultWebNavigator.cs" />
<Compile Include="Web\Support\IHierarchicalWebNavigator.cs" />

View File

@@ -24,6 +24,7 @@ using System;
using System.Collections;
using System.IO;
using System.Web;
using System.Web.UI;
using Common.Logging;
using Spring.Collections;
using Spring.Context;
@@ -90,6 +91,32 @@ namespace Spring.Web.Support
/// </summary>
private readonly IDictionary _reusableHandlerCache = new CaseInsensitiveHashtable();
/// <summary>
/// Holds an instance of the instrinsic System.Web.UI.SimpleHandlerFactory
/// </summary>
private static IHttpHandlerFactory s_simpleHandlerFactory;
/// <summary>
/// Get the global instance of System.Web.UI.SimpleHandlerFactory
/// </summary>
/// <remarks>
/// This factory is a plaform version agnostic way to instantiate
/// arbitrary handlers without the need for additional reflection.
/// </remarks>
public static IHttpHandlerFactory SimpleHandlerFactory
{
get
{
// instantiate lazy to avoid security exceptions in restricted reflection environments
if (s_simpleHandlerFactory == null)
{
Type simpleHandlerFactoryType = typeof(IHttpHandler).Assembly.GetType("System.Web.UI.SimpleHandlerFactory");
s_simpleHandlerFactory = (IHttpHandlerFactory)Activator.CreateInstance(simpleHandlerFactoryType, true);
}
return s_simpleHandlerFactory;
}
}
/// <summary>
/// Holds the shared logger for all factories.
/// </summary>
@@ -158,7 +185,11 @@ namespace Spring.Web.Support
handler = (IHttpHandler)_reusableHandlerCache[url];
if (handler == null)
{
handler = CreateHandlerInstance( context, requestType, url, physicalPath );
IConfigurableApplicationContext appContext = GetCheckedApplicationContext(url);
handler = CreateHandlerInstance( appContext, context, requestType, url, physicalPath );
ApplyDependencyInjectionInfrastructure(handler, appContext);
if (handler.IsReusable)
{
@@ -182,12 +213,13 @@ namespace Spring.Web.Support
/// <summary>
/// Create a handler instance for the given URL.
/// </summary>
/// <param name="appContext">the application context corresponding to the current request</param>
/// <param name="context">The <see cref="HttpContext"/> instance for this request.</param>
/// <param name="requestType">The HTTP data transfer method (GET, POST, ...)</param>
/// <param name="url">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="rawUrl">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="physicalPath">The physical path of the requested resource.</param>
/// <returns>A handler instance for processing the current request.</returns>
protected abstract IHttpHandler CreateHandlerInstance( HttpContext context, string requestType, string url, string physicalPath );
protected abstract IHttpHandler CreateHandlerInstance( IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath );
/// <summary>
/// Get the application context instance corresponding to the given absolute url and checks
@@ -292,5 +324,26 @@ namespace Spring.Web.Support
return (pageDefinition == null) ? (NamedObjectDefinition)null : new NamedObjectDefinition( objectDefinitionName, pageDefinition );
}
/// <summary>
/// Apply dependency injection stuff on the handler.
/// </summary>
/// <param name="handler">the handler to be intercepted</param>
/// <param name="applicationContext">the context responsible for configuring this handler</param>
private static void ApplyDependencyInjectionInfrastructure(IHttpHandler handler, IApplicationContext applicationContext)
{
if (handler is Control)
{
ControlInterceptor.EnsureControlIntercepted(applicationContext, (Control)handler);
}
else
{
if ( (handler is ISupportsWebDependencyInjection)
&& (((ISupportsWebDependencyInjection)handler).DefaultApplicationContext == null) )
{
((ISupportsWebDependencyInjection)handler).DefaultApplicationContext = applicationContext;
}
}
}
}
}

View File

@@ -0,0 +1,104 @@
#region License
/*
* Copyright <20> 2002-2008 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.Web;
using Spring.Context;
using Spring.Context.Support;
using Spring.Util;
#endregion
namespace Spring.Web.Support
{
/// <summary>
/// SimpleHandlerFactory is used to wrap any arbitrary <see cref="IHttpHandlerFactory"/> to make it "Spring-aware".
/// </summary>
/// <remarks>
/// By default, an instance of <see cref="System.Web.UI.SimpleHandlerFactory"/> is used as underlying factory.
/// </remarks>
/// <author>Erich Eichinger</author>
public class DefaultHandlerFactory : AbstractHandlerFactory
{
private readonly IHttpHandlerFactory _innerFactory;
/// <summary>
/// Creates a new instance, using a <see cref="System.Web.UI.SimpleHandlerFactory"/> as underlying factory.
/// </summary>
public DefaultHandlerFactory()
: this(SimpleHandlerFactory)
{ }
/// <summary>
/// Create a new instance, using an instance of <paramref name="innerFactoryType"/> as underlying factory.
/// </summary>
/// <param name="innerFactoryType">a type that implements <see cref="IHttpHandlerFactory"/></param>
public DefaultHandlerFactory(Type innerFactoryType)
: this((IHttpHandlerFactory)Activator.CreateInstance(innerFactoryType, true))
{
}
/// <summary>
/// Create a new instance, using <paramref name="innerFactory"/> as underlying factory.
/// </summary>
/// <param name="innerFactory">the factory to be wrapped.</param>
public DefaultHandlerFactory(IHttpHandlerFactory innerFactory)
{
AssertUtils.ArgumentNotNull(innerFactory, "innerFactory");
_innerFactory = innerFactory;
}
/// <summary>
/// Create a handler instance for the given URL.
/// </summary>
/// <param name="appContext">the application context corresponding to the current request</param>
/// <param name="context">The <see cref="HttpContext"/> instance for this request.</param>
/// <param name="requestType">The HTTP data transfer method (GET, POST, ...)</param>
/// <param name="rawUrl">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="physicalPath">The physical path of the requested resource.</param>
/// <returns>A handler instance for processing the current request.</returns>
protected override IHttpHandler CreateHandlerInstance(IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath)
{
IHttpHandler handler = _innerFactory.GetHandler(context, requestType, rawUrl, physicalPath);
// find a matching object definition
string appRelativeVirtualPath = WebUtils.GetAppRelativePath(rawUrl);
NamedObjectDefinition nod = FindWebObjectDefinition(appRelativeVirtualPath, appContext.ObjectFactory);
string objectDefinitionName = (nod != null) ? nod.Name : rawUrl;
handler = WebSupportModule.ConfigureHandler(context, handler, appContext, objectDefinitionName, (nod != null));
return handler;
}
/// <summary>
/// Enables a factory to release an existing
/// <see cref="System.Web.IHttpHandler"/> instance.
/// </summary>
/// <param name="handler">
/// The <see cref="System.Web.IHttpHandler"/> object to release.
/// </param>
public override void ReleaseHandler(IHttpHandler handler)
{
_innerFactory.ReleaseHandler(handler);
}
}
}

View File

@@ -0,0 +1,238 @@
#region License
/*
* Copyright <20> 2002-2008 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.Text.RegularExpressions;
using System.Web;
using Common.Logging;
#endregion
namespace Spring.Web.Support
{
/// <summary>
/// Holds a list of url <see cref="Regex"/> expressions and their corresponding names of responsible <see cref="IHttpHandlerFactory"/>
/// or <see cref="IHttpHandler"/> objects managed by the container.
/// </summary>
/// <author>Erich Eichinger</author>
public class HandlerMap : IDictionary
{
private readonly ILog Log = LogManager.GetLogger(typeof(HandlerMap));
private ArrayList _internalTable = new ArrayList();
/// <summary>
/// Maps the specified url pattern expression to an object name denoting a <see cref="IHttpHandlerFactory"/> or <see cref="IHttpHandler"/> object.
/// </summary>
/// <param name="urlPattern">the string pattern (see conform to <see cref="Regex"/> syntax)</param>
/// <param name="handlerObjectName">an object name denoting the spring-managed handler definition</param>
public void Add(string urlPattern, string handlerObjectName)
{
this._internalTable.Add( new HandlerMapEntry(urlPattern, handlerObjectName) );
}
/// <summary>
/// Maps the specified url pattern expression to an object name denoting a <see cref="IHttpHandlerFactory"/> or <see cref="IHttpHandler"/> object.
/// </summary>
/// <param name="urlPattern">the url pattern</param>
/// <param name="handlerObjectName">an object name denoting the spring-managed handler definition</param>
public void Add(Regex urlPattern, string handlerObjectName)
{
this._internalTable.Add( new HandlerMapEntry(urlPattern, handlerObjectName) );
}
/// <summary>
/// Maps the <paramref name="virtualPath"/> to a handler object name by matching against all registered patterns.
/// </summary>
/// <param name="virtualPath">the virtual path</param>
/// <returns>the object name</returns>
public HandlerMapEntry MapPath( string virtualPath )
{
if(Log.IsDebugEnabled) Log.Debug( string.Format( "looking up mapping for url '{0}'", virtualPath ) );
for(int i=0;i<this._internalTable.Count;i++)
{
HandlerMapEntry handlerMapEntry = (HandlerMapEntry)this._internalTable[i];
if ( handlerMapEntry.UrlPattern.IsMatch( virtualPath ) )
{
if (Log.IsDebugEnabled) Log.Debug(string.Format("found mapping '{0}' for url '{1}'", handlerMapEntry, virtualPath));
return handlerMapEntry;
}
}
if (Log.IsDebugEnabled) Log.Debug(string.Format("no mapping found for url '{0}'", virtualPath));
return null;
}
/// <summary>
/// Add a new mapping
/// </summary>
/// <param name="key">an url pattern string</param>
/// <param name="value">a handler object name string</param>
void IDictionary.Add(object key, object value)
{
this.Add((string) key, (string) value);
}
/// <summary>
/// Add or replace a mapping
/// </summary>
/// <remarks>
/// Getter will throw a <see cref="NotSupportedException"/>!
/// </remarks>
/// <param name="key">an url pattern string</param>
object IDictionary.this[object key]
{
get
{
throw new NotSupportedException();
}
set
{
this.Add( (string)key,(string)value );
}
}
/// <summary>
/// Clear the mapping table.
/// </summary>
public void Clear()
{
this._internalTable.Clear();
}
/// <summary>
/// Always returns false.
/// </summary>
public bool IsReadOnly
{
get
{
return false;
// return this._internalTable.IsReadOnly;
}
}
///<summary>
///Gets a value indicating whether the <see cref="T:System.Collections.IDictionary"></see> object has a fixed size.
///</summary>
///
///<returns>
///true if the <see cref="T:System.Collections.IDictionary"></see> object has a fixed size; otherwise, false.
///</returns>
///<filterpriority>2</filterpriority>
public bool IsFixedSize
{
get { return false; /*return this._internalTable.IsFixedSize;*/ }
}
///<summary>
///Copies all <see cref="HandlerMapEntry"/> entries to the specified array.
///</summary>
public void CopyTo(Array array, int index)
{
this._internalTable.CopyTo(array, index);
}
/// <summary>
/// Get the number of registered mappings.
/// </summary>
public int Count
{
get { return this._internalTable.Count; }
}
///<summary>
///Gets an object that can be used to synchronize access.
///</summary>
public object SyncRoot
{
get { return this._internalTable.SyncRoot; }
}
/// <summary>
/// Always returns false.
/// </summary>
public bool IsSynchronized
{
get { return false; /*return this._internalTable.IsSynchronized;*/ }
}
/// <summary>
/// Get an enumerator for iterating over the list of registered mappings.
/// </summary>
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable) this._internalTable).GetEnumerator();
}
#region Unsupported methods
/// <summary>
/// Not supported by this implementation.
/// </summary>
bool IDictionary.Contains(object key)
{
throw new NotSupportedException();
}
/// <summary>
/// Not supported by this implementation.
/// </summary>
IDictionaryEnumerator IDictionary.GetEnumerator()
{
throw new NotSupportedException();
}
/// <summary>
/// Not supported by this implementation.
/// </summary>
void IDictionary.Remove(object key)
{
throw new NotSupportedException();
}
/// <summary>
/// Not supported by this implementation.
/// </summary>
ICollection IDictionary.Keys
{
get
{
throw new NotSupportedException();
}
}
/// <summary>
/// Not supported by this implementation.
/// </summary>
ICollection IDictionary.Values
{
get
{
throw new NotSupportedException();
}
}
#endregion
}
}

View File

@@ -0,0 +1,92 @@
#region License
/*
* Copyright <20> 2002-2008 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.Text.RegularExpressions;
using Spring.Util;
#endregion
namespace Spring.Web.Support
{
/// <summary>
/// Holds pairs of (url pattern, handler object name).
/// </summary>
/// <seealso cref="HandlerMap"/>
/// <seealso cref="MappingHandlerFactory"/>
/// <seealso cref="MappingHandlerFactoryConfigurer"/>
/// <author>Erich Eichinger</author>
public class HandlerMapEntry
{
private Regex _urlPattern;
private string _handlerObjectName;
/// <summary>
/// Create a new instance.
/// </summary>
/// <param name="urlPattern"></param>
/// <param name="handlerObjectName"></param>
public HandlerMapEntry(string urlPattern, string handlerObjectName)
{
AssertUtils.ArgumentNotNull(urlPattern, "urlPattern");
AssertUtils.ArgumentNotNull(handlerObjectName, "handlerObjectName");
this._urlPattern = new Regex(urlPattern, RegexOptions.Compiled|RegexOptions.ECMAScript|RegexOptions.CultureInvariant|RegexOptions.IgnoreCase);
this._handlerObjectName = handlerObjectName;
}
///<summary>
/// Create a new instance
///</summary>
///<param name="urlPattern"></param>
///<param name="handlerObjectName"></param>
public HandlerMapEntry(Regex urlPattern, string handlerObjectName)
{
AssertUtils.ArgumentNotNull(urlPattern, "urlPattern");
AssertUtils.ArgumentNotNull(handlerObjectName, "handlerObjectName");
this._urlPattern = urlPattern;
this._handlerObjectName = handlerObjectName;
}
///<summary>
/// Get the url pattern
///</summary>
public Regex UrlPattern
{
get { return this._urlPattern; }
}
/// <summary>
/// Get the handler object name
/// </summary>
public string HandlerObjectName
{
get { return this._handlerObjectName; }
}
/// <summary>
/// Return a string representation of this entry.
/// </summary>
public override string ToString()
{
return string.Format("HandlerMapEntry['{0}','{1}']", _urlPattern, _handlerObjectName);
}
}
}

View File

@@ -0,0 +1,175 @@
#region License
/*
* Copyright <20> 2002-2008 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.Collections;
using System.Net;
using System.Web;
using Spring.Context;
using Spring.Context.Support;
#endregion
namespace Spring.Web.Support
{
/// <summary>
/// MappingHandleryFactory allows for full Spring-managed &lt;httpHandlers&gt; configuration.
/// It uses regular expressions for url matching.
/// </summary>
/// <remarks>
/// <example>
/// The example below shows, how to map all url requests to spring and let
/// <see cref="MappingHandlerFactory"/> resolve urls to container-managed <see cref="IHttpHandlerFactory"/> or <see cref="IHttpHandler"/> objects.
/// <code>
/// // web.config
///
/// &lt;httpHandlers&gt;
/// &lt;!-- map all requests to spring (just for demo - don't do this at home!) --&gt;
/// &lt;add verb=&quot;*&quot; path=&quot;*.*&quot; type=&quot;Spring.Web.Support.MappingHandlerFactory, Spring.Web&quot; /&gt;
/// &lt;/httpHandlers&gt;
///
/// // spring-objects.config
///
/// &lt;object type=&quot;Spring.Web.Support.MappingHandlerFactoryConfigurer, Spring.Web&quot;&gt;
/// &lt;property name=&quot;HandlerMap&quot;&gt;
/// &lt;dictionary&gt;
/// &lt;entry key=&quot;\.ashx$&quot; value=&quot;standardHandlerFactory&quot; /&gt;
/// &lt;!-- map any request ending with *.whatever to standardHandlerFactory --&gt;
/// &lt;entry key=&quot;\.whatever$&quot; value=&quot;specialHandlerFactory&quot; /&gt;
/// &lt;/dictionary&gt;
/// &lt;/property&gt;
/// &lt;/object&gt;
///
/// &lt;object name=&quot;standardHandlerFactory&quot; type=&quot;Spring.Web.Support.DefaultHandlerFactory, Spring.Web&quot; /&gt;
///
/// &lt;object name=&quot;specialHandlerFactory&quot; type=&quot;MySpecialHandlerFactoryImpl&quot; /&gt;
/// </code>
/// </example>
/// </remarks>
/// <seealso cref="IHttpHandlerFactory"/>
/// <seealso cref="IHttpHandler"/>
/// <seealso cref="HandlerMap"/>
/// <seealso cref="MappingHandlerFactoryConfigurer"/>
/// <author>Erich Eichinger</author>
public class MappingHandlerFactory : AbstractHandlerFactory
{
private static readonly HandlerMap s_handlerMap = new HandlerMap();
/// <summary>
/// Holds the global list of mappings from url patterns to handler names.
/// </summary>
public static HandlerMap HandlerMap
{
get { return s_handlerMap; }
}
/// <summary>
/// Holds the cache of handler/factory pairs handed out by this factory. This is required
/// for proper handling of <see cref="IHttpHandlerFactory.ReleaseHandler"/>.
/// </summary>
private readonly Hashtable _handlerWithFactoryTable = new Hashtable();
/// <summary>
/// Create a handler instance for the given URL. Will try to find a match of <paramref name="rawUrl"/> onto patterns in <see cref="HandlerMap"/>.
/// If a match is found, delegates the call to the matching <see cref="IHttpHandlerFactory.GetHandler"/> method.
/// </summary>
/// <param name="appContext">the application context corresponding to the current request</param>
/// <param name="context">The <see cref="HttpContext"/> instance for this request.</param>
/// <param name="requestType">The HTTP data transfer method (GET, POST, ...)</param>
/// <param name="rawUrl">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="physicalPath">The physical path of the requested resource.</param>
/// <returns>A handler instance for processing the current request.</returns>
protected override IHttpHandler CreateHandlerInstance(IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath)
{
return MapHandlerInstance(appContext, context, requestType, rawUrl, physicalPath, s_handlerMap, _handlerWithFactoryTable);
}
/// <summary>
/// Obtains a handler by mapping <paramref name="rawUrl"/> to the list of patterns in <paramref name="handlerMappings"/>.
/// </summary>
/// <param name="appContext">the application context corresponding to the current request</param>
/// <param name="context">The <see cref="HttpContext"/> instance for this request.</param>
/// <param name="requestType">The HTTP data transfer method (GET, POST, ...)</param>
/// <param name="rawUrl">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="physicalPath">The physical path of the requested resource.</param>
/// <param name="handlerMappings"></param>
/// <param name="handlerWithFactoryTable"></param>
/// <returns>A handler instance for processing the current request.</returns>
protected IHttpHandler MapHandlerInstance(IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath, HandlerMap handlerMappings, IDictionary handlerWithFactoryTable)
{
// resolve handler instance by mapping the url to the list of patterns
HandlerMapEntry handlerMapEntry = handlerMappings.MapPath(rawUrl);
if (handlerMapEntry == null)
{
throw new HttpException(404, HttpStatusCode.NotFound.ToString());
}
object handlerObject = appContext.GetObject(handlerMapEntry.HandlerObjectName);
if (handlerObject is IHttpHandler)
{
return (IHttpHandler) handlerObject;
}
else if (handlerObject is IHttpHandlerFactory)
{
// keep a reference to the issuing factory for later ReleaseHandler call
IHttpHandlerFactory factory = (IHttpHandlerFactory) handlerObject;
IHttpHandler handler = factory.GetHandler(context, requestType, rawUrl, physicalPath);
lock(handlerWithFactoryTable.SyncRoot)
{
handlerWithFactoryTable.Add(handler, factory);
}
return handler;
}
throw new HttpException((int)HttpStatusCode.NotFound, HttpStatusCode.NotFound.ToString());
}
/// <summary>
/// Enables a factory to release an existing
/// <see cref="System.Web.IHttpHandler"/> instance.
/// </summary>
/// <param name="handler">
/// The <see cref="System.Web.IHttpHandler"/> object to release.
/// </param>
public override void ReleaseHandler(IHttpHandler handler)
{
ReleaseHandler(handler, this._handlerWithFactoryTable);
}
/// <summary>
/// Removes the handler from the handler/factory dictionary and releases the handler.
/// </summary>
/// <param name="handler">the handler to be released</param>
/// <param name="_handlerWithFactoryTable">a dictionary containing (<see cref="IHttpHandler"/>, <see cref="IHttpHandlerFactory"/>) entries.</param>
protected void ReleaseHandler( IHttpHandler handler, IDictionary _handlerWithFactoryTable )
{
lock (_handlerWithFactoryTable.SyncRoot)
{
IHttpHandlerFactory factory = _handlerWithFactoryTable[handler] as IHttpHandlerFactory;
if (factory != null)
{
_handlerWithFactoryTable.Remove(handler);
factory.ReleaseHandler(handler);
}
}
}
}
}

View File

@@ -0,0 +1,67 @@
#region License
/*
* Copyright <20> 2002-2008 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
#endregion
namespace Spring.Web.Support
{
/// <summary>
/// Configures <see cref="MappingHandlerFactory"/>.
/// </summary>
/// <author>Erich Eichinger</author>
public class MappingHandlerFactoryConfigurer
// : Spring.Objects.Factory.Config.IObjectPostProcessor // just a trick to have
{
/// <summary>
/// Contains mappings of url patterns to handler objects.
/// </summary>
public HandlerMap HandlerMap
{
get
{
return MappingHandlerFactory.HandlerMap;
}
// set
// {
// AssertUtils.ArgumentNotNull(value, "HandlerMap");
// foreach(HandlerMapEntry mapEntry in value)
// {
// GenericHandlerFactory.HandlerMap[mapEntry.UrlPattern] = mapEntry;
// }
// }
}
#region IObjectPostProcessor implementation
// object IObjectPostProcessor.PostProcessBeforeInitialization(object instance, string name)
// {
// return instance;
// }
//
// object IObjectPostProcessor.PostProcessAfterInitialization(object instance, string objectName)
// {
// return instance;
// }
#endregion
}
}

View File

@@ -82,22 +82,17 @@ namespace Spring.Web.Support
/// <summary>
/// Create a handler instance for the given URL.
/// </summary>
/// <param name="appContext">the application context corresponding to the current request</param>
/// <param name="context">The <see cref="HttpContext"/> instance for this request.</param>
/// <param name="requestType">The HTTP data transfer method (GET, POST, ...)</param>
/// <param name="url">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="rawUrl">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="physicalPath">The physical path of the requested resource.</param>
/// <returns>A handler instance for the current request.</returns>
protected override IHttpHandler CreateHandlerInstance(HttpContext context, string requestType, string url, string physicalPath)
protected override IHttpHandler CreateHandlerInstance(IConfigurableApplicationContext appContext, HttpContext context, string requestType, string rawUrl, string physicalPath)
{
IHttpHandler handler;
IConfigurableApplicationContext appContext = GetCheckedApplicationContext(url);
if (appContext == null)
{
throw new InvalidOperationException("PageHandlerFactory requires an IConfigurableApplicationContext");
}
string appRelativeVirtualPath = WebUtils.GetAppRelativePath(url);
string appRelativeVirtualPath = WebUtils.GetAppRelativePath(rawUrl);
NamedObjectDefinition namedPageDefinition = FindWebObjectDefinition(appRelativeVirtualPath, appContext.ObjectFactory);
if (namedPageDefinition != null)
@@ -113,50 +108,17 @@ namespace Spring.Web.Support
// execution pipeline "entry-point" - create page instance only
// and defer configuration to PreRequestHandlerExecute step
handler = (IHttpHandler)appContext.CreateObject(namedPageDefinition.Name, typeof(IHttpHandler), null);
WebSupportModule.ConfigureHandler(context, handler, appContext, namedPageDefinition.Name, true);
}
WebSupportModule.SetCurrentHandlerConfiguration(appContext, namedPageDefinition.Name, true);
}
else
{
handler = WebObjectUtils.CreateHandler(context, url);
// is this a nested call (HttpServerUtility.Transfer() or HttpServerUtility.Execute())?
if (context.Handler != null)
{
// apply ObjectPostProcessors now
handler = WebSupportModule.ConfigureHandler(handler, appContext, url, false);
}
else
{
// execution pipeline "entry-point" - create page instance only
// and defer configuration to PreRequestHandlerExecute step
WebSupportModule.SetCurrentHandlerConfiguration(appContext, url, false);
}
handler = WebObjectUtils.CreateHandler(context, rawUrl);
// let WebSupportModule handle configuration
handler = WebSupportModule.ConfigureHandler(context, handler, appContext, rawUrl, false);
}
ApplyDependencyInjectionInfrastructure(handler, appContext);
return handler;
}
/// <summary>
/// Apply dependency injection stuff on the handler.
/// </summary>
/// <param name="handler">the handler to be intercepted</param>
/// <param name="applicationContext">the context responsible for configuring this handler</param>
private static void ApplyDependencyInjectionInfrastructure(IHttpHandler handler, IApplicationContext applicationContext)
{
if (handler is Control)
{
ControlInterceptor.EnsureControlIntercepted(applicationContext, (Control)handler);
}
else
{
if (handler is ISupportsWebDependencyInjection)
{
((ISupportsWebDependencyInjection)handler).DefaultApplicationContext = applicationContext;
}
}
}
}
}

View File

@@ -79,7 +79,7 @@ namespace Spring.Web.Support
#region AbstractHandlerFactory implementations
protected override IHttpHandler CreateHandlerInstance( HttpContext context, string requestType, string url, string physicalPath )
protected override IHttpHandler CreateHandlerInstance( IConfigurableApplicationContext appContext, HttpContext context, string requestType, string url, string physicalPath )
{
throw new NotImplementedException();
}
@@ -105,12 +105,12 @@ namespace Spring.Web.Support
return base.GetCheckedApplicationContext(virtualPath);
}
protected override IHttpHandler CreateHandlerInstance(HttpContext context, string requestType, string url, string physicalPath )
protected override IHttpHandler CreateHandlerInstance(IConfigurableApplicationContext appContext, HttpContext context, string requestType, string url, string physicalPath )
{
return CreateHandlerInstanceStub(context, requestType, url, physicalPath);
return CreateHandlerInstanceStub(appContext, context, requestType, url, physicalPath);
}
public virtual IHttpHandler CreateHandlerInstanceStub(HttpContext context, string requestType, string url, string physicalPath)
public virtual IHttpHandler CreateHandlerInstanceStub(IConfigurableApplicationContext appContext, HttpContext context, string requestType, string url, string physicalPath)
{
throw new NotImplementedException();
}
@@ -178,7 +178,7 @@ namespace Spring.Web.Support
using(Record(mocks))
{
Expect.Call(reusableHandler.IsReusable).Return(true);
Expect.Call(f.CreateHandlerInstanceStub(null, null, "reusable", null)).Return(reusableHandler);
Expect.Call(f.CreateHandlerInstanceStub(null, null, null, "reusable", null)).Return(reusableHandler);
}
using (Playback(mocks))
{
@@ -201,8 +201,8 @@ namespace Spring.Web.Support
// - CreateHandlerInstance() is called for each request
using(Record(mocks))
{
Expect.Call(f.CreateHandlerInstanceStub(null, null, "notreusable", null)).Return(nonReusableHandler);
Expect.Call(f.CreateHandlerInstanceStub(null, null, "notreusable", null)).Return(nonReusableHandler2);
Expect.Call(f.CreateHandlerInstanceStub(null, null, null, "notreusable", null)).Return(nonReusableHandler);
Expect.Call(f.CreateHandlerInstanceStub(null, null, null, "notreusable", null)).Return(nonReusableHandler2);
}
using (Playback(mocks))
{