From 963c159743a82a470bcaee950f1385ef8a18c51c Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Wed, 28 Apr 2010 11:36:27 -0700 Subject: [PATCH 1/4] Adding prefix adjustment in route matches Complications with login make this impractical for the time being, but mechanically it does work to some extent. --HG-- branch : dev --- src/Orchard.Specs/MultiTenancy.feature | 2 +- src/Orchard.Specs/MultiTenancy.feature.cs | 2 +- .../Mvc/Routes/ShellRouteTests.cs | 95 ++++- .../Mvc/Routes/UrlPrefixTests.cs | 71 ++++ .../Orchard.Framework.Tests.csproj | 1 + src/Orchard.Tests/Stubs/StubHttpContext.cs | 18 +- src/Orchard/Mvc/Routes/ShellRoute.cs | 26 +- src/Orchard/Mvc/Routes/UrlPrefix.cs | 56 +++ .../Routes/UrlPrefixAdjustedHttpContext.cs | 36 ++ .../Mvc/Wrappers/HttpContextBaseWrapper.cs | 211 +++++++++++ .../Mvc/Wrappers/HttpRequestBaseWrapper.cs | 287 ++++++++++++++ .../Mvc/Wrappers/HttpResponseBaseWrapper.cs | 358 ++++++++++++++++++ src/Orchard/Orchard.Framework.csproj | 5 + 13 files changed, 1154 insertions(+), 14 deletions(-) create mode 100644 src/Orchard.Tests/Mvc/Routes/UrlPrefixTests.cs create mode 100644 src/Orchard/Mvc/Routes/UrlPrefix.cs create mode 100644 src/Orchard/Mvc/Routes/UrlPrefixAdjustedHttpContext.cs create mode 100644 src/Orchard/Mvc/Wrappers/HttpContextBaseWrapper.cs create mode 100644 src/Orchard/Mvc/Wrappers/HttpRequestBaseWrapper.cs create mode 100644 src/Orchard/Mvc/Wrappers/HttpResponseBaseWrapper.cs diff --git a/src/Orchard.Specs/MultiTenancy.feature b/src/Orchard.Specs/MultiTenancy.feature index ed5bbed0b..b91693135 100644 --- a/src/Orchard.Specs/MultiTenancy.feature +++ b/src/Orchard.Specs/MultiTenancy.feature @@ -79,6 +79,6 @@ Scenario: Listing tenants from command line Given I have installed Orchard And I have installed "Orchard.MultiTenancy" And I have tenant "Alpha" on "example.org" as "New-site-name" - When I execute >orchard tenant list + When I execute >tenant list Then I should see "Name: Alpha" And I should see "Request Url Host: example.org" diff --git a/src/Orchard.Specs/MultiTenancy.feature.cs b/src/Orchard.Specs/MultiTenancy.feature.cs index 701a66ee0..ec7bf1d9f 100644 --- a/src/Orchard.Specs/MultiTenancy.feature.cs +++ b/src/Orchard.Specs/MultiTenancy.feature.cs @@ -8,7 +8,7 @@ // the code is regenerated. // // ------------------------------------------------------------------------------ -namespace Orchard.Specs +namespace Orchard.Tests { using TechTalk.SpecFlow; diff --git a/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs b/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs index 886845203..dea1069c2 100644 --- a/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs +++ b/src/Orchard.Tests/Mvc/Routes/ShellRouteTests.cs @@ -7,6 +7,7 @@ using System.Web.Mvc; using System.Web.Routing; using Autofac; using Autofac.Integration.Web; +using Moq; using NUnit.Framework; using Orchard.Environment; using Orchard.Environment.Configuration; @@ -87,15 +88,15 @@ namespace Orchard.Tests.Mvc.Routes { var routeC = new Route("quux", new MvcRouteHandler()); _containerA.Resolve().Publish( - new[] {new RouteDescriptor {Priority = 0, Route = routeA}}); + new[] { new RouteDescriptor { Priority = 0, Route = routeA } }); _containerB.Resolve().Publish( - new[] {new RouteDescriptor {Priority = 0, Route = routeB}}); + new[] { new RouteDescriptor { Priority = 0, Route = routeB } }); Assert.That(_routes.Count(), Is.EqualTo(2)); _containerA.Resolve().Publish( - new[] {new RouteDescriptor {Priority = 0, Route = routeC}}); + new[] { new RouteDescriptor { Priority = 0, Route = routeC } }); Assert.That(_routes.Count(), Is.EqualTo(2)); @@ -110,17 +111,17 @@ namespace Orchard.Tests.Mvc.Routes { [Test] public void MatchingRouteToActiveShellTableWillLimitTheAbilityToMatchRoutes() { - + var routeFoo = new Route("foo", new MvcRouteHandler()); _settingsA.RequestUrlHost = "a.example.com"; _containerA.Resolve().Publish( - new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}}); + new[] { new RouteDescriptor { Priority = 0, Route = routeFoo } }); _rootContainer.Resolve().Add(_settingsA); _settingsB.RequestUrlHost = "b.example.com"; _containerB.Resolve().Publish( - new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}}); + new[] { new RouteDescriptor { Priority = 0, Route = routeFoo } }); _rootContainer.Resolve().Add(_settingsB); var httpContext = new StubHttpContext("~/foo"); @@ -143,6 +144,86 @@ namespace Orchard.Tests.Mvc.Routes { Assert.That(routeContainerProviderB.ApplicationContainer.Resolve(), Is.SameAs(_containerB.Resolve())); Assert.That(routeContainerProviderB.ApplicationContainer.Resolve(), Is.Not.SameAs(_containerA.Resolve())); } - + + [Test] + public void RequestUrlPrefixAdjustsMatchingAndPathGeneration() { + var settings = new ShellSettings { RequestUrlPrefix = "~/foo" }; + + var builder = new ContainerBuilder(); + builder.RegisterType().InstancePerDependency(); + builder.RegisterAutoMocking(); + builder.Register(ctx => settings); + + var container = builder.Build(); + container.Mock() + .Setup(x => x.Match(It.IsAny())) + .Returns(settings); + + + var shellRouteFactory = container.Resolve>(); + + var helloRoute = shellRouteFactory(new Route( + "hello", + new RouteValueDictionary { { "controller", "foo" }, { "action", "bar" } }, + new MvcRouteHandler())); + + var tagsRoute = shellRouteFactory(new Route( + "tags/{tagName}", + new RouteValueDictionary { { "controller", "tags" }, { "action", "show" } }, + new MvcRouteHandler())); + + var defaultRoute = shellRouteFactory(new Route( + "{controller}/{action}", + new RouteValueDictionary { { "controller", "home" }, { "action", "index" } }, + new MvcRouteHandler())); + + var routes = new RouteCollection { helloRoute, tagsRoute, defaultRoute }; + + var helloRouteData = routes.GetRouteData(new StubHttpContext("~/Foo/Hello")); + Assert.That(helloRouteData, Is.Not.Null); + Assert.That(helloRouteData.Values.Count(), Is.EqualTo(2)); + Assert.That(helloRouteData.GetRequiredString("controller"), Is.EqualTo("foo")); + Assert.That(helloRouteData.GetRequiredString("action"), Is.EqualTo("bar")); + + var tagsRouteData = routes.GetRouteData(new StubHttpContext("~/Foo/Tags/my-tag-name")); + Assert.That(tagsRouteData, Is.Not.Null); + Assert.That(tagsRouteData.Values.Count(), Is.EqualTo(3)); + Assert.That(tagsRouteData.GetRequiredString("controller"), Is.EqualTo("tags")); + Assert.That(tagsRouteData.GetRequiredString("action"), Is.EqualTo("show")); + Assert.That(tagsRouteData.GetRequiredString("tagName"), Is.EqualTo("my-tag-name")); + + var defaultRouteData = routes.GetRouteData(new StubHttpContext("~/Foo/Alpha/Beta")); + Assert.That(defaultRouteData, Is.Not.Null); + Assert.That(defaultRouteData.Values.Count(), Is.EqualTo(2)); + Assert.That(defaultRouteData.GetRequiredString("controller"), Is.EqualTo("Alpha")); + Assert.That(defaultRouteData.GetRequiredString("action"), Is.EqualTo("Beta")); + + var defaultRouteData2 = routes.GetRouteData(new StubHttpContext("~/Foo/Alpha")); + Assert.That(defaultRouteData2, Is.Not.Null); + Assert.That(defaultRouteData2.Values.Count(), Is.EqualTo(2)); + Assert.That(defaultRouteData2.GetRequiredString("controller"), Is.EqualTo("Alpha")); + Assert.That(defaultRouteData2.GetRequiredString("action"), Is.EqualTo("index")); + + var defaultRouteData3 = routes.GetRouteData(new StubHttpContext("~/Foo/")); + Assert.That(defaultRouteData3, Is.Not.Null); + Assert.That(defaultRouteData3.Values.Count(), Is.EqualTo(2)); + Assert.That(defaultRouteData3.GetRequiredString("controller"), Is.EqualTo("home")); + Assert.That(defaultRouteData3.GetRequiredString("action"), Is.EqualTo("index")); + + var defaultRouteData4 = routes.GetRouteData(new StubHttpContext("~/Foo")); + Assert.That(defaultRouteData4, Is.Not.Null); + Assert.That(defaultRouteData4.Values.Count(), Is.EqualTo(2)); + Assert.That(defaultRouteData4.GetRequiredString("controller"), Is.EqualTo("home")); + Assert.That(defaultRouteData4.GetRequiredString("action"), Is.EqualTo("index")); + + var requestContext = new RequestContext(new StubHttpContext("~/Foo/Alpha/Beta"), defaultRouteData); + var helloVirtualPath = routes.GetVirtualPath(requestContext, helloRouteData.Values); + Assert.That(helloVirtualPath, Is.Not.Null); + Assert.That(helloVirtualPath.VirtualPath, Is.EqualTo("~/foo/hello")); + + var defaultVirtualPath4 = routes.GetVirtualPath(requestContext, defaultRouteData4.Values); + Assert.That(defaultVirtualPath4, Is.Not.Null); + Assert.That(defaultVirtualPath4.VirtualPath, Is.EqualTo("~/foo/")); + } } } diff --git a/src/Orchard.Tests/Mvc/Routes/UrlPrefixTests.cs b/src/Orchard.Tests/Mvc/Routes/UrlPrefixTests.cs new file mode 100644 index 000000000..37255f345 --- /dev/null +++ b/src/Orchard.Tests/Mvc/Routes/UrlPrefixTests.cs @@ -0,0 +1,71 @@ +using NUnit.Framework; +using Orchard.Mvc.Routes; + +namespace Orchard.Tests.Mvc.Routes { + [TestFixture] + public class UrlPrefixTests { + [Test] + public void RemoveLeadingSegmentsOnlyMatchesFullSegment() { + var prefix = new UrlPrefix("foo"); + Assert.That(prefix.RemoveLeadingSegments("~/foo/bar"), Is.EqualTo("~/bar")); + Assert.That(prefix.RemoveLeadingSegments("~/fooo/bar"), Is.EqualTo("~/fooo/bar")); + Assert.That(prefix.RemoveLeadingSegments("~/fo/bar"), Is.EqualTo("~/fo/bar")); + } + + [Test] + public void RemoveLeadingSegmentsMayContainSlash() { + var prefix = new UrlPrefix("foo/quux"); + Assert.That(prefix.RemoveLeadingSegments("~/foo/quux/bar"), Is.EqualTo("~/bar")); + Assert.That(prefix.RemoveLeadingSegments("~/foo/bar"), Is.EqualTo("~/foo/bar")); + Assert.That(prefix.RemoveLeadingSegments("~/quux/bar"), Is.EqualTo("~/quux/bar")); + } + + [Test] + public void RemoveLeadingSegmentsCanMatchEntireUrl() { + var prefix = new UrlPrefix("foo"); + Assert.That(prefix.RemoveLeadingSegments("~/foo/"), Is.EqualTo("~/")); + Assert.That(prefix.RemoveLeadingSegments("~/foo"), Is.EqualTo("~/")); + } + + [Test] + public void RemoveLeadingSegmentsIsCaseInsensitive() { + var prefix = new UrlPrefix("Foo"); + Assert.That(prefix.RemoveLeadingSegments("~/foo/bar"), Is.EqualTo("~/bar")); + Assert.That(prefix.RemoveLeadingSegments("~/FOO/BAR"), Is.EqualTo("~/BAR")); + } + + [Test] + public void RemoveLeadingSegmentsIgnoreLeadingAndTrailingCharactersOnInput() { + var prefix = new UrlPrefix("foo"); + Assert.That(prefix.RemoveLeadingSegments("~/foo/bar"), Is.EqualTo("~/bar")); + var prefix2 = new UrlPrefix("~/foo"); + Assert.That(prefix2.RemoveLeadingSegments("~/foo/bar"), Is.EqualTo("~/bar")); + var prefix3 = new UrlPrefix("foo/"); + Assert.That(prefix3.RemoveLeadingSegments("~/foo/bar"), Is.EqualTo("~/bar")); + } + + [Test] + public void PrependLeadingSegmentsInsertsBeforeNormalVirtualPath() { + var prefix = new UrlPrefix("foo"); + Assert.That(prefix.PrependLeadingSegments("~/bar"), Is.EqualTo("~/foo/bar")); + } + + [Test] + public void PrependLeadingSegmentsPreservesNatureOfIncomingPath() { + var prefix = new UrlPrefix("foo"); + Assert.That(prefix.PrependLeadingSegments("~/bar"), Is.EqualTo("~/foo/bar")); + Assert.That(prefix.PrependLeadingSegments("/bar"), Is.EqualTo("/foo/bar")); + Assert.That(prefix.PrependLeadingSegments("bar"), Is.EqualTo("foo/bar")); + } + + [Test] + public void PrependLeadingSegmentsHandlesShortUrlConditionsAppropriately() { + var prefix = new UrlPrefix("foo"); + Assert.That(prefix.PrependLeadingSegments("~/"), Is.EqualTo("~/foo/")); + Assert.That(prefix.PrependLeadingSegments("/"), Is.EqualTo("/foo/")); + Assert.That(prefix.PrependLeadingSegments("~"), Is.EqualTo("~/foo/")); + Assert.That(prefix.PrependLeadingSegments(""), Is.EqualTo("foo/")); + } + + } +} diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 43e1a0240..00e849f60 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -169,6 +169,7 @@ + diff --git a/src/Orchard.Tests/Stubs/StubHttpContext.cs b/src/Orchard.Tests/Stubs/StubHttpContext.cs index d8495e5a1..df66a262a 100644 --- a/src/Orchard.Tests/Stubs/StubHttpContext.cs +++ b/src/Orchard.Tests/Stubs/StubHttpContext.cs @@ -1,3 +1,4 @@ +using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; @@ -25,6 +26,10 @@ namespace Orchard.Tests.Stubs { public override HttpRequestBase Request { get { return new StubHttpRequest(this); } } + public override HttpResponseBase Response { + get { return new StubHttpResponse(this); } + } + public override IDictionary Items { get { return _items; } @@ -56,7 +61,18 @@ namespace Orchard.Tests.Stubs { ?? new NameValueCollection { { "HTTP_HOST", _httpContext._hostHeader } }; } } - } + + class StubHttpResponse : HttpResponseBase { + private readonly StubHttpContext _httpContext; + + public StubHttpResponse(StubHttpContext httpContext) { + _httpContext = httpContext; + } + public override string ApplyAppPathModifier(string virtualPath) { + return "~/" + virtualPath.TrimStart('/'); + } + } + } } \ No newline at end of file diff --git a/src/Orchard/Mvc/Routes/ShellRoute.cs b/src/Orchard/Mvc/Routes/ShellRoute.cs index 6ead5e404..3a0585bb4 100644 --- a/src/Orchard/Mvc/Routes/ShellRoute.cs +++ b/src/Orchard/Mvc/Routes/ShellRoute.cs @@ -16,12 +16,15 @@ namespace Orchard.Mvc.Routes { private readonly ShellSettings _shellSettings; private readonly IContainer _container; private readonly IRunningShellTable _runningShellTable; + private UrlPrefix _urlPrefix; public ShellRoute(RouteBase route, ShellSettings shellSettings, ILifetimeScope shellLifetimeScope, IRunningShellTable runningShellTable) { _route = route; _shellSettings = shellSettings; _runningShellTable = runningShellTable; _container = new LifetimeScopeContainer(shellLifetimeScope); + if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) + _urlPrefix = new UrlPrefix(_shellSettings.RequestUrlPrefix); var routeWithArea = route as IRouteWithArea; if (routeWithArea != null) { @@ -45,8 +48,11 @@ namespace Orchard.Mvc.Routes { if (settings == null || settings.Name != _shellSettings.Name) return null; - // route didn't match anyway - var routeData = _route.GetRouteData(httpContext); + var effectiveHttpContext = httpContext; + if (_urlPrefix != null) + effectiveHttpContext = new UrlPrefixAdjustedHttpContext(httpContext, _urlPrefix); + + var routeData = _route.GetRouteData(effectiveHttpContext); if (routeData == null) return null; @@ -59,12 +65,24 @@ namespace Orchard.Mvc.Routes { public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { - // todo - ignore conditionally + // locate appropriate shell settings for request + var settings = _runningShellTable.Match(requestContext.HttpContext); - var virtualPath = _route.GetVirtualPath(requestContext, values); + // only proceed if there was a match, and it was for this client + if (settings == null || settings.Name != _shellSettings.Name) + return null; + + var effectiveRequestContext = requestContext; + if (_urlPrefix != null) + effectiveRequestContext = new RequestContext(new UrlPrefixAdjustedHttpContext(requestContext.HttpContext, _urlPrefix), requestContext.RouteData); + + var virtualPath = _route.GetVirtualPath(effectiveRequestContext, values); if (virtualPath == null) return null; + if (_urlPrefix != null) + virtualPath.VirtualPath = _urlPrefix.PrependLeadingSegments(virtualPath.VirtualPath); + return virtualPath; } diff --git a/src/Orchard/Mvc/Routes/UrlPrefix.cs b/src/Orchard/Mvc/Routes/UrlPrefix.cs new file mode 100644 index 000000000..0faa4bd12 --- /dev/null +++ b/src/Orchard/Mvc/Routes/UrlPrefix.cs @@ -0,0 +1,56 @@ +using System; + +namespace Orchard.Mvc.Routes { + /// + /// Small worker class to perform path prefix adjustments + /// + public class UrlPrefix { + private readonly string _prefix; + + public UrlPrefix(string prefix) { + _prefix = prefix.TrimStart('~').Trim('/'); + } + + public string RemoveLeadingSegments(string path) { + var beginIndex = 0; + if (path.Length > beginIndex && path[beginIndex] == '~') + ++beginIndex; + if (path.Length > beginIndex && path[beginIndex] == '/') + ++beginIndex; + + var endIndex = beginIndex + _prefix.Length; + if (path.Length == endIndex) { + // no-op + } + else if (path.Length > endIndex && path[endIndex] == '/') { + // don't include slash after segment in result + ++endIndex; + } + else { + // too short to compare - return unmodified + return path; + } + + if (string.Compare(path, beginIndex, _prefix, 0, _prefix.Length, StringComparison.OrdinalIgnoreCase) == 0) { + return path.Substring(0, beginIndex) + path.Substring(endIndex); + } + + return path; + } + + public string PrependLeadingSegments(string path) { + if (path == "~") { + // special case for peculiar situation + return "~/" + _prefix + "/"; + } + + var index = 0; + if (path.Length > index && path[index] == '~') + ++index; + if (path.Length > index && path[index] == '/') + ++index; + + return path.Substring(0, index) + _prefix + '/' + path.Substring(index); + } + } +} diff --git a/src/Orchard/Mvc/Routes/UrlPrefixAdjustedHttpContext.cs b/src/Orchard/Mvc/Routes/UrlPrefixAdjustedHttpContext.cs new file mode 100644 index 000000000..41ba52951 --- /dev/null +++ b/src/Orchard/Mvc/Routes/UrlPrefixAdjustedHttpContext.cs @@ -0,0 +1,36 @@ +using System; +using System.Web; +using Orchard.Mvc.Wrappers; + +namespace Orchard.Mvc.Routes { + public class UrlPrefixAdjustedHttpContext : HttpContextBaseWrapper { + private readonly UrlPrefix _prefix; + + public UrlPrefixAdjustedHttpContext(HttpContextBase httpContextBase, UrlPrefix prefix) + : base(httpContextBase) { + _prefix = prefix; + } + + public override HttpRequestBase Request { + get { + return new AdjustedRequest(_httpContextBase.Request, _prefix); + } + } + + class AdjustedRequest : HttpRequestBaseWrapper { + private readonly UrlPrefix _prefix; + + public AdjustedRequest(HttpRequestBase httpRequestBase, UrlPrefix prefix) + : base(httpRequestBase) { + _prefix = prefix; + } + + public override string AppRelativeCurrentExecutionFilePath { + get { + return _prefix.RemoveLeadingSegments(_httpRequestBase.AppRelativeCurrentExecutionFilePath); + } + } + } + + } +} diff --git a/src/Orchard/Mvc/Wrappers/HttpContextBaseWrapper.cs b/src/Orchard/Mvc/Wrappers/HttpContextBaseWrapper.cs new file mode 100644 index 000000000..6261f2217 --- /dev/null +++ b/src/Orchard/Mvc/Wrappers/HttpContextBaseWrapper.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections; +using System.Globalization; +using System.Security.Principal; +using System.Web; +using System.Web.Caching; +using System.Web.Profile; + +namespace Orchard.Mvc.Wrappers { + public abstract class HttpContextBaseWrapper : HttpContextBase { + protected readonly HttpContextBase _httpContextBase; + + protected HttpContextBaseWrapper(HttpContextBase httpContextBase) { + _httpContextBase = httpContextBase; + } + + public override void AddError(Exception errorInfo) { + _httpContextBase.AddError(errorInfo); + } + + public override void ClearError() { + _httpContextBase.ClearError(); + } + + public override object GetGlobalResourceObject(string classKey, string resourceKey) { + return _httpContextBase.GetGlobalResourceObject(classKey, resourceKey); + } + + public override object GetGlobalResourceObject(string classKey, string resourceKey, CultureInfo culture) { + return _httpContextBase.GetGlobalResourceObject(classKey, resourceKey, culture); + } + + public override object GetLocalResourceObject(string virtualPath, string resourceKey) { + return _httpContextBase.GetLocalResourceObject(virtualPath, resourceKey); + } + + public override object GetLocalResourceObject(string virtualPath, string resourceKey, CultureInfo culture) { + return _httpContextBase.GetLocalResourceObject(virtualPath, resourceKey, culture); + } + + public override object GetSection(string sectionName) { + return _httpContextBase.GetSection(sectionName); + } + + public override object GetService(Type serviceType) { + return ((IServiceProvider)_httpContextBase).GetService(serviceType); + } + + public override void RewritePath(string path) { + _httpContextBase.RewritePath(path); + } + + public override void RewritePath(string path, bool rebaseClientPath) { + _httpContextBase.RewritePath(path, rebaseClientPath); + } + + public override void RewritePath(string filePath, string pathInfo, string queryString) { + _httpContextBase.RewritePath(filePath, pathInfo, queryString); + } + + public override void RewritePath(string filePath, string pathInfo, string queryString, bool setClientFilePath) { + _httpContextBase.RewritePath(filePath, pathInfo, queryString, setClientFilePath); + } + + public override Exception[] AllErrors { + get { + return _httpContextBase.AllErrors; + } + } + + public override HttpApplicationStateBase Application { + get { + return _httpContextBase.Application; + } + } + + public override HttpApplication ApplicationInstance { + get { + return _httpContextBase.ApplicationInstance; + } + set { + _httpContextBase.ApplicationInstance = value; + } + } + + public override Cache Cache { + get { + return _httpContextBase.Cache; + } + } + + public override IHttpHandler CurrentHandler { + get { + return _httpContextBase.CurrentHandler; + } + } + + public override RequestNotification CurrentNotification { + get { + return _httpContextBase.CurrentNotification; + } + } + + public override Exception Error { + get { + return _httpContextBase.Error; + } + } + + public override IHttpHandler Handler { + get { + return _httpContextBase.Handler; + } + set { + _httpContextBase.Handler = value; + } + } + + public override bool IsCustomErrorEnabled { + get { + return _httpContextBase.IsCustomErrorEnabled; + } + } + + public override bool IsDebuggingEnabled { + get { + return _httpContextBase.IsDebuggingEnabled; + } + } + + public override bool IsPostNotification { + get { + return _httpContextBase.IsDebuggingEnabled; + } + } + + public override IDictionary Items { + get { + return _httpContextBase.Items; + } + } + + public override IHttpHandler PreviousHandler { + get { + return _httpContextBase.PreviousHandler; + } + } + + public override ProfileBase Profile { + get { + return _httpContextBase.Profile; + } + } + + public override HttpRequestBase Request { + get { + return _httpContextBase.Request; + } + } + + public override HttpResponseBase Response { + get { + return _httpContextBase.Response; + } + } + + public override HttpServerUtilityBase Server { + get { + return _httpContextBase.Server; + } + } + + public override HttpSessionStateBase Session { + get { + return _httpContextBase.Session; + } + } + + public override bool SkipAuthorization { + get { + return _httpContextBase.SkipAuthorization; + } + set { + _httpContextBase.SkipAuthorization = value; + } + } + + public override DateTime Timestamp { + get { + return _httpContextBase.Timestamp; + } + } + + public override TraceContext Trace { + get { + return _httpContextBase.Trace; + } + } + + public override IPrincipal User { + get { + return _httpContextBase.User; + } + set { + _httpContextBase.User = value; + } + } + + + } +} \ No newline at end of file diff --git a/src/Orchard/Mvc/Wrappers/HttpRequestBaseWrapper.cs b/src/Orchard/Mvc/Wrappers/HttpRequestBaseWrapper.cs new file mode 100644 index 000000000..82bea62ba --- /dev/null +++ b/src/Orchard/Mvc/Wrappers/HttpRequestBaseWrapper.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Specialized; +using System.IO; +using System.Security.Principal; +using System.Text; +using System.Web; + +namespace Orchard.Mvc.Wrappers { + public abstract class HttpRequestBaseWrapper : HttpRequestBase { + protected readonly HttpRequestBase _httpRequestBase; + + protected HttpRequestBaseWrapper(HttpRequestBase httpRequestBase) { + _httpRequestBase = httpRequestBase; + } + + public override byte[] BinaryRead(int count) { + return _httpRequestBase.BinaryRead(count); + } + + public override int[] MapImageCoordinates(string imageFieldName) { + return _httpRequestBase.MapImageCoordinates(imageFieldName); + } + + public override string MapPath(string virtualPath) { + return _httpRequestBase.MapPath(virtualPath); + } + + public override string MapPath(string virtualPath, string baseVirtualDir, bool allowCrossAppMapping) { + return _httpRequestBase.MapPath(virtualPath, baseVirtualDir, allowCrossAppMapping); + } + + public override void SaveAs(string filename, bool includeHeaders) { + _httpRequestBase.SaveAs(filename, includeHeaders); + } + + public override void ValidateInput() { + _httpRequestBase.ValidateInput(); + } + + public override string[] AcceptTypes { + get { + return _httpRequestBase.AcceptTypes; + } + } + + public override string AnonymousID { + get { + return _httpRequestBase.AnonymousID; + } + } + + public override string ApplicationPath { + get { + return _httpRequestBase.ApplicationPath; + } + } + + public override string AppRelativeCurrentExecutionFilePath { + get { + return _httpRequestBase.AppRelativeCurrentExecutionFilePath; + } + } + + public override HttpBrowserCapabilitiesBase Browser { + get { + return _httpRequestBase.Browser; + } + } + + public override HttpClientCertificate ClientCertificate { + get { + return _httpRequestBase.ClientCertificate; + } + } + + public override Encoding ContentEncoding { + get { + return _httpRequestBase.ContentEncoding; + } + set { + _httpRequestBase.ContentEncoding = value; + } + } + + public override int ContentLength { + get { + return _httpRequestBase.ContentLength; + } + } + + public override string ContentType { + get { + return _httpRequestBase.ContentType; + } + set { + _httpRequestBase.ContentType = value; + } + } + + public override HttpCookieCollection Cookies { + get { + return _httpRequestBase.Cookies; + } + } + + public override string CurrentExecutionFilePath { + get { + return _httpRequestBase.CurrentExecutionFilePath; + } + } + + public override string FilePath { + get { + return _httpRequestBase.FilePath; + } + } + + public override HttpFileCollectionBase Files { + get { + return _httpRequestBase.Files; + } + } + + public override Stream Filter { + get { + return _httpRequestBase.Filter; + } + set { + _httpRequestBase.Filter = value; + } + } + + public override NameValueCollection Form { + get { + return _httpRequestBase.Form; + } + } + + public override NameValueCollection Headers { + get { + return _httpRequestBase.Headers; + } + } + + public override string HttpMethod { + get { + return _httpRequestBase.HttpMethod; + } + } + + public override Stream InputStream { + get { + return _httpRequestBase.InputStream; + } + } + + public override bool IsAuthenticated { + get { + return _httpRequestBase.IsAuthenticated; + } + } + + public override bool IsLocal { + get { + return _httpRequestBase.IsLocal; + } + } + + public override bool IsSecureConnection { + get { + return _httpRequestBase.IsSecureConnection; + } + } + + public override string this[string key] { + get { + return _httpRequestBase[key]; + } + } + + public override WindowsIdentity LogonUserIdentity { + get { + return _httpRequestBase.LogonUserIdentity; + } + } + + public override NameValueCollection Params { + get { + return _httpRequestBase.Params; + } + } + + public override string Path { + get { + return _httpRequestBase.Path; + } + } + + public override string PathInfo { + get { + return _httpRequestBase.PathInfo; + } + } + + public override string PhysicalApplicationPath { + get { + return _httpRequestBase.PhysicalApplicationPath; + } + } + + public override string PhysicalPath { + get { + return _httpRequestBase.PhysicalPath; + } + } + + public override NameValueCollection QueryString { + get { + return _httpRequestBase.QueryString; + } + } + + public override string RawUrl { + get { + return _httpRequestBase.RawUrl; + } + } + + public override string RequestType { + get { + return _httpRequestBase.RequestType; + } + set { + _httpRequestBase.RequestType = value; + } + } + + public override NameValueCollection ServerVariables { + get { + return _httpRequestBase.ServerVariables; + } + } + + public override int TotalBytes { + get { + return _httpRequestBase.TotalBytes; + } + } + + public override Uri Url { + get { + return _httpRequestBase.Url; + } + } + + public override Uri UrlReferrer { + get { + return _httpRequestBase.UrlReferrer; + } + } + + public override string UserAgent { + get { + return _httpRequestBase.UserAgent; + } + } + + public override string UserHostAddress { + get { + return _httpRequestBase.UserHostAddress; + } + } + + public override string UserHostName { + get { + return _httpRequestBase.UserHostName; + } + } + + public override string[] UserLanguages { + get { + return _httpRequestBase.UserLanguages; + } + } + + } +} \ No newline at end of file diff --git a/src/Orchard/Mvc/Wrappers/HttpResponseBaseWrapper.cs b/src/Orchard/Mvc/Wrappers/HttpResponseBaseWrapper.cs new file mode 100644 index 000000000..5728503ce --- /dev/null +++ b/src/Orchard/Mvc/Wrappers/HttpResponseBaseWrapper.cs @@ -0,0 +1,358 @@ +using System; +using System.Collections; +using System.Collections.Specialized; +using System.IO; +using System.Text; +using System.Web; +using System.Web.Caching; + +namespace Orchard.Mvc.Wrappers { + public abstract class HttpResponseBaseWrapper : HttpResponseBase { + private readonly HttpResponseBase _httpResponseBase; + + protected HttpResponseBaseWrapper(HttpResponseBase httpResponse) { + _httpResponseBase = httpResponse; + } + + public override void AddCacheDependency(params CacheDependency[] dependencies) { + _httpResponseBase.AddCacheDependency(dependencies); + } + + public override void AddCacheItemDependencies(ArrayList cacheKeys) { + _httpResponseBase.AddCacheItemDependencies(cacheKeys); + } + + public override void AddCacheItemDependencies(string[] cacheKeys) { + _httpResponseBase.AddCacheItemDependencies(cacheKeys); + } + + public override void AddCacheItemDependency(string cacheKey) { + _httpResponseBase.AddCacheItemDependency(cacheKey); + } + + public override void AddFileDependencies(string[] filenames) { + _httpResponseBase.AddFileDependencies(filenames); + } + + public override void AddFileDependencies(ArrayList filenames) { + _httpResponseBase.AddFileDependencies(filenames); + } + + public override void AddFileDependency(string filename) { + _httpResponseBase.AddFileDependency(filename); + } + + public override void AddHeader(string name, string value) { + _httpResponseBase.AddHeader(name, value); + } + + public override void AppendCookie(HttpCookie cookie) { + _httpResponseBase.AppendCookie(cookie); + } + + public override void AppendHeader(string name, string value) { + _httpResponseBase.AppendHeader(name, value); + } + + public override void AppendToLog(string param) { + _httpResponseBase.AppendToLog(param); + } + + public override string ApplyAppPathModifier(string virtualPath) { + return _httpResponseBase.ApplyAppPathModifier(virtualPath); + } + + public override void BinaryWrite(byte[] buffer) { + _httpResponseBase.BinaryWrite(buffer); + } + + public override void Clear() { + _httpResponseBase.Clear(); + } + + public override void ClearContent() { + _httpResponseBase.ClearContent(); + } + + public override void ClearHeaders() { + _httpResponseBase.ClearHeaders(); + } + + public override void Close() { + _httpResponseBase.Close(); + } + + public override void DisableKernelCache() { + _httpResponseBase.DisableKernelCache(); + } + + public override void End() { + _httpResponseBase.End(); + } + + public override void Flush() { + _httpResponseBase.Flush(); + } + + public override void Pics(string value) { + _httpResponseBase.Pics(value); + } + + public override void Redirect(string url) { + _httpResponseBase.Redirect(url); + } + + public override void Redirect(string url, bool endResponse) { + _httpResponseBase.Redirect(url, endResponse); + } + + public override void RemoveOutputCacheItem(string path) { + _httpResponseBase.RemoveOutputCacheItem(path); + } + + public override void SetCookie(HttpCookie cookie) { + _httpResponseBase.SetCookie(cookie); + } + + public override void TransmitFile(string filename) { + _httpResponseBase.TransmitFile(filename); + } + + public override void TransmitFile(string filename, long offset, long length) { + _httpResponseBase.TransmitFile(filename, offset, length); + } + + public override void Write(char ch) { + _httpResponseBase.Write(ch); + } + + public override void Write(object obj) { + _httpResponseBase.Write(obj); + } + + public override void Write(string s) { + _httpResponseBase.Write(s); + } + + public override void Write(char[] buffer, int index, int count) { + _httpResponseBase.Write(buffer, index, count); + } + + public override void WriteFile(string filename) { + _httpResponseBase.WriteFile(filename); + } + + public override void WriteFile(string filename, bool readIntoMemory) { + _httpResponseBase.WriteFile(filename, readIntoMemory); + } + + public override void WriteFile(IntPtr fileHandle, long offset, long size) { + _httpResponseBase.WriteFile(fileHandle, offset, size); + } + + public override void WriteFile(string filename, long offset, long size) { + _httpResponseBase.WriteFile(filename, offset, size); + } + + public override void WriteSubstitution(HttpResponseSubstitutionCallback callback) { + _httpResponseBase.WriteSubstitution(callback); + } + + // Properties + public override bool Buffer { + get { + return _httpResponseBase.Buffer; + } + set { + _httpResponseBase.Buffer = value; + } + } + + public override bool BufferOutput { + get { + return _httpResponseBase.BufferOutput; + } + set { + _httpResponseBase.BufferOutput = value; + } + } + + public override HttpCachePolicyBase Cache { + get { + return _httpResponseBase.Cache; + } + } + + public override string CacheControl { + get { + return _httpResponseBase.CacheControl; + } + set { + _httpResponseBase.CacheControl = value; + } + } + + public override string Charset { + get { + return _httpResponseBase.Charset; + } + set { + _httpResponseBase.Charset = value; + } + } + + public override Encoding ContentEncoding { + get { + return _httpResponseBase.ContentEncoding; + } + set { + _httpResponseBase.ContentEncoding = value; + } + } + + public override string ContentType { + get { + return _httpResponseBase.ContentType; + } + set { + _httpResponseBase.ContentType = value; + } + } + + public override HttpCookieCollection Cookies { + get { + return _httpResponseBase.Cookies; + } + } + + public override int Expires { + get { + return _httpResponseBase.Expires; + } + set { + _httpResponseBase.Expires = value; + } + } + + public override DateTime ExpiresAbsolute { + get { + return _httpResponseBase.ExpiresAbsolute; + } + set { + _httpResponseBase.ExpiresAbsolute = value; + } + } + + public override Stream Filter { + get { + return _httpResponseBase.Filter; + } + set { + _httpResponseBase.Filter = value; + } + } + + public override Encoding HeaderEncoding { + get { + return _httpResponseBase.HeaderEncoding; + } + set { + _httpResponseBase.HeaderEncoding = value; + } + } + + public override NameValueCollection Headers { + get { + return _httpResponseBase.Headers; + } + } + + public override bool IsClientConnected { + get { + return _httpResponseBase.IsClientConnected; + } + } + + public override bool IsRequestBeingRedirected { + get { + return _httpResponseBase.IsRequestBeingRedirected; + } + } + + public override TextWriter Output { + get { + return _httpResponseBase.Output; + } + } + + public override Stream OutputStream { + get { + return _httpResponseBase.OutputStream; + } + } + + public override string RedirectLocation { + get { + return _httpResponseBase.RedirectLocation; + } + set { + _httpResponseBase.RedirectLocation = value; + } + } + + public override string Status { + get { + return _httpResponseBase.Status; + } + set { + _httpResponseBase.Status = value; + } + } + + public override int StatusCode { + get { + return _httpResponseBase.StatusCode; + } + set { + _httpResponseBase.StatusCode = value; + } + } + + public override string StatusDescription { + get { + return _httpResponseBase.StatusDescription; + } + set { + _httpResponseBase.StatusDescription = value; + } + } + + public override int SubStatusCode { + get { + return _httpResponseBase.SubStatusCode; + } + set { + _httpResponseBase.SubStatusCode = value; + } + } + + public override bool SuppressContent { + get { + return _httpResponseBase.SuppressContent; + } + set { + _httpResponseBase.SuppressContent = value; + } + } + + public override bool TrySkipIisCustomErrors { + get { + return _httpResponseBase.TrySkipIisCustomErrors; + } + set { + _httpResponseBase.TrySkipIisCustomErrors = value; + } + } + + } +} \ No newline at end of file diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 44589f27c..7be14bbab 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -196,11 +196,16 @@ + + ASPXCodeBehind + + + From cadfd78c55a26e1c16402906c4fd5ab744516835 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Wed, 28 Apr 2010 12:44:16 -0700 Subject: [PATCH 2/4] Orchard host recreates shell context based on significant events At the moment the events related to shell settings and shell descriptor changes will cause the host to rebuild their compositions. --HG-- branch : dev --- .hgignore | 1 + .../Bindings/OrchardSiteFactory.cs | 13 ----------- .../DefaultTenantManagerTests.cs | 10 ++++---- .../Topology/ShellDescriptorManager.cs | 2 +- .../Controllers/SetupController.cs | 3 --- .../Configuration/ShellSettingsManager.cs | 7 +++++- src/Orchard/Environment/DefaultOrchardHost.cs | 10 +++++++- .../DefaultOrchardHostEventSink.cs | 23 +++++++++++++++++++ src/Orchard/Environment/IOrchardHost.cs | 3 +-- src/Orchard/Events/DefaultOrchardEventBus.cs | 9 ++++---- src/Orchard/Orchard.Framework.csproj | 1 + 11 files changed, 53 insertions(+), 29 deletions(-) create mode 100644 src/Orchard/Environment/DefaultOrchardHostEventSink.cs diff --git a/.hgignore b/.hgignore index 704e42375..0e4e5c05c 100644 --- a/.hgignore +++ b/.hgignore @@ -12,3 +12,4 @@ glob:src/Orchard.Web/Modules/Orchard.DevTools/Module.txt glob:src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt glob:src/Orchard.Web/Media/* glob:desktop.ini +glob:src/Orchard.Azure.suo diff --git a/src/Orchard.Specs/Bindings/OrchardSiteFactory.cs b/src/Orchard.Specs/Bindings/OrchardSiteFactory.cs index 605692f79..0558fb854 100644 --- a/src/Orchard.Specs/Bindings/OrchardSiteFactory.cs +++ b/src/Orchard.Specs/Bindings/OrchardSiteFactory.cs @@ -47,23 +47,11 @@ namespace Orchard.Specs.Bindings { descriptor.EnabledFeatures.Concat(new[] { new ShellFeature { Name = name } }), descriptor.Parameters); } - - Trace.WriteLine("This call to Host.Reinitialize should not be needed, eventually"); - MvcApplication.Host.Reinitialize_Obsolete(); }); } - [When(@"I cycle the app domain")] - public void WhenICycleTheAppDomain() { - var webApp = Binding(); - webApp.Host.Execute(() => { - Trace.WriteLine("This call to Host.Reinitialize should not be needed, eventually"); - MvcApplication.Host.Reinitialize_Obsolete(); - }); - } - [Given(@"I have tenant ""(.*)\"" on ""(.*)\"" as ""(.*)\""")] public void GivenIHaveTenantOnSiteAsName(string shellName, string hostName, string siteName) { var webApp = Binding(); @@ -76,7 +64,6 @@ namespace Orchard.Specs.Bindings { using (var environment = MvcApplication.CreateStandaloneEnvironment("Default")) { environment.Resolve().SaveSettings(shellSettings); } - MvcApplication.Host.Reinitialize_Obsolete(); }); webApp.WhenIGoToPathOnHost("Setup", hostName); diff --git a/src/Orchard.Tests/Environment/Configuration/DefaultTenantManagerTests.cs b/src/Orchard.Tests/Environment/Configuration/DefaultTenantManagerTests.cs index 6bae8039a..d47d66904 100644 --- a/src/Orchard.Tests/Environment/Configuration/DefaultTenantManagerTests.cs +++ b/src/Orchard.Tests/Environment/Configuration/DefaultTenantManagerTests.cs @@ -1,7 +1,9 @@ using System.IO; using System.Linq; +using Moq; using NUnit.Framework; using Orchard.Environment.Configuration; +using Orchard.Events; namespace Orchard.Tests.Environment.Configuration { [TestFixture] @@ -26,7 +28,7 @@ namespace Orchard.Tests.Environment.Configuration { _appData.CreateFile("Sites\\Default\\Settings.txt", "Name: Default\r\nDataProvider: SQLite\r\nDataConnectionString: something else"); - IShellSettingsManager loader = new ShellSettingsManager(_appData); + IShellSettingsManager loader = new ShellSettingsManager(_appData, new Mock().Object); var settings = loader.LoadSettings().Single(); Assert.That(settings, Is.Not.Null); Assert.That(settings.Name, Is.EqualTo("Default")); @@ -41,7 +43,7 @@ namespace Orchard.Tests.Environment.Configuration { _appData.CreateFile("Sites\\Default\\Settings.txt", "Name: Default\r\nDataProvider: SQLite\r\nDataConnectionString: something else"); _appData.CreateFile("Sites\\Another\\Settings.txt", "Name: Another\r\nDataProvider: SQLite2\r\nDataConnectionString: something else2"); - IShellSettingsManager loader = new ShellSettingsManager(_appData); + IShellSettingsManager loader = new ShellSettingsManager(_appData, new Mock().Object); var settings = loader.LoadSettings(); Assert.That(settings.Count(), Is.EqualTo(2)); @@ -59,8 +61,8 @@ namespace Orchard.Tests.Environment.Configuration { [Test] public void NewSettingsCanBeStored() { _appData.CreateFile("Sites\\Default\\Settings.txt", "Name: Default\r\nDataProvider: SQLite\r\nDataConnectionString: something else"); - - IShellSettingsManager loader = new ShellSettingsManager(_appData); + + IShellSettingsManager loader = new ShellSettingsManager(_appData, new Mock().Object); var foo = new ShellSettings {Name = "Foo", DataProvider = "Bar", DataConnectionString = "Quux"}; Assert.That(loader.LoadSettings().Count(), Is.EqualTo(1)); diff --git a/src/Orchard.Web/Core/Settings/Topology/ShellDescriptorManager.cs b/src/Orchard.Web/Core/Settings/Topology/ShellDescriptorManager.cs index bd38f87e4..98bcddd67 100644 --- a/src/Orchard.Web/Core/Settings/Topology/ShellDescriptorManager.cs +++ b/src/Orchard.Web/Core/Settings/Topology/ShellDescriptorManager.cs @@ -86,7 +86,7 @@ namespace Orchard.Core.Settings.Topology { } _eventBus.Notify( - typeof(IShellDescriptorManager).FullName + ".UpdateShellDescriptor", + "ShellDescriptor_Changed", null); } } diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs index 2ded69bb3..eb8e1abe4 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs @@ -173,9 +173,6 @@ namespace Orchard.Setup.Controllers { _shellSettingsManager.SaveSettings(shellSettings); - // MultiTenancy: This will not be needed when host listens to event bus - _orchardHost.Reinitialize_Obsolete(); - // redirect to the welcome page. return Redirect("~/"); } diff --git a/src/Orchard/Environment/Configuration/ShellSettingsManager.cs b/src/Orchard/Environment/Configuration/ShellSettingsManager.cs index d1de2a657..0267bc955 100644 --- a/src/Orchard/Environment/Configuration/ShellSettingsManager.cs +++ b/src/Orchard/Environment/Configuration/ShellSettingsManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Yaml.Serialization; +using Orchard.Events; using Orchard.Localization; namespace Orchard.Environment.Configuration { @@ -13,10 +14,12 @@ namespace Orchard.Environment.Configuration { public class ShellSettingsManager : IShellSettingsManager { private readonly IAppDataFolder _appDataFolder; + private readonly IEventBus _eventBus; Localizer T { get; set; } - public ShellSettingsManager(IAppDataFolder appDataFolder) { + public ShellSettingsManager(IAppDataFolder appDataFolder, IEventBus eventBus) { _appDataFolder = appDataFolder; + _eventBus = eventBus; T = NullLocalizer.Instance; } @@ -32,6 +35,8 @@ namespace Orchard.Environment.Configuration { var filePath = Path.Combine(Path.Combine("Sites", settings.Name), "Settings.txt"); _appDataFolder.CreateFile(filePath, ComposeSettings(settings)); + + _eventBus.Notify("ShellSettings_Saved", null); } IEnumerable LoadSettings() { diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs index 3f6e182d3..35a1f394b 100644 --- a/src/Orchard/Environment/DefaultOrchardHost.cs +++ b/src/Orchard/Environment/DefaultOrchardHost.cs @@ -1,7 +1,7 @@ +using System; using System.Linq; using System.Web.Mvc; using Autofac; -using Autofac.Integration.Web; using System.Collections.Generic; using Orchard.Environment.Configuration; using Orchard.Environment.Extensions; @@ -131,5 +131,13 @@ namespace Orchard.Environment { } } + public void Process(string messageName, IDictionary eventData) { + if (messageName == "ShellSettings_Saved") { + _current = null; + } + else if (messageName == "ShellDescriptor_Changed") { + _current = null; + } + } } } diff --git a/src/Orchard/Environment/DefaultOrchardHostEventSink.cs b/src/Orchard/Environment/DefaultOrchardHostEventSink.cs new file mode 100644 index 000000000..9d0542e21 --- /dev/null +++ b/src/Orchard/Environment/DefaultOrchardHostEventSink.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Orchard.Events; + +namespace Orchard.Environment { + /// + /// This handler forwards calls to the IOrchardHost when it is an instance of DefaultOrchardHost. + /// The reason for this is to avoid adding IEventBusHandler, because DefaultOrchardHost is a component + /// that should not be detected and registererd automatically as an IDependency. + /// + public class DefaultOrchardHostEventSink : IEventBusHandler { + private readonly DefaultOrchardHost _host; + + public DefaultOrchardHostEventSink(IOrchardHost host) { + _host = host as DefaultOrchardHost; + } + + public void Process(string messageName, IDictionary eventData) { + if (_host != null) { + _host.Process(messageName, eventData); + } + } + } +} diff --git a/src/Orchard/Environment/IOrchardHost.cs b/src/Orchard/Environment/IOrchardHost.cs index 314560677..754ca84a0 100644 --- a/src/Orchard/Environment/IOrchardHost.cs +++ b/src/Orchard/Environment/IOrchardHost.cs @@ -27,6 +27,5 @@ namespace Orchard.Environment { /// Services may be resolved from within this instance to configure and initialize it's storage. /// IStandaloneEnvironment CreateStandaloneEnvironment(ShellSettings shellSettings); - } - + } } diff --git a/src/Orchard/Events/DefaultOrchardEventBus.cs b/src/Orchard/Events/DefaultOrchardEventBus.cs index d1ae5652d..820b1fa55 100644 --- a/src/Orchard/Events/DefaultOrchardEventBus.cs +++ b/src/Orchard/Events/DefaultOrchardEventBus.cs @@ -1,11 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Orchard.Logging; namespace Orchard.Events { public class DefaultOrchardEventBus : IEventBus { - private readonly IEnumerable _handlers; + private readonly Func> _handlers; - public DefaultOrchardEventBus(IEnumerable handlers) { + public DefaultOrchardEventBus(Func> handlers) { _handlers = handlers; Logger = NullLogger.Instance; } @@ -15,7 +16,7 @@ namespace Orchard.Events { #region Implementation of IEventBus public void Notify(string messageName, IDictionary eventData) { - _handlers.Invoke(handler => handler.Process(messageName, eventData), Logger); + _handlers().Invoke(handler => handler.Process(messageName, eventData), Logger); } #endregion diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 7be14bbab..00b4497e4 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -163,6 +163,7 @@ + From f892a18588e542aa650d481db135f53cb218a215 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Wed, 28 Apr 2010 12:46:29 -0700 Subject: [PATCH 3/4] Removed one other place non-test code was calling Reinitialize_Obsolete --HG-- branch : dev --- .../Orchard.MultiTenancy/Services/TenantService.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Services/TenantService.cs b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Services/TenantService.cs index f4fd6ecbd..d838927e1 100644 --- a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Services/TenantService.cs +++ b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Services/TenantService.cs @@ -12,20 +12,12 @@ namespace Orchard.MultiTenancy.Services { _orchardHost = orchardHost; } - #region Implementation of ITenantService - public IEnumerable GetTenants() { return _shellSettingsManager.LoadSettings(); } public void CreateTenant(ShellSettings settings) { _shellSettingsManager.SaveSettings(settings); - - - // MultiTenancy: This will not be needed when host listens to event bus - _orchardHost.Reinitialize_Obsolete(); } - - #endregion } } \ No newline at end of file From ee29c5214120b4a86338c3b39aa531cc037fce8f Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Wed, 28 Apr 2010 12:53:44 -0700 Subject: [PATCH 4/4] Updating name of event in unit test --HG-- branch : dev --- .../Settings/Topology/ShellDescriptorManagerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Tests.Modules/Settings/Topology/ShellDescriptorManagerTests.cs b/src/Orchard.Tests.Modules/Settings/Topology/ShellDescriptorManagerTests.cs index ae058f009..17175465e 100644 --- a/src/Orchard.Tests.Modules/Settings/Topology/ShellDescriptorManagerTests.cs +++ b/src/Orchard.Tests.Modules/Settings/Topology/ShellDescriptorManagerTests.cs @@ -137,7 +137,7 @@ namespace Orchard.Tests.Modules.Settings.Topology { Enumerable.Empty(), Enumerable.Empty()); - Assert.That(eventBus.LastMessageName, Is.EqualTo(typeof(IShellDescriptorManager).FullName + ".UpdateShellDescriptor")); + Assert.That(eventBus.LastMessageName, Is.EqualTo("ShellDescriptor_Changed")); } } }