refactored PageHandlerFactory and AbstractHandlerFactory

This commit is contained in:
eeichinger
2008-10-03 09:53:16 +00:00
parent f3b01b69ce
commit f3dc7a33cd
7 changed files with 416 additions and 157 deletions

View File

@@ -86,20 +86,11 @@ namespace Spring.Web.Script.Services
public override IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
string filename = VirtualPathUtility.ToAbsolute(context.Request.FilePath);
string cacheKey = (string)webServiceData_GetCacheKey.Invoke(
null, new object[] { VirtualPathUtility.ToAbsolute(context.Request.FilePath) });
string cacheKey = (string)webServiceData_GetCacheKey.Invoke(null, new object[] { filename });
object webServiceData = context.Cache.Get(cacheKey);
if (webServiceData == null)
{
IConfigurableApplicationContext appContext =
WebApplicationContext.GetContext(url) as IConfigurableApplicationContext;
if (appContext == null)
{
throw new InvalidOperationException(
"Implementations of IApplicationContext must also implement IConfigurableApplicationContext");
}
IConfigurableApplicationContext appContext = base.GetCheckedApplicationContext(url);
string appRelativeVirtualPath = WebUtils.GetAppRelativePath(url);
NamedObjectDefinition nod = FindWebObjectDefinition(appRelativeVirtualPath, appContext.ObjectFactory);
@@ -126,5 +117,18 @@ namespace Spring.Web.Script.Services
{
this.scriptHandlerFactory.ReleaseHandler(handler);
}
/// <summary>
/// Create a handler instance for the given URL.
/// </summary>
/// <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="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 )
{
throw new NotSupportedException();
}
}
}

View File

@@ -20,9 +20,14 @@
#region Imports
using System;
using System.Collections;
using System.IO;
using System.Web;
using Common.Logging;
using Spring.Collections;
using Spring.Context;
using Spring.Context.Support;
using Spring.Objects.Factory.Config;
using Spring.Util;
@@ -43,17 +48,24 @@ namespace Spring.Web.Support
/// <author>Aleksandar Seovic</author>
public abstract class AbstractHandlerFactory : IHttpHandlerFactory
{
/// <summary>
/// Holds all handlers having <see cref="IHttpHandler.IsReusable"/> == true.
/// </summary>
private readonly IDictionary _reusableHandlerCache = new CaseInsensitiveHashtable();
/// <summary>
/// Holds the shared logger for all factories.
/// </summary>
protected readonly ILog Log;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Web.Support.AbstractHandlerFactory"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class and as such provides no public constructors.
/// </p>
/// </remarks>
protected AbstractHandlerFactory()
{}
{
this.Log = LogManager.GetLogger( this.GetType() );
}
/// <summary>
/// Returns an appropriate <see cref="System.Web.IHttpHandler"/> implementation.
@@ -66,15 +78,59 @@ namespace Spring.Web.Support
/// The HTTP method of the request.
/// </param>
/// <param name="url">The request URL.</param>
/// <param name="pathTranslated">
/// <param name="physicalPath">
/// The physical path of the requested resource.
/// </param>
/// <returns>
/// A new <see cref="System.Web.IHttpHandler"/> object that processes
/// the request.
/// </returns>
public abstract IHttpHandler GetHandler(
HttpContext context, string requestType, string url, string pathTranslated);
public virtual IHttpHandler GetHandler( HttpContext context, string requestType, string url, string physicalPath )
{
bool isDebug = Log.IsDebugEnabled;
#region Instrumentation
if (isDebug)
Log.Debug( string.Format( "GetHandler():resolving url '{0}'", url ) );
#endregion
IHttpHandler handler = null;
lock (_reusableHandlerCache.SyncRoot)
{
handler = (IHttpHandler)_reusableHandlerCache[url];
}
if (handler != null)
{
#region Instrumentation
if (isDebug)
{
Log.Debug( string.Format( "GetHandler():resolved url '{0}' from reusable handler cache", url ) );
}
#endregion
return handler;
}
lock (_reusableHandlerCache.SyncRoot)
{
handler = (IHttpHandler)_reusableHandlerCache[url];
if (handler == null)
{
handler = CreateHandlerInstance( context, requestType, url, physicalPath );
if (handler.IsReusable)
{
_reusableHandlerCache[url] = handler;
}
}
return handler;
}
}
/// <summary>
/// Enables a factory to release an existing
@@ -83,8 +139,61 @@ namespace Spring.Web.Support
/// <param name="handler">
/// The <see cref="System.Web.IHttpHandler"/> object to release.
/// </param>
public virtual void ReleaseHandler(IHttpHandler handler)
{}
public virtual void ReleaseHandler( IHttpHandler handler )
{ }
/// <summary>
/// Create a handler instance for the given URL.
/// </summary>
/// <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="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 );
/// <summary>
/// Get the application context instance corresponding to the given absolute url and checks
/// it for <see cref="IConfigurableApplicationContext"/> contract and being not null.
/// </summary>
/// <param name="url">the absolute url</param>
/// <exception cref="ArgumentException">
/// if no context is found
/// </exception>
/// <exception cref="InvalidOperationException">
/// if context is not an <see cref="IConfigurableApplicationContext"/>
/// </exception>
/// <returns>teh application context instance corresponding to the given absolute url.</returns>
/// <remarks>
/// Calls <see cref="GetContext"/> to obtain a context instance.
/// </remarks>
protected IConfigurableApplicationContext GetCheckedApplicationContext( string url )
{
IApplicationContext appContext = GetContext( url );
if (appContext == null)
{
throw new ArgumentException( string.Format( "no application context for virtual path '{0}'", url ) );
}
if (!(appContext is IConfigurableApplicationContext))
{
throw new InvalidOperationException( string.Format( "application context '{0}' for virtual path '{1}' must implement IConfigurableApplicationContext", appContext.ToString(), url ) );
}
return (IConfigurableApplicationContext)appContext;
}
/// <summary>
/// Returns the unchecked, raw application context for the given virtual path.
/// </summary>
/// <param name="virtualPath">the virtual path to get the context for.</param>
/// <returns>the context or null.</returns>
/// <remarks>
/// Subclasses may override this method to change the context source.
/// By default, <see cref="WebApplicationContext.GetContext"/> is used for obtaining context instances.
/// </remarks>
protected virtual IApplicationContext GetContext( string virtualPath )
{
return WebApplicationContext.GetContext( virtualPath );
}
/// <summary>
/// DO NOT USE - this is subject to change!
@@ -98,27 +207,29 @@ namespace Spring.Web.Support
/// <remarks>
/// Resolve an object definition by url.
/// </remarks>
protected internal static NamedObjectDefinition FindWebObjectDefinition(string appRelativeVirtualPath, IConfigurableListableObjectFactory objectFactory)
protected internal static NamedObjectDefinition FindWebObjectDefinition( string appRelativeVirtualPath, IConfigurableListableObjectFactory objectFactory )
{
ILog Log = LogManager.GetLogger(typeof(AbstractHandlerFactory));
ILog Log = LogManager.GetLogger( typeof( AbstractHandlerFactory ) );
bool isDebug = Log.IsDebugEnabled;
// lookup definition using app-relative url
if (isDebug) Log.Debug(string.Format("GetHandler():looking up definition for app-relative url '{0}'", appRelativeVirtualPath));
if (isDebug)
Log.Debug( string.Format( "GetHandler():looking up definition for app-relative url '{0}'", appRelativeVirtualPath ) );
string objectDefinitionName = appRelativeVirtualPath;
IObjectDefinition pageDefinition = objectFactory.GetObjectDefinition(appRelativeVirtualPath, true);
IObjectDefinition pageDefinition = objectFactory.GetObjectDefinition( appRelativeVirtualPath, true );
if (pageDefinition == null)
{
// try using pagename+extension and pagename only
string pageExtension = Path.GetExtension(appRelativeVirtualPath);
string pageName = WebUtils.GetPageName(appRelativeVirtualPath);
string pageExtension = Path.GetExtension( appRelativeVirtualPath );
string pageName = WebUtils.GetPageName( appRelativeVirtualPath );
// only looks in the specified object factory -- it will *not* search parent contexts
pageDefinition = objectFactory.GetObjectDefinition(pageName + pageExtension, false);
pageDefinition = objectFactory.GetObjectDefinition( pageName + pageExtension, false );
if (pageDefinition == null)
{
pageDefinition = objectFactory.GetObjectDefinition(pageName, false);
if (pageDefinition != null) objectDefinitionName = pageName;
pageDefinition = objectFactory.GetObjectDefinition( pageName, false );
if (pageDefinition != null)
objectDefinitionName = pageName;
}
else
{
@@ -128,20 +239,21 @@ namespace Spring.Web.Support
if (pageDefinition != null)
{
if (isDebug)
Log.Debug(string.Format("GetHandler():found definition for page-name '{0}'", objectDefinitionName));
Log.Debug( string.Format( "GetHandler():found definition for page-name '{0}'", objectDefinitionName ) );
}
else
{
if (isDebug)
Log.Debug(string.Format("GetHandler():no definition found for page-name '{0}'", pageName));
Log.Debug( string.Format( "GetHandler():no definition found for page-name '{0}'", pageName ) );
}
}
else
{
if (isDebug) Log.Debug(string.Format("GetHandler():found definition for page-url '{0}'", appRelativeVirtualPath));
if (isDebug)
Log.Debug( string.Format( "GetHandler():found definition for page-url '{0}'", appRelativeVirtualPath ) );
}
return (pageDefinition == null) ? (NamedObjectDefinition)null : new NamedObjectDefinition(objectDefinitionName, pageDefinition);
return (pageDefinition == null) ? (NamedObjectDefinition)null : new NamedObjectDefinition( objectDefinitionName, pageDefinition );
}
/// <summary>
@@ -155,7 +267,7 @@ namespace Spring.Web.Support
/// <summary>
/// DO NOT USE
/// </summary>
public NamedObjectDefinition(string name, IObjectDefinition objectDefinition)
public NamedObjectDefinition( string name, IObjectDefinition objectDefinition )
{
_name = name;
_objectDefinition = objectDefinition;
@@ -178,5 +290,4 @@ namespace Spring.Web.Support
}
}
}
}

View File

@@ -68,10 +68,6 @@ namespace Spring.Web.Support
/// <author>Aleksandar Seovic</author>
public class PageHandlerFactory : AbstractHandlerFactory
{
private readonly ILog Log = LogManager.GetLogger(typeof(PageHandlerFactory));
private readonly IDictionary pageHandlerWrappers = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
/// <summary>
/// Retrieves instance of the configured page from Spring web application context,
/// or if page is not defined in Spring config file tries to find it using standard
@@ -82,76 +78,59 @@ namespace Spring.Web.Support
/// <param name="url">Requested page URL</param>
/// <param name="physicalPath">Translated server path for the page</param>
/// <returns>Instance of the IHttpHandler object that should be used to process request.</returns>
public override IHttpHandler GetHandler(HttpContext context, string requestType, string url, string physicalPath)
public override IHttpHandler GetHandler( HttpContext context, string requestType, string url, string physicalPath )
{
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
new SecurityPermission( SecurityPermissionFlag.UnmanagedCode ).Assert();
bool isDebug = Log.IsDebugEnabled;
if (isDebug) Log.Debug(string.Format("GetHandler():resolving url '{0}'", url));
return base.GetHandler(context, requestType, url, physicalPath);
}
/// <summary>
/// Create a handler instance for the given URL.
/// </summary>
/// <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="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 )
{
IHttpHandler pageHandlerWrapper;
IConfigurableApplicationContext appContext = GetCheckedApplicationContext( url );
lock (pageHandlerWrappers.SyncRoot)
if (appContext == null)
{
pageHandlerWrapper = (PageHandlerWrapper)pageHandlerWrappers[url];
throw new InvalidOperationException(
"Implementations of IApplicationContext must also implement IConfigurableApplicationContext" );
}
if (pageHandlerWrapper != null)
string appRelativeVirtualPath = WebUtils.GetAppRelativePath( url );
NamedObjectDefinition namedPageDefinition = FindWebObjectDefinition( appRelativeVirtualPath, appContext.ObjectFactory );
if (namedPageDefinition != null)
{
if (isDebug)
Type pageType = namedPageDefinition.ObjectDefinition.ObjectType;
if (typeof( IRequiresSessionState ).IsAssignableFrom( pageType ))
{
Log.Debug(string.Format("GetHandler():resolved url '{0}' from reusable handler cache", url));
pageHandlerWrapper = new SessionAwarePageHandlerWrapper( appContext, namedPageDefinition.Name, url, null );
}
else
{
pageHandlerWrapper = new PageHandlerWrapper( appContext, namedPageDefinition.Name, url, null );
}
}
else
{
IConfigurableApplicationContext appContext =
WebApplicationContext.GetContext(url) as IConfigurableApplicationContext;
if (appContext == null)
Type pageType = WebObjectUtils.GetCompiledPageType( url );
if (typeof( IRequiresSessionState ).IsAssignableFrom( pageType ))
{
throw new InvalidOperationException(
"Implementations of IApplicationContext must also implement IConfigurableApplicationContext");
}
string appRelativeVirtualPath = WebUtils.GetAppRelativePath(url);
NamedObjectDefinition namedPageDefinition = FindWebObjectDefinition(appRelativeVirtualPath, appContext.ObjectFactory);
if (namedPageDefinition != null)
{
Type pageType = namedPageDefinition.ObjectDefinition.ObjectType;
if (typeof(IRequiresSessionState).IsAssignableFrom(pageType))
{
pageHandlerWrapper = new SessionAwarePageHandlerWrapper(appContext, namedPageDefinition.Name, url, null);
}
else
{
pageHandlerWrapper = new PageHandlerWrapper(appContext, namedPageDefinition.Name, url, null);
}
pageHandlerWrapper = new SessionAwarePageHandlerWrapper( appContext, appRelativeVirtualPath, url, physicalPath );
}
else
{
Type pageType = WebObjectUtils.GetCompiledPageType(url);
if (typeof(IRequiresSessionState).IsAssignableFrom(pageType))
{
pageHandlerWrapper = new SessionAwarePageHandlerWrapper(appContext, appRelativeVirtualPath, url, physicalPath);
}
else
{
pageHandlerWrapper = new PageHandlerWrapper(appContext, appRelativeVirtualPath, url, physicalPath);
}
}
if (pageHandlerWrapper.IsReusable)
{
lock (pageHandlerWrappers.SyncRoot)
{
pageHandlerWrappers[url] = pageHandlerWrapper;
}
pageHandlerWrapper = new PageHandlerWrapper( appContext, appRelativeVirtualPath, url, physicalPath );
}
}
return pageHandlerWrapper;
}
}
@@ -169,15 +148,15 @@ namespace Spring.Web.Support
{
#if NET_2_0 && !MONO_2_0
private static readonly FieldInfo fiHttpContext_CurrentHandler =
typeof(HttpContext).GetField("_currentHandler", BindingFlags.NonPublic | BindingFlags.Instance);
typeof( HttpContext ).GetField( "_currentHandler", BindingFlags.NonPublic | BindingFlags.Instance );
#endif
#if MONO_2_0
private static readonly FieldInfo fiHttpContext_CurrentHandler =
typeof(HttpContext).GetField("handler", BindingFlags.NonPublic | BindingFlags.Instance);
#endif
#if NET_2_0 || !MONO_2_0
private static readonly MethodInfo miPage_SetPreviousPage =
typeof(System.Web.UI.Page).GetMethod("SetPreviousPage", BindingFlags.NonPublic | BindingFlags.Instance);
private static readonly MethodInfo miPage_SetPreviousPage =
typeof( System.Web.UI.Page ).GetMethod( "SetPreviousPage", BindingFlags.NonPublic | BindingFlags.Instance );
#endif
private readonly IApplicationContext appContext;
@@ -202,7 +181,7 @@ namespace Spring.Web.Support
/// <param name="pageName">Name of the page object to execute.</param>
/// <param name="url">Requested page URL.</param>
/// <param name="path">Translated server path for the page.</param>
public PageHandlerWrapper(IApplicationContext appContext, string pageName, string url, string path)
public PageHandlerWrapper( IApplicationContext appContext, string pageName, string url, string path )
{
this.appContext = appContext;
this.pageId = pageName;
@@ -215,8 +194,8 @@ namespace Spring.Web.Support
/// </summary>
/// <param name="appContext">Application context instance to retrieve page from.</param>
/// <param name="pageName">Name of the page object to execute.</param>
public PageHandlerWrapper(IApplicationContext appContext, string pageName)
: this(appContext, pageName, null, null)
public PageHandlerWrapper( IApplicationContext appContext, string pageName )
: this( appContext, pageName, null, null )
{
}
@@ -245,7 +224,7 @@ namespace Spring.Web.Support
#endregion
void IHttpHandler.ProcessRequest(HttpContext context)
void IHttpHandler.ProcessRequest( HttpContext context )
{
IHttpHandler handler = cachedHandler;
@@ -257,11 +236,12 @@ namespace Spring.Web.Support
}
else
{
handler = GetOrCreateProcessHandler(context);
handler = GetOrCreateProcessHandler( context );
}
// note, that we don't care about sync here. The last call wins (it's the most current handler instance anyway)
if (handler.IsReusable) cachedHandler = handler;
if (handler.IsReusable)
cachedHandler = handler;
}
// replace handler proxy on context with "real" handler
@@ -276,29 +256,29 @@ namespace Spring.Web.Support
// fix this...
if (this == context.CurrentHandler)
{
fiHttpContext_CurrentHandler.SetValue(context, handler);
fiHttpContext_CurrentHandler.SetValue( context, handler );
}
if (handler is System.Web.UI.Page)
{
System.Web.UI.Page page = (Page) handler;
System.Web.UI.Page page = (Page)handler;
// TODO: to fix this would require a change to the Mono source as there is no mechanisim (public or private) for explicitly setting the
// PreviousPage at the moment
// TODO: to fix this would require a change to the Mono source as there is no mechanisim (public or private) for explicitly setting the
// PreviousPage at the moment
#if !MONO_2_0
// During Server.Transfer/Execute() the PreviousPage property gets set
if (this.PreviousPage != null)
{
miPage_SetPreviousPage.Invoke(page, new object[] { this.PreviousPage });
miPage_SetPreviousPage.Invoke( page, new object[] { this.PreviousPage } );
}
#endif
}
#endif
ApplySharedState(handler);
ApplyDependencyInjection(handler);
ApplySharedState( handler );
ApplyDependencyInjection( handler );
handler.ProcessRequest(context);
handler.ProcessRequest( context );
}
/// <summary>
@@ -316,7 +296,7 @@ namespace Spring.Web.Support
private IHttpHandler CreatePageInstance()
{
IHttpHandler handler;
handler = WebObjectUtils.CreatePageInstance(url);
handler = WebObjectUtils.CreatePageInstance( url );
if (handler is IApplicationContextAware)
{
((IApplicationContextAware)handler).ApplicationContext = appContext;
@@ -327,21 +307,21 @@ namespace Spring.Web.Support
/// <summary>
/// Gets or - if not found - creates a process handler instance.
/// </summary>
private IHttpHandler GetOrCreateProcessHandler(HttpContext context)
private IHttpHandler GetOrCreateProcessHandler( HttpContext context )
{
IHttpHandler handler = null;
string processId = context.Request[AbstractProcessHandler.ProcessIdParamName];
if (processId != null)
{
handler = (IHttpHandler)ProcessManager.GetProcess(processId);
handler = (IHttpHandler)ProcessManager.GetProcess( processId );
}
if (handler == null)
{
handler = (IHttpHandler)this.appContext.GetObject(this.pageId);
handler = (IHttpHandler)this.appContext.GetObject( this.pageId );
if (handler is IProcess)
{
((IProcess)handler).Start(url);
((IProcess)handler).Start( url );
}
}
return handler;
@@ -351,11 +331,11 @@ namespace Spring.Web.Support
/// Apply dependency injection stuff on the handler.
/// </summary>
/// <param name="handler"></param>
private void ApplyDependencyInjection(IHttpHandler handler)
private void ApplyDependencyInjection( IHttpHandler handler )
{
if (handler is Control)
{
ControlInterceptor.EnsureControlIntercepted(appContext, (Control)handler);
ControlInterceptor.EnsureControlIntercepted( appContext, (Control)handler );
}
else
{
@@ -369,11 +349,11 @@ namespace Spring.Web.Support
/// <summary>
/// Applies <see cref="HandlerState"/> to the given handler if applicable.
/// </summary>
private void ApplySharedState(IHttpHandler handler)
private void ApplySharedState( IHttpHandler handler )
{
if (handler is ISharedStateAware)
{
CheckIfPageWasRecompiled(handler);
CheckIfPageWasRecompiled( handler );
((ISharedStateAware)handler).SharedState = this.handlerState;
}
}
@@ -382,7 +362,7 @@ namespace Spring.Web.Support
/// Checks, if page has been recompiled. Creates/discards handlerState if necessary.
/// </summary>
/// <param name="handler"></param>
private void CheckIfPageWasRecompiled(IHttpHandler handler)
private void CheckIfPageWasRecompiled( IHttpHandler handler )
{
if (handlerType != handler.GetType())
{
@@ -415,8 +395,8 @@ namespace Spring.Web.Support
/// <param name="pageName">Name of the page object to execute.</param>
/// <param name="url">Requested page URL.</param>
/// <param name="path">Translated server path for the page.</param>
public SessionAwarePageHandlerWrapper(IApplicationContext appContext, string pageName, string url, string path)
: base(appContext, pageName, url, path)
public SessionAwarePageHandlerWrapper( IApplicationContext appContext, string pageName, string url, string path )
: base( appContext, pageName, url, path )
{
}
@@ -425,8 +405,8 @@ namespace Spring.Web.Support
/// </summary>
/// <param name="appContext">Application context instance to retrieve page from.</param>
/// <param name="pageName">Name of the page object to execute.</param>
public SessionAwarePageHandlerWrapper(IApplicationContext appContext, string pageName)
: base(appContext, pageName)
public SessionAwarePageHandlerWrapper( IApplicationContext appContext, string pageName )
: base( appContext, pageName )
{
}
}

View File

@@ -0,0 +1,14 @@
<%@ Page language="c#" EnableSessionState="ReadOnly" AutoEventWireup="false" Inherits="Spring.Web.UI.Page" %><script language="c#" runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
try
{
Session["disablesSession"] = "somevalue";
NUnit.Framework.Assert.Fail("must not be able to write to session");
}
catch(HttpException)
{}
}
</script><%=Session.IsReadOnly?"OK":"NOK"%>

View File

@@ -131,6 +131,7 @@
<EmbeddedResource Include="Context\Support\HttpApplicationConfigurerTests.xml" />
<Content Include="Data\Spring\Context\Support\WebApplicationContextTests\Dummy.aspx" />
<Content Include="Data\Spring\Objects\Factory\Support\TestForm.aspx" />
<Content Include="Data\Spring\Web\Support\PageHandlerFactoryTests\ReadOnlySession.aspx" />
<Content Include="Data\Spring\Web\Support\PageHandlerFactoryTests\TransferAfterSetResult.aspx" />
<Content Include="Data\Spring\Web\Support\PageHandlerFactoryTests\MaintainsSession1.aspx" />
<Content Include="Data\Spring\Web\Support\PageHandlerFactoryTests\MaintainsSession2.aspx" />

View File

@@ -23,6 +23,8 @@
using System;
using System.Web;
using NUnit.Framework;
using Rhino.Mocks;
using Spring.Context;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
@@ -35,51 +37,180 @@ namespace Spring.Web.Support
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class AbstractHandlerFactoryTests : AbstractHandlerFactory
public class AbstractHandlerFactoryTests
{
private class Type1 {}
#region TestFindWebObjectDefinition Helper
private class TestFindWebObjectDefinitionHandlerFactory : AbstractHandlerFactory
{
private class Type1 { }
public void TestFindWebObjectDefinition()
{
NamedObjectDefinition nod;
nod = Find( "/path/o1.ext", "/path/o1.ext" );
Assert.AreEqual( typeof( Type1 ), nod.ObjectDefinition.ObjectType );
Assert.AreEqual( "/path/o1.ext", nod.Name );
nod = Find( "/path/o1.ext", "/o1.ext" );
Assert.IsNull( nod );
nod = Find( "/path/o1.ext", "/path/o1" );
Assert.IsNull( nod );
nod = Find( "/path/o1.ext", "o1.ext" );
Assert.AreEqual( typeof( Type1 ), nod.ObjectDefinition.ObjectType );
Assert.AreEqual( "o1.ext", nod.Name );
nod = Find( "/path/o1.ext", "o1" );
Assert.AreEqual( typeof( Type1 ), nod.ObjectDefinition.ObjectType );
Assert.AreEqual( "o1", nod.Name );
}
private static NamedObjectDefinition Find( string url, string objectName )
{
DefaultListableObjectFactory of = new DefaultListableObjectFactory();
RootObjectDefinition rod = new RootObjectDefinition( typeof( Type1 ) );
of.RegisterObjectDefinition( objectName, rod );
return FindWebObjectDefinition( url, of );
}
#region AbstractHandlerFactory implementations
protected override IHttpHandler CreateHandlerInstance( HttpContext context, string requestType, string url, string physicalPath )
{
throw new NotImplementedException();
}
#endregion
}
#endregion TestFindWebObjectDefinition Helper
[Test]
public void FindWebObjectDefinition()
{
NamedObjectDefinition nod;
nod = Find("/path/o1.ext", "/path/o1.ext");
Assert.AreEqual( typeof(Type1), nod.ObjectDefinition.ObjectType);
Assert.AreEqual( "/path/o1.ext", nod.Name);
nod = Find("/path/o1.ext", "/o1.ext");
Assert.IsNull(nod);
nod = Find("/path/o1.ext", "/path/o1");
Assert.IsNull(nod);
nod = Find("/path/o1.ext", "o1.ext");
Assert.AreEqual(typeof(Type1), nod.ObjectDefinition.ObjectType);
Assert.AreEqual("o1.ext", nod.Name);
nod = Find("/path/o1.ext", "o1");
Assert.AreEqual(typeof(Type1), nod.ObjectDefinition.ObjectType);
Assert.AreEqual("o1", nod.Name);
TestFindWebObjectDefinitionHandlerFactory f = new TestFindWebObjectDefinitionHandlerFactory();
f.TestFindWebObjectDefinition();
}
private NamedObjectDefinition Find(string url, string objectName)
#region TestHandlerFactory
public class TestHandlerFactory : AbstractHandlerFactory
{
DefaultListableObjectFactory of = new DefaultListableObjectFactory();
RootObjectDefinition rod = new RootObjectDefinition(typeof(Type1));
of.RegisterObjectDefinition(objectName, rod);
public new IConfigurableApplicationContext GetCheckedApplicationContext(string virtualPath)
{
return base.GetCheckedApplicationContext(virtualPath);
}
return FindWebObjectDefinition( url, of );
protected override IHttpHandler CreateHandlerInstance(HttpContext context, string requestType, string url, string physicalPath )
{
return CreateHandlerInstanceStub(context, requestType, url, physicalPath);
}
public virtual IHttpHandler CreateHandlerInstanceStub(HttpContext context, string requestType, string url, string physicalPath)
{
throw new NotImplementedException();
}
protected override IApplicationContext GetContext( string virtualPath )
{
return GetContextStub( virtualPath );
}
public virtual IApplicationContext GetContextStub( string virtualPath )
{
throw new NotImplementedException();
}
}
#region AbstractHandlerFactory implementations
public override IHttpHandler GetHandler(HttpContext context, string requestType, string url,
string pathTranslated)
{
throw new NotImplementedException();
}
#endregion
[Test]
public void GetCheckedApplicationContextThrowsExceptionsOnNonConfigurableContexts()
{
MockRepository mocks = new MockRepository();
TestHandlerFactory f = (TestHandlerFactory) mocks.PartialMock(typeof(TestHandlerFactory));
IApplicationContext simpleAppContext = (IApplicationContext) mocks.Stub(typeof(IApplicationContext));
IConfigurableApplicationContext allowedAppContext = (IConfigurableApplicationContext) mocks.Stub(typeof(IConfigurableApplicationContext));
using(mocks.Record())
{
Expect.Call(f.GetContextStub("/NullContext")).Return(null);
Expect.Call(f.GetContextStub("/NonConfigurableContext")).Return(simpleAppContext);
Expect.Call(f.GetContextStub("/AllowedContext")).Return(allowedAppContext);
}
// (context == null) -> ArgumentException
try
{
f.GetCheckedApplicationContext("/NullContext");
Assert.Fail("should throw ArgumentException");
}
catch (ArgumentException)
{}
// !(context is IConfigurableApplicationContext) -> InvalidOperationException
try
{
f.GetCheckedApplicationContext("/NonConfigurableContext");
Assert.Fail("should throw InvalidOperationException");
}
catch (InvalidOperationException)
{}
// (context is IConfigurableApplicationContext) -> OK
Assert.AreSame(allowedAppContext, f.GetCheckedApplicationContext("/AllowedContext"));
}
[Test]
public void CachesReusableHandlers()
{
MockRepository mocks = new MockRepository();
TestHandlerFactory f = (TestHandlerFactory) mocks.PartialMock(typeof(TestHandlerFactory));
IHttpHandler reusableHandler = (IHttpHandler) mocks.Stub(typeof(IHttpHandler));
Expect.Call(reusableHandler.IsReusable).Return(true);
IHttpHandler reusableHandler2 = (IHttpHandler) mocks.Stub(typeof(IHttpHandler));
Expect.Call(reusableHandler2.IsReusable).Return(true);
// if (IHttpHandler.IsReusable == true) => always returns the same handler instance
// - CreateHandlerInstance() is only called once
using(mocks.Record())
{
Expect.Call(f.CreateHandlerInstanceStub(null, null, "reusable", null)).Return(reusableHandler);
}
using (mocks.Playback())
{
Assert.AreSame( reusableHandler, f.GetHandler( null, null, "reusable", null ) );
Assert.AreSame( reusableHandler, f.GetHandler( null, null, "reusable", null ) );
}
}
[Test]
public void DoesntCacheNonReusableHandlers()
{
MockRepository mocks = new MockRepository();
TestHandlerFactory f = (TestHandlerFactory) mocks.PartialMock(typeof(TestHandlerFactory));
IHttpHandler nonReusableHandler = (IHttpHandler) mocks.DynamicMock(typeof(IHttpHandler));
Expect.Call(nonReusableHandler.IsReusable).Return(false);
IHttpHandler nonReusableHandler2 = (IHttpHandler) mocks.DynamicMock(typeof(IHttpHandler));
Expect.Call(nonReusableHandler2.IsReusable).Return(false);
// if (IHttpHandler.IsReusable == false) => always create new handler instance
// - CreateHandlerInstance() is called for each request
using(mocks.Record())
{
Expect.Call(f.CreateHandlerInstanceStub(null, null, "notreusable", null)).Return(nonReusableHandler);
Expect.Call(f.CreateHandlerInstanceStub(null, null, "notreusable", null)).Return(nonReusableHandler2);
}
using (mocks.Playback())
{
Assert.AreSame( nonReusableHandler, f.GetHandler( null, null, "notreusable", null ) );
Assert.AreSame( nonReusableHandler2, f.GetHandler( null, null, "notreusable", null ) );
}
}
}
}

View File

@@ -48,6 +48,14 @@ namespace Spring.Web.Support
Assert.AreEqual("OK", result);
}
[Test, Explicit]
public void UsesReadonlySession()
{
AspTestClient client = new AspTestClient();
string result = client.GetPage("ReadOnlySession.aspx");
Assert.AreEqual("OK", result);
}
[Test]
public void MaintainsSession()
{
@@ -60,7 +68,7 @@ namespace Spring.Web.Support
result = client.GetPage("MaintainsSession2.aspx");
Assert.AreEqual("OK", result);
}
[Test]
public void BCLPageHandlerFactoryBehavior()
{
@@ -125,4 +133,14 @@ namespace Spring.Web.Support
}
#endif
}
[TestFixture]
public class PageHandlerFactoryStandaloneTests
{
[Test]
public void PageUsesReadonlySessionState()
{
}
}
}