From ec22d985ef0b157512d703dceeadbe6273084932 Mon Sep 17 00:00:00 2001 From: "shannon@ShandemVaio" Date: Mon, 30 Jul 2012 22:52:59 +0600 Subject: [PATCH] Updated all lookups to use new logging system. Updated lookups resolvers to use ManyObjectResolverBase and are just adding the known resolvers on app startup and commented out the other resolver stuff for now. Fixed up xpath statement for resolving the first document, site now renders :) --- src/Umbraco.Core/DisposableTimer.cs | 39 ++ src/Umbraco.Core/PluginTypeResolver.cs | 2 +- ...olverBase.cs => ManyObjectResolverBase.cs} | 10 +- .../Resolving/ManyWeightedResolved.cs | 246 ++++----- .../Resolving/ManyWeightedResolverBase.cs | 94 ++-- .../Resolving/ResolutionWeightAttribute.cs | 30 +- src/Umbraco.Core/Resolving/ResolverBase.cs | 33 +- ...verBase.cs => SingleObjectResolverBase.cs} | 10 +- src/Umbraco.Core/Umbraco.Core.csproj | 4 +- src/Umbraco.Web/ContentStore.cs | 2 +- .../PluginTypeResolverExtensions.cs | 18 +- .../Routing/DocumentLookupsResolver.cs | 118 +++-- src/Umbraco.Web/Routing/DocumentRequest.cs | 76 +-- src/Umbraco.Web/Routing/IDocumentLookup.cs | 2 +- src/Umbraco.Web/Routing/LookupByAlias.cs | 10 +- src/Umbraco.Web/Routing/LookupById.cs | 13 +- src/Umbraco.Web/Routing/LookupByNiceUrl.cs | 18 +- .../Routing/LookupByNiceUrlAndTemplate.cs | 13 +- src/Umbraco.Web/Routing/LookupByProfile.cs | 16 +- .../Routing/RoutesCacheResolver.cs | 2 +- src/Umbraco.Web/Routing/RoutingContext.cs | 12 +- src/Umbraco.Web/UmbracoApplication.cs | 20 +- src/Umbraco.Web/UmbracoModule.cs | 494 +++++++++--------- 23 files changed, 710 insertions(+), 572 deletions(-) rename src/Umbraco.Core/Resolving/{MultipleResolverBase.cs => ManyObjectResolverBase.cs} (81%) rename src/Umbraco.Core/Resolving/{SingleResolverBase.cs => SingleObjectResolverBase.cs} (72%) diff --git a/src/Umbraco.Core/DisposableTimer.cs b/src/Umbraco.Core/DisposableTimer.cs index 2b9dd6a273..5269244609 100644 --- a/src/Umbraco.Core/DisposableTimer.cs +++ b/src/Umbraco.Core/DisposableTimer.cs @@ -41,17 +41,56 @@ namespace Umbraco.Core return new DisposableTimer(callback); } + /// + /// Adds a start and end log entry as Info and tracks how long it takes until disposed. + /// + /// + /// + /// + /// public static DisposableTimer TraceDuration(string startMessage, string completeMessage) { return TraceDuration(typeof(T), startMessage, completeMessage); } + /// + /// Adds a start and end log entry as Info and tracks how long it takes until disposed. + /// + /// + /// + /// + /// public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage) { LogHelper.Info(loggerType, () => startMessage); return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)")); } + /// + /// Adds a start and end log entry as Debug and tracks how long it takes until disposed. + /// + /// + /// + /// + /// + public static DisposableTimer DebugDuration(string startMessage, string completeMessage) + { + return DebugDuration(typeof(T), startMessage, completeMessage); + } + + /// + /// Adds a start and end log entry as Debug and tracks how long it takes until disposed. + /// + /// + /// + /// + /// + public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage) + { + LogHelper.Info(loggerType, () => startMessage); + return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)")); + } + /// /// Handles the disposal of resources. Derived from abstract class which handles common required locking logic. /// diff --git a/src/Umbraco.Core/PluginTypeResolver.cs b/src/Umbraco.Core/PluginTypeResolver.cs index 62e548d901..f2e5994f57 100644 --- a/src/Umbraco.Core/PluginTypeResolver.cs +++ b/src/Umbraco.Core/PluginTypeResolver.cs @@ -85,7 +85,7 @@ namespace Umbraco.Core internal IEnumerable CreateInstances(IEnumerable types, bool throwException = false) { var typesAsArray = types.ToArray(); - using (DisposableTimer.TraceDuration( + using (DisposableTimer.DebugDuration( string.Format("Starting instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName), string.Format("Completed instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName))) { diff --git a/src/Umbraco.Core/Resolving/MultipleResolverBase.cs b/src/Umbraco.Core/Resolving/ManyObjectResolverBase.cs similarity index 81% rename from src/Umbraco.Core/Resolving/MultipleResolverBase.cs rename to src/Umbraco.Core/Resolving/ManyObjectResolverBase.cs index 01e4c861f8..6aac79de18 100644 --- a/src/Umbraco.Core/Resolving/MultipleResolverBase.cs +++ b/src/Umbraco.Core/Resolving/ManyObjectResolverBase.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Resolving /// Used to resolve multiple types from a collection. The collection can also be modified at runtime/application startup. /// An example of this is MVCs ViewEngines collection. /// - internal abstract class MultipleResolverBase : ResolverBase + internal abstract class ManyObjectResolverBase : ResolverBase where TResolver : class where TResolved : class { @@ -23,18 +23,18 @@ namespace Umbraco.Core.Resolving protected readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim(); /// - /// Initializes a new instance of the class with an empty list of objects. + /// Initializes a new instance of the class with an empty list of objects. /// - protected MultipleResolverBase() + protected ManyObjectResolverBase() { _resolved = new List(); } /// - /// Initializes a new instance of the class with an initial list of objects. + /// Initializes a new instance of the class with an initial list of objects. /// /// The list of objects. - protected MultipleResolverBase(IEnumerable value) + protected ManyObjectResolverBase(IEnumerable value) { _resolved = new List(value); } diff --git a/src/Umbraco.Core/Resolving/ManyWeightedResolved.cs b/src/Umbraco.Core/Resolving/ManyWeightedResolved.cs index 683e9dce99..14161df9ec 100644 --- a/src/Umbraco.Core/Resolving/ManyWeightedResolved.cs +++ b/src/Umbraco.Core/Resolving/ManyWeightedResolved.cs @@ -5,155 +5,155 @@ using System.Text; namespace Umbraco.Core.Resolving { - internal class ManyWeightedResolved - { - List _resolved = new List(); - Dictionary _weights = new Dictionary(); + //internal class ManyWeightedResolved + //{ + // List _resolved = new List(); + // Dictionary _weights = new Dictionary(); - public ManyWeightedResolved() - { - Resolution.Frozen += (sender, e) => - { - _resolved = _resolved.OrderBy(r => _weights[r.GetType()]).ToList(); - _weights = null; - }; - } + // public ManyWeightedResolved() + // { + // Resolution.Frozen += (sender, e) => + // { + // _resolved = _resolved.OrderBy(r => _weights[r.GetType()]).ToList(); + // _weights = null; + // }; + // } - public ManyWeightedResolved(IEnumerable resolved) - : this() - { - _resolved.AddRange(resolved); - foreach (var type in _resolved.Select(r => r.GetType())) - _weights.Add(type, ResolutionWeightAttribute.ReadWeight(type)); - } + // public ManyWeightedResolved(IEnumerable resolved) + // : this() + // { + // _resolved.AddRange(resolved); + // foreach (var type in _resolved.Select(r => r.GetType())) + // _weights.Add(type, ResolutionWeightAttribute.ReadWeight(type)); + // } - public IEnumerable Values - { - get { return _resolved; } - } + // public IEnumerable Values + // { + // get { return _resolved; } + // } - #region Manage collection + // #region Manage collection - public void Add(TResolved value) - { - Resolution.EnsureNotFrozen(); + // public void Add(TResolved value) + // { + // Resolution.EnsureNotFrozen(); - var type = value.GetType(); - EnsureNotExists(type); - _resolved.Add(value); - _weights[type] = ResolutionWeightAttribute.ReadWeight(type); - } + // var type = value.GetType(); + // EnsureNotExists(type); + // _resolved.Add(value); + // _weights[type] = ResolutionWeightAttribute.ReadWeight(type); + // } - public void Add(TResolved value, int weight) - { - Resolution.EnsureNotFrozen(); + // public void Add(TResolved value, int weight) + // { + // Resolution.EnsureNotFrozen(); - var type = value.GetType(); - EnsureNotExists(type); - _resolved.Add(value); - _weights[type] = weight; - } + // var type = value.GetType(); + // EnsureNotExists(type); + // _resolved.Add(value); + // _weights[type] = weight; + // } - public void AddRange(IEnumerable values) - { - Resolution.EnsureNotFrozen(); + // public void AddRange(IEnumerable values) + // { + // Resolution.EnsureNotFrozen(); - foreach (var value in values) - { - var type = value.GetType(); - EnsureNotExists(type); - _resolved.Add(value); - _weights[type] = ResolutionWeightAttribute.ReadWeight(type); - } - } + // foreach (var value in values) + // { + // var type = value.GetType(); + // EnsureNotExists(type); + // _resolved.Add(value); + // _weights[type] = ResolutionWeightAttribute.ReadWeight(type); + // } + // } - //public void SetWeight(TResolved value, int weight) - //{ - // Resolution.EnsureNotFrozen(); + // //public void SetWeight(TResolved value, int weight) + // //{ + // // Resolution.EnsureNotFrozen(); - // var type = value.GetType(); - // EnsureExists(type); - // _weights[type] = weight; - //} + // // var type = value.GetType(); + // // EnsureExists(type); + // // _weights[type] = weight; + // //} - public void SetWeight(int weight) - { - Resolution.EnsureNotFrozen(); + // public void SetWeight(int weight) + // { + // Resolution.EnsureNotFrozen(); - var type = typeof(TResolving); - EnsureExists(type); - _weights[type] = weight; - } + // var type = typeof(TResolving); + // EnsureExists(type); + // _weights[type] = weight; + // } - //public int GetWeight(TResolved value) - //{ - // var type = value.GetType(); - // EnsureExists(type); - // return _weights[value.GetType()]; - //} + // //public int GetWeight(TResolved value) + // //{ + // // var type = value.GetType(); + // // EnsureExists(type); + // // return _weights[value.GetType()]; + // //} - public int GetWeight() - { - var type = typeof(TResolving); - EnsureExists(type); - return _weights[type]; - } + // public int GetWeight() + // { + // var type = typeof(TResolving); + // EnsureExists(type); + // return _weights[type]; + // } - //public void Remove(TResolved value) - //{ - // Resolution.EnsureNotFrozen(); + // //public void Remove(TResolved value) + // //{ + // // Resolution.EnsureNotFrozen(); - // var type = value.GetType(); - // var remove = _resolved.SingleOrDefault(r => r.GetType() == type); - // if (remove != null) - // { - // _resolved.Remove(remove); - // _weights.Remove(remove.GetType()); - // } - //} + // // var type = value.GetType(); + // // var remove = _resolved.SingleOrDefault(r => r.GetType() == type); + // // if (remove != null) + // // { + // // _resolved.Remove(remove); + // // _weights.Remove(remove.GetType()); + // // } + // //} - public void Remove() - { - Resolution.EnsureNotFrozen(); + // public void Remove() + // { + // Resolution.EnsureNotFrozen(); - var type = typeof(TResolving); - var remove = _resolved.SingleOrDefault(r => r.GetType() == type); - if (remove != null) - { - _resolved.Remove(remove); - _weights.Remove(remove.GetType()); - } - } + // var type = typeof(TResolving); + // var remove = _resolved.SingleOrDefault(r => r.GetType() == type); + // if (remove != null) + // { + // _resolved.Remove(remove); + // _weights.Remove(remove.GetType()); + // } + // } - public void Clear() - { - Resolution.EnsureNotFrozen(); + // public void Clear() + // { + // Resolution.EnsureNotFrozen(); - _resolved = new List(); - _weights = new Dictionary(); - } + // _resolved = new List(); + // _weights = new Dictionary(); + // } - #endregion + // #endregion - #region Utilities + // #region Utilities - public bool Exists(Type type) - { - return _resolved.Any(r => r.GetType() == type); - } + // public bool Exists(Type type) + // { + // return _resolved.Any(r => r.GetType() == type); + // } - void EnsureExists(Type type) - { - if (!Exists(type)) - throw new InvalidOperationException("There is not value of that type in the collection."); - } + // void EnsureExists(Type type) + // { + // if (!Exists(type)) + // throw new InvalidOperationException("There is not value of that type in the collection."); + // } - void EnsureNotExists(Type type) - { - if (Exists(type)) - throw new InvalidOperationException("A value of that type already exists in the collection."); - } + // void EnsureNotExists(Type type) + // { + // if (Exists(type)) + // throw new InvalidOperationException("A value of that type already exists in the collection."); + // } - #endregion - } + // #endregion + //} } diff --git a/src/Umbraco.Core/Resolving/ManyWeightedResolverBase.cs b/src/Umbraco.Core/Resolving/ManyWeightedResolverBase.cs index 44b313aec6..061f8423b2 100644 --- a/src/Umbraco.Core/Resolving/ManyWeightedResolverBase.cs +++ b/src/Umbraco.Core/Resolving/ManyWeightedResolverBase.cs @@ -5,63 +5,63 @@ using System.Text; namespace Umbraco.Core.Resolving { - internal abstract class ManyWeightedResolverBase : ResolverBase - where TResolver : class - { - readonly ManyWeightedResolved _resolved; + //internal abstract class ManyWeightedResolverBase : ResolverBase + // where TResolver : class + //{ + // readonly ManyWeightedResolved _resolved; - protected ManyWeightedResolverBase() - { - _resolved = new ManyWeightedResolved(); - } + // protected ManyWeightedResolverBase() + // { + // _resolved = new ManyWeightedResolved(); + // } - protected ManyWeightedResolverBase(IEnumerable values) - { - _resolved = new ManyWeightedResolved(values); - } + // protected ManyWeightedResolverBase(IEnumerable values) + // { + // _resolved = new ManyWeightedResolved(values); + // } - protected IEnumerable Values - { - get { return _resolved.Values; } - } + // protected IEnumerable Values + // { + // get { return _resolved.Values; } + // } - #region Manage collection + // #region Manage collection - public void Add(TResolved value) - { - _resolved.Add(value); - } + // public void Add(TResolved value) + // { + // _resolved.Add(value); + // } - public void Add(TResolved value, int weight) - { - _resolved.Add(value, weight); - } + // public void Add(TResolved value, int weight) + // { + // _resolved.Add(value, weight); + // } - public void AddRange(IEnumerable values) - { - _resolved.AddRange(values); - } + // public void AddRange(IEnumerable values) + // { + // _resolved.AddRange(values); + // } - public void SetWeight(int weight) - { - _resolved.SetWeight(weight); - } + // public void SetWeight(int weight) + // { + // _resolved.SetWeight(weight); + // } - public int GetWeight() - { - return _resolved.GetWeight(); - } + // public int GetWeight() + // { + // return _resolved.GetWeight(); + // } - public void Remove() - { - _resolved.Remove(); - } + // public void Remove() + // { + // _resolved.Remove(); + // } - public void Clear() - { - _resolved.Clear(); - } + // public void Clear() + // { + // _resolved.Clear(); + // } - #endregion - } + // #endregion + //} } diff --git a/src/Umbraco.Core/Resolving/ResolutionWeightAttribute.cs b/src/Umbraco.Core/Resolving/ResolutionWeightAttribute.cs index 6cd11ec910..c888798513 100644 --- a/src/Umbraco.Core/Resolving/ResolutionWeightAttribute.cs +++ b/src/Umbraco.Core/Resolving/ResolutionWeightAttribute.cs @@ -5,22 +5,22 @@ using System.Text; namespace Umbraco.Core.Resolving { - [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)] - internal class ResolutionWeightAttribute : Attribute - { - public const int DefaultWeight = 100; + //[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)] + //internal class ResolutionWeightAttribute : Attribute + //{ + // public const int DefaultWeight = 100; - public ResolutionWeightAttribute(int weight) - { - this.Weight = weight; - } + // public ResolutionWeightAttribute(int weight) + // { + // this.Weight = weight; + // } - public int Weight { get; private set; } + // public int Weight { get; private set; } - public static int ReadWeight(Type type) - { - var attr = type.GetCustomAttribute(false); - return attr != null ? attr.Weight : DefaultWeight; - } - } + // public static int ReadWeight(Type type) + // { + // var attr = type.GetCustomAttribute(false); + // return attr != null ? attr.Weight : DefaultWeight; + // } + //} } diff --git a/src/Umbraco.Core/Resolving/ResolverBase.cs b/src/Umbraco.Core/Resolving/ResolverBase.cs index 2d27ac1f21..56c0bcd735 100644 --- a/src/Umbraco.Core/Resolving/ResolverBase.cs +++ b/src/Umbraco.Core/Resolving/ResolverBase.cs @@ -7,9 +7,36 @@ namespace Umbraco.Core.Resolving /// base class for resolvers which declare a singleton accessor /// /// - internal abstract class ResolverBase - where TResolver : class + internal abstract class ResolverBase where TResolver : class { - public static TResolver Current { get; set; } + static TResolver _resolver; + + //TODO: This is not correct, this will be the same lock for all ResolverBase classes!! + static readonly ReaderWriterLockSlim ResolversLock = new ReaderWriterLockSlim(); + + public static TResolver Current + { + get + { + using (new ReadLock(ResolversLock)) + { + if (_resolver == null) + throw new InvalidOperationException("Current has not been initialized. You must initialize Current before trying to read it."); + return _resolver; + } + } + + set + { + using (new WriteLock(ResolversLock)) + { + if (value == null) + throw new ArgumentNullException("value"); + if (_resolver != null) + throw new InvalidOperationException("Current has already been initialized. It is not possible to re-initialize Current once it has been initialized."); + _resolver = value; + } + } + } } } diff --git a/src/Umbraco.Core/Resolving/SingleResolverBase.cs b/src/Umbraco.Core/Resolving/SingleObjectResolverBase.cs similarity index 72% rename from src/Umbraco.Core/Resolving/SingleResolverBase.cs rename to src/Umbraco.Core/Resolving/SingleObjectResolverBase.cs index fb5475dd3c..a77d98f680 100644 --- a/src/Umbraco.Core/Resolving/SingleResolverBase.cs +++ b/src/Umbraco.Core/Resolving/SingleObjectResolverBase.cs @@ -11,29 +11,29 @@ namespace Umbraco.Core.Resolving /// Used for 'singly' registered objects. An example is like the MVC Controller Factory, only one exists application wide and it can /// be get/set. /// - internal abstract class SingleResolverBase : ResolverBase + internal abstract class SingleObjectResolverBase : ResolverBase where TResolver : class where TResolved : class { TResolved _resolved; readonly bool _canBeNull; - protected SingleResolverBase() + protected SingleObjectResolverBase() : this(false) { } - protected SingleResolverBase(TResolved value) + protected SingleObjectResolverBase(TResolved value) : this(false) { _resolved = value; } - protected SingleResolverBase(bool canBeNull) + protected SingleObjectResolverBase(bool canBeNull) { _canBeNull = canBeNull; } - protected SingleResolverBase(TResolved value, bool canBeNull) + protected SingleObjectResolverBase(TResolved value, bool canBeNull) { _resolved = value; _canBeNull = canBeNull; diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ee19019c11..a972e320fe 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -66,12 +66,12 @@ - + - + diff --git a/src/Umbraco.Web/ContentStore.cs b/src/Umbraco.Web/ContentStore.cs index e13714c9ac..45017bc842 100644 --- a/src/Umbraco.Web/ContentStore.cs +++ b/src/Umbraco.Web/ContentStore.cs @@ -120,7 +120,7 @@ namespace Umbraco.Web { // if not in a domain - what is the default page? // let's say it is the first one in the tree, if any - xpath = "/root/*[@isDoc and first]"; + xpath = "(/root/*[@isDoc])[1]"; } } else diff --git a/src/Umbraco.Web/PluginTypeResolverExtensions.cs b/src/Umbraco.Web/PluginTypeResolverExtensions.cs index fa8ac22980..3c02fdfeb5 100644 --- a/src/Umbraco.Web/PluginTypeResolverExtensions.cs +++ b/src/Umbraco.Web/PluginTypeResolverExtensions.cs @@ -13,15 +13,15 @@ namespace Umbraco.Web public static class PluginTypeResolverExtensions { - /// - /// Returns all IDocumentLookup types - /// - /// - /// - internal static IEnumerable ResolveLookups(this PluginTypeResolver resolver) - { - return resolver.ResolveTypes(); - } + ///// + ///// Returns all IDocumentLookup types + ///// + ///// + ///// + //internal static IEnumerable ResolveLookups(this PluginTypeResolver resolver) + //{ + // return resolver.ResolveTypes(); + //} } } \ No newline at end of file diff --git a/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs b/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs index 8f40b4a98c..908edcfadd 100644 --- a/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs +++ b/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs @@ -9,63 +9,109 @@ using Umbraco.Core.Resolving; namespace Umbraco.Web.Routing { - /// - /// Resolves the implementations and the implementation. - /// - class DocumentLookupsResolver : ResolverBase + class LastChanceLookupResolver : SingleObjectResolverBase { - /// - /// Initializes a new instance of the class with an enumeration of an an . - /// - /// The document lookups. - /// The document last chance lookup. - internal DocumentLookupsResolver(IEnumerable lookupTypes, IDocumentLastChanceLookup lastChanceLookup) + public LastChanceLookupResolver(IDocumentLastChanceLookup lastChanceLookup) { - //TODO: I've changed this to resolve types but the intances are not created yet! - // I've created a method on the PluginTypeResolver to create types: PluginTypesResolver.Current.FindAndCreateInstances() - - - _lookupTypes.AddRange(lookupTypes); - _lastChanceLookup.Value = lastChanceLookup; + Value = lastChanceLookup; } - #region LastChanceLookup - - readonly SingleResolved _lastChanceLookup = new SingleResolved(true); - /// - /// Gets or sets the implementation. + /// Returns the Last Chance Lookup /// - public IDocumentLastChanceLookup DocumentLastChanceLookup + public IDocumentLastChanceLookup LastChanceLookup { - get { return _lastChanceLookup.Value; } - set { _lastChanceLookup.Value = value; } + get { return Value; } } + } - #endregion + class DocumentLookupsResolver2 : ManyObjectResolverBase + { + private readonly LastChanceLookupResolver _lastChanceLookupResolver; - #region Lookups - - private readonly List _lookupTypes = new List(); - readonly ManyWeightedResolved _lookups = new ManyWeightedResolved(); + internal DocumentLookupsResolver2(IEnumerable lookups, LastChanceLookupResolver lastChanceLookupResolver) + { + _lastChanceLookupResolver = lastChanceLookupResolver; + foreach (var l in lookups) + { + this.Add(l); + } + } /// /// Gets the implementations. /// public IEnumerable DocumentLookups { - get { return _lookups.Values; } + get { return Values; } } - //why do we have this? /// - /// Gets the inner resolution. + /// Gets or sets the implementation. /// - public ManyWeightedResolved DocumentLookupsResolution + public IDocumentLastChanceLookup DocumentLastChanceLookup { - get { return _lookups; } + get { return _lastChanceLookupResolver.LastChanceLookup; } } - - #endregion } + + ///// + ///// Resolves the implementations and the implementation. + ///// + //class DocumentLookupsResolver : ResolverBase + //{ + // /// + // /// Initializes a new instance of the class with an enumeration of an an . + // /// + // /// The document lookups. + // /// The document last chance lookup. + // internal DocumentLookupsResolver(IEnumerable lookupTypes, IDocumentLastChanceLookup lastChanceLookup) + // { + // //TODO: I've changed this to resolve types but the intances are not created yet! + // // I've created a method on the PluginTypeResolver to create types: PluginTypesResolver.Current.FindAndCreateInstances() + + + // _lookupTypes.AddRange(lookupTypes); + // _lastChanceLookup.Value = lastChanceLookup; + // } + + // #region LastChanceLookup + + // readonly SingleResolved _lastChanceLookup = new SingleResolved(true); + + // /// + // /// Gets or sets the implementation. + // /// + // public IDocumentLastChanceLookup DocumentLastChanceLookup + // { + // get { return _lastChanceLookup.Value; } + // set { _lastChanceLookup.Value = value; } + // } + + // #endregion + + // #region Lookups + + // private readonly List _lookupTypes = new List(); + // readonly ManyWeightedResolved _lookups = new ManyWeightedResolved(); + + // /// + // /// Gets the implementations. + // /// + // public IEnumerable DocumentLookups + // { + // get { return _lookups.Values; } + // } + + // //why do we have this? + // /// + // /// Gets the inner resolution. + // /// + // public ManyWeightedResolved DocumentLookupsResolution + // { + // get { return _lookups; } + // } + + // #endregion + //} } diff --git a/src/Umbraco.Web/Routing/DocumentRequest.cs b/src/Umbraco.Web/Routing/DocumentRequest.cs index bc25fc0fbc..95f76615b2 100644 --- a/src/Umbraco.Web/Routing/DocumentRequest.cs +++ b/src/Umbraco.Web/Routing/DocumentRequest.cs @@ -6,6 +6,8 @@ using System.Globalization; using System.Diagnostics; // legacy +using Umbraco.Core; +using Umbraco.Core.Logging; using umbraco.BusinessLogic; using umbraco.cms.businesslogic.web; using umbraco.cms.businesslogic.template; @@ -16,9 +18,8 @@ namespace Umbraco.Web.Routing // represents a request for one specified Umbraco document to be rendered // by one specified template, using one particular culture. // - internal class DocumentRequest + public class DocumentRequest { - static readonly TraceSource Trace = new TraceSource("DocumentRequest"); public DocumentRequest(Uri uri, RoutingContext routingContext) { @@ -152,7 +153,7 @@ namespace Umbraco.Web.Routing // note - we are not handling schemes nor ports here. - Trace.TraceInformation("{0}Uri=\"{1}\"", tracePrefix, this.Uri); + LogHelper.Debug("{0}Uri=\"{1}\"", () => tracePrefix, () => this.Uri); // try to find a domain matching the current request var domainAndUri = Domains.DomainMatch(Domain.GetDomains(), RoutingContext.UmbracoContext.UmbracoUrl, false); @@ -161,9 +162,11 @@ namespace Umbraco.Web.Routing if (domainAndUri != null) { // matching an existing domain - Trace.TraceInformation("{0}Matches domain=\"{1}\", rootId={2}, culture=\"{3}\"", - tracePrefix, - domainAndUri.Domain.Name, domainAndUri.Domain.RootNodeId, domainAndUri.Domain.Language.CultureAlias); + LogHelper.Debug("{0}Matches domain=\"{1}\", rootId={2}, culture=\"{3}\"", + () => tracePrefix, + () => domainAndUri.Domain.Name, + () => domainAndUri.Domain.RootNodeId, + () => domainAndUri.Domain.Language.CultureAlias); this.Domain = domainAndUri.Domain; this.DomainUri = domainAndUri.Uri; @@ -179,13 +182,14 @@ namespace Umbraco.Web.Routing else { // not matching any existing domain - Trace.TraceInformation("{0}Matches no domain", tracePrefix); + LogHelper.Debug("{0}Matches no domain", () => tracePrefix); var defaultLanguage = Language.GetAllAsList().FirstOrDefault(); this.Culture = defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.CultureAlias); } - Trace.TraceInformation("{0}Culture=\"{1}\"", tracePrefix, this.Culture.Name); + LogHelper.Debug("{0}Culture=\"{1}\"", () => tracePrefix, () => this.Culture.Name); + return this.Domain != null; } @@ -196,15 +200,19 @@ namespace Umbraco.Web.Routing public bool LookupDocument() { const string tracePrefix = "LookupDocument: "; - Trace.TraceInformation("{0}Path=\"{1}\"", tracePrefix, this.Uri.AbsolutePath); + LogHelper.Debug("{0}Path=\"{1}\"", () => tracePrefix, () => this.Uri.AbsolutePath); // look for the document // the first successful resolver, if any, will set this.Node, and may also set this.Template // some lookups may implement caching - Trace.TraceInformation("{0}Begin resolvers", tracePrefix); - var lookups = RoutingContext.DocumentLookupsResolver.DocumentLookups; - lookups.Any(lookup => lookup.TrySetDocument(this)); - Trace.TraceInformation("{0}End resolvers, {1}", tracePrefix, (this.HasNode ? "a document was found" : "no document was found")); + + using (DisposableTimer.DebugDuration( + string.Format("{0}Begin resolvers", tracePrefix), + string.Format("{0}End resolvers, {1}", tracePrefix, (this.HasNode ? "a document was found" : "no document was found")))) + { + var lookups = RoutingContext.DocumentLookupsResolver.DocumentLookups; + lookups.Any(lookup => lookup.TrySetDocument(this)); + } // fixme - not handling umbracoRedirect // should come after internal redirects @@ -234,24 +242,24 @@ namespace Umbraco.Web.Routing const int maxLoop = 12; do { - Trace.TraceInformation("{0}{1}", tracePrefix, (i == 0 ? "Begin" : "Loop")); + LogHelper.Debug("{0}{1}", () => tracePrefix, () => (i == 0 ? "Begin" : "Loop")); // handle not found if (!this.HasNode) { this.Is404 = true; - Trace.TraceInformation("{0}No document, try last chance lookup", tracePrefix); + LogHelper.Debug("{0}No document, try last chance lookup", () => tracePrefix); // if it fails then give up, there isn't much more that we can do var lastChance = RoutingContext.DocumentLookupsResolver.DocumentLastChanceLookup; if (lastChance == null || !lastChance.TrySetDocument(this)) { - Trace.TraceInformation("{0}Failed to find a document, give up", tracePrefix); + LogHelper.Debug("{0}Failed to find a document, give up", () => tracePrefix); break; } else { - Trace.TraceInformation("{0}Found a document", tracePrefix); + LogHelper.Debug("{0}Found a document", () => tracePrefix); } } @@ -277,10 +285,10 @@ namespace Umbraco.Web.Routing if (i == maxLoop || j == maxLoop) { - Trace.TraceInformation("{0}Looks like we're running into an infinite loop, abort", tracePrefix); + LogHelper.Debug("{0}Looks like we're running into an infinite loop, abort", () => tracePrefix); this.Node = null; } - Trace.TraceInformation("{0}End", tracePrefix); + LogHelper.Debug("{0}End", () => tracePrefix); } /// @@ -300,7 +308,7 @@ namespace Umbraco.Web.Routing if (!string.IsNullOrWhiteSpace(internalRedirect)) { - Trace.TraceInformation("{0}Found umbracoInternalRedirectId={1}", tracePrefix, internalRedirect); + LogHelper.Debug("{0}Found umbracoInternalRedirectId={1}", () => tracePrefix, () => internalRedirect); int internalRedirectId; if (!int.TryParse(internalRedirect, out internalRedirectId)) @@ -310,12 +318,12 @@ namespace Umbraco.Web.Routing { // bad redirect this.Node = null; - Trace.TraceInformation("{0}Failed to redirect to id={1}: invalid value", tracePrefix, internalRedirect); + LogHelper.Debug("{0}Failed to redirect to id={1}: invalid value", () => tracePrefix, () => internalRedirect); } else if (internalRedirectId == this.NodeId) { // redirect to self - Trace.TraceInformation("{0}Redirecting to self, ignore", tracePrefix); + LogHelper.Debug("{0}Redirecting to self, ignore", () => tracePrefix); } else { @@ -325,11 +333,11 @@ namespace Umbraco.Web.Routing if (node != null) { redirect = true; - Trace.TraceInformation("{0}Redirecting to id={1}", tracePrefix, internalRedirectId); + LogHelper.Debug("{0}Redirecting to id={1}", () => tracePrefix, () => internalRedirectId); } else { - Trace.TraceInformation("{0}Failed to redirect to id={1}: no such published document", tracePrefix, internalRedirectId); + LogHelper.Debug("{0}Failed to redirect to id={1}: no such published document", () => tracePrefix, () => internalRedirectId); } } } @@ -352,32 +360,32 @@ namespace Umbraco.Web.Routing if (Access.IsProtected(this.NodeId, path)) { - Trace.TraceInformation("{0}Page is protected, check for access", tracePrefix); + LogHelper.Debug("{0}Page is protected, check for access", () => tracePrefix); var user = System.Web.Security.Membership.GetUser(); if (user == null || !Member.IsLoggedOn()) { - Trace.TraceInformation("{0}Not logged in, redirect to login page", tracePrefix); + LogHelper.Debug("{0}Not logged in, redirect to login page", () => tracePrefix); var loginPageId = Access.GetLoginPage(path); if (loginPageId != this.NodeId) this.Node = RoutingContext.ContentStore.GetNodeById(loginPageId); } else if (!Access.HasAccces(this.NodeId, user.ProviderUserKey)) { - Trace.TraceInformation("{0}Current member has not access, redirect to error page", tracePrefix); + LogHelper.Debug("{0}Current member has not access, redirect to error page", () => tracePrefix); var errorPageId = Access.GetErrorPage(path); if (errorPageId != this.NodeId) this.Node = RoutingContext.ContentStore.GetNodeById(errorPageId); } else { - Trace.TraceInformation("{0}Current member has access", tracePrefix); + LogHelper.Debug("{0}Current member has access", () => tracePrefix); } } else { - Trace.TraceInformation("{0}Page is not protected", tracePrefix); + LogHelper.Debug("{0}Page is not protected", () => tracePrefix); } } @@ -402,7 +410,7 @@ namespace Umbraco.Web.Routing if (string.IsNullOrWhiteSpace(templateAlias)) { templateAlias = RoutingContext.ContentStore.GetNodeProperty(this.Node, "@template"); - Trace.TraceInformation("{0}Look for template id={1}", tracePrefix, templateAlias); + LogHelper.Debug("{0}Look for template id={1}", () => tracePrefix, () => templateAlias); int templateId; if (!int.TryParse(templateAlias, out templateId)) templateId = 0; @@ -410,19 +418,19 @@ namespace Umbraco.Web.Routing } else { - Trace.TraceInformation("{0}Look for template alias=\"{1}\" (altTemplate)", tracePrefix, templateAlias); + LogHelper.Debug("{0}Look for template alias=\"{1}\" (altTemplate)", () => tracePrefix, () => templateAlias); this.Template = Template.GetByAlias(templateAlias); } if (!this.HasTemplate) { - Trace.TraceInformation("{0}No template was found", tracePrefix); + LogHelper.Debug("{0}No template was found", () => tracePrefix); //TODO: I like the idea of this new setting, but lets get this in to the core at a later time, for now lets just get the basics working. //if (Settings.HandleMissingTemplateAs404) //{ // this.Node = null; - // Trace.TraceInformation("{0}Assume page not found (404)", tracePrefix); + // LogHelper.Debug("{0}Assume page not found (404)", tracePrefix); //} // else we have no template @@ -430,7 +438,7 @@ namespace Umbraco.Web.Routing } else { - Trace.TraceInformation("{0}Found", tracePrefix); + LogHelper.Debug("{0}Found", () => tracePrefix); } } } diff --git a/src/Umbraco.Web/Routing/IDocumentLookup.cs b/src/Umbraco.Web/Routing/IDocumentLookup.cs index 17d74098ee..b84d9b37e2 100644 --- a/src/Umbraco.Web/Routing/IDocumentLookup.cs +++ b/src/Umbraco.Web/Routing/IDocumentLookup.cs @@ -3,7 +3,7 @@ namespace Umbraco.Web.Routing /// /// Provides a method to try to find an assign an Umbraco document to a DocumentRequest. /// - internal interface IDocumentLookup + public interface IDocumentLookup { /// /// Tries to find and assign an Umbraco document to a DocumentRequest. diff --git a/src/Umbraco.Web/Routing/LookupByAlias.cs b/src/Umbraco.Web/Routing/LookupByAlias.cs index 81147be85c..2d2e77ce8e 100644 --- a/src/Umbraco.Web/Routing/LookupByAlias.cs +++ b/src/Umbraco.Web/Routing/LookupByAlias.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Xml; +using Umbraco.Core.Logging; using Umbraco.Core.Resolving; namespace Umbraco.Web.Routing @@ -11,15 +12,14 @@ namespace Umbraco.Web.Routing /// Handles /just/about/anything where /just/about/anything is contained in the umbracoUrlAlias property of a document. /// The alias is the full path to the document. There can be more than one alias, separated by commas. /// - [ResolutionWeight(50)] + //[ResolutionWeight(50)] internal class LookupByAlias : IDocumentLookup { - static readonly TraceSource Trace = new TraceSource("LookupByAlias"); /// /// Tries to find and assign an Umbraco document to a DocumentRequest. /// - /// The DocumentRequest. + /// The DocumentRequest. /// A value indicating whether an Umbraco document was found and assigned. public bool TrySetDocument(DocumentRequest docreq) { @@ -30,13 +30,13 @@ namespace Umbraco.Web.Routing node = docreq.RoutingContext.ContentStore.GetNodeByUrlAlias(docreq.HasDomain ? docreq.Domain.RootNodeId : 0, docreq.Uri.AbsolutePath); if (node != null) { - Trace.TraceInformation("Path \"{0}\" is an alias for id={1}", docreq.Uri.AbsolutePath, docreq.NodeId); + LogHelper.Debug("Path \"{0}\" is an alias for id={1}", () => docreq.Uri.AbsolutePath, () => docreq.NodeId); docreq.Node = node; } } if (node == null) - Trace.TraceInformation("Not an alias"); + LogHelper.Debug("Not an alias"); return node != null; } diff --git a/src/Umbraco.Web/Routing/LookupById.cs b/src/Umbraco.Web/Routing/LookupById.cs index 9418d3843f..038e077cb7 100644 --- a/src/Umbraco.Web/Routing/LookupById.cs +++ b/src/Umbraco.Web/Routing/LookupById.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Xml; +using Umbraco.Core.Logging; using Umbraco.Core.Resolving; namespace Umbraco.Web.Routing @@ -11,15 +12,13 @@ namespace Umbraco.Web.Routing /// /// Handles /1234 where 1234 is the identified of a document. /// - [ResolutionWeight(20)] + //[ResolutionWeight(20)] internal class LookupById : IDocumentLookup { - static readonly TraceSource Trace = new TraceSource("LookupById"); - /// /// Tries to find and assign an Umbraco document to a DocumentRequest. /// - /// The DocumentRequest. + /// The DocumentRequest. /// A value indicating whether an Umbraco document was found and assigned. public bool TrySetDocument(DocumentRequest docreq) { @@ -35,12 +34,12 @@ namespace Umbraco.Web.Routing if (nodeId > 0) { - Trace.TraceInformation("Id={0}", nodeId); + LogHelper.Debug("Id={0}", () => nodeId); node = docreq.RoutingContext.ContentStore.GetNodeById(nodeId); if (node != null) { docreq.Node = node; - Trace.TraceInformation("Found node with id={0}", docreq.NodeId); + LogHelper.Debug("Found node with id={0}", () => docreq.NodeId); } else { @@ -50,7 +49,7 @@ namespace Umbraco.Web.Routing } if (nodeId == -1) - Trace.TraceInformation("Not a node id"); + LogHelper.Debug("Not a node id"); return node != null; } diff --git a/src/Umbraco.Web/Routing/LookupByNiceUrl.cs b/src/Umbraco.Web/Routing/LookupByNiceUrl.cs index 83a089ddad..4bea29e415 100644 --- a/src/Umbraco.Web/Routing/LookupByNiceUrl.cs +++ b/src/Umbraco.Web/Routing/LookupByNiceUrl.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Xml; +using Umbraco.Core.Logging; using Umbraco.Core.Resolving; namespace Umbraco.Web.Routing @@ -10,15 +11,14 @@ namespace Umbraco.Web.Routing /// /// Handles /foo/bar where /foo/bar is the nice url of a document. /// - [ResolutionWeight(10)] + //[ResolutionWeight(10)] internal class LookupByNiceUrl : IDocumentLookup { - static readonly TraceSource Trace = new TraceSource("LookupByNiceUrl"); - + /// /// Tries to find and assign an Umbraco document to a DocumentRequest. /// - /// The DocumentRequest. + /// The DocumentRequest. /// A value indicating whether an Umbraco document was found and assigned. public virtual bool TrySetDocument(DocumentRequest docreq) { @@ -40,7 +40,7 @@ namespace Umbraco.Web.Routing /// The document node, or null. protected XmlNode LookupDocumentNode(DocumentRequest docreq, string route) { - Trace.TraceInformation("Test route \"{0}\"", route); + LogHelper.Debug("Test route \"{0}\"", () => route); //return '0' if in preview mode! var nodeId = !docreq.RoutingContext.UmbracoContext.InPreviewMode @@ -55,7 +55,7 @@ namespace Umbraco.Web.Routing if (node != null) { docreq.Node = node; - Trace.TraceInformation("Cache hit, id={0}", nodeId); + LogHelper.Debug("Cache hit, id={0}", () => nodeId); } else { @@ -65,12 +65,12 @@ namespace Umbraco.Web.Routing if (node == null) { - Trace.TraceInformation("Cache miss, query"); + LogHelper.Debug("Cache miss, query"); node = docreq.RoutingContext.ContentStore.GetNodeByRoute(route); if (node != null) { docreq.Node = node; - Trace.TraceInformation("Query matches, id={0}", docreq.NodeId); + LogHelper.Debug("Query matches, id={0}", () => docreq.NodeId); if (!docreq.RoutingContext.UmbracoContext.InPreviewMode) { @@ -80,7 +80,7 @@ namespace Umbraco.Web.Routing } else { - Trace.TraceInformation("Query does not match"); + LogHelper.Debug("Query does not match"); } } diff --git a/src/Umbraco.Web/Routing/LookupByNiceUrlAndTemplate.cs b/src/Umbraco.Web/Routing/LookupByNiceUrlAndTemplate.cs index 4c02d8793c..58ba1a904b 100644 --- a/src/Umbraco.Web/Routing/LookupByNiceUrlAndTemplate.cs +++ b/src/Umbraco.Web/Routing/LookupByNiceUrlAndTemplate.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Xml; +using Umbraco.Core.Logging; using Umbraco.Core.Resolving; using umbraco.cms.businesslogic.template; @@ -12,15 +13,13 @@ namespace Umbraco.Web.Routing /// Handles /foo/bar/template where /foo/bar is the nice url of a document, and template a template alias. /// If successful, then the template of the document request is also assigned. /// - [ResolutionWeight(30)] + //[ResolutionWeight(30)] internal class LookupByNiceUrlAndTemplate : LookupByNiceUrl, IDocumentLookup { - static readonly TraceSource Trace = new TraceSource("LookupByNiceUrlAndTemplate"); - /// /// Tries to find and assign an Umbraco document to a DocumentRequest. /// - /// The DocumentRequest. + /// The DocumentRequest. /// A value indicating whether an Umbraco document was found and assigned. /// If successful, also assigns the template. public override bool TrySetDocument(DocumentRequest docreq) @@ -39,7 +38,7 @@ namespace Umbraco.Web.Routing var template = Template.GetByAlias(templateAlias); if (template != null) { - Trace.TraceInformation("Valid template: \"{0}\"", templateAlias); + LogHelper.Debug("Valid template: \"{0}\"", () => templateAlias); var route = docreq.HasDomain ? (docreq.Domain.RootNodeId.ToString() + path) : path; node = LookupDocumentNode(docreq, route); @@ -49,12 +48,12 @@ namespace Umbraco.Web.Routing } else { - Trace.TraceInformation("Not a valid template: \"{0}\"", templateAlias); + LogHelper.Debug("Not a valid template: \"{0}\"", () => templateAlias); } } else { - Trace.TraceInformation("No template in path \"/\""); + LogHelper.Debug("No template in path \"/\""); } return node != null; diff --git a/src/Umbraco.Web/Routing/LookupByProfile.cs b/src/Umbraco.Web/Routing/LookupByProfile.cs index 655db393aa..29547b9b97 100644 --- a/src/Umbraco.Web/Routing/LookupByProfile.cs +++ b/src/Umbraco.Web/Routing/LookupByProfile.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Xml; +using Umbraco.Core.Logging; using Umbraco.Core.Resolving; using umbraco; @@ -13,15 +14,14 @@ namespace Umbraco.Web.Routing /// This should rather be done with a rewriting rule. There would be multiple profile pages in multi-sites/multi-langs setups. /// We keep it for backward compatility reasons. /// - [ResolutionWeight(40)] + //[ResolutionWeight(40)] internal class LookupByProfile : LookupByNiceUrl, IDocumentLookup { - static readonly TraceSource Trace = new TraceSource("LookupByProfile"); /// /// Tries to find and assign an Umbraco document to a DocumentRequest. /// - /// The DocumentRequest. + /// The DocumentRequest. /// A value indicating whether an Umbraco document was found and assigned. public override bool TrySetDocument(DocumentRequest docreq) { @@ -37,7 +37,7 @@ namespace Umbraco.Web.Routing if (path == GlobalSettings.ProfileUrl) { isProfile = true; - Trace.TraceInformation("Path \"{0}\" is the profile path", path); + LogHelper.Debug("Path \"{0}\" is the profile path", () => path); var route = docreq.HasDomain ? (docreq.Domain.RootNodeId.ToString() + path) : path; node = LookupDocumentNode(docreq, route); @@ -48,12 +48,16 @@ namespace Umbraco.Web.Routing docreq.RoutingContext.UmbracoContext.HttpContext.Items["umbMemberLogin"] = memberLogin; } else - Trace.TraceInformation("No document matching profile path?"); + { + LogHelper.Debug("No document matching profile path?"); + } } } if (!isProfile) - Trace.TraceInformation("Not the profile path"); + { + LogHelper.Debug("Not the profile path"); + } return node != null; } diff --git a/src/Umbraco.Web/Routing/RoutesCacheResolver.cs b/src/Umbraco.Web/Routing/RoutesCacheResolver.cs index 04a49f4e66..7ef5b11ebc 100644 --- a/src/Umbraco.Web/Routing/RoutesCacheResolver.cs +++ b/src/Umbraco.Web/Routing/RoutesCacheResolver.cs @@ -6,7 +6,7 @@ namespace Umbraco.Web.Routing /// /// Resolves the implementation. /// - class RoutesCacheResolver : SingleResolverBase + class RoutesCacheResolver : SingleObjectResolverBase { /// /// Initializes a new instance of the class with an implementation. diff --git a/src/Umbraco.Web/Routing/RoutingContext.cs b/src/Umbraco.Web/Routing/RoutingContext.cs index dbb3123034..d91568e44d 100644 --- a/src/Umbraco.Web/Routing/RoutingContext.cs +++ b/src/Umbraco.Web/Routing/RoutingContext.cs @@ -7,7 +7,7 @@ namespace Umbraco.Web.Routing /// /// Provides context for the routing of a request. /// - internal class RoutingContext + public class RoutingContext { /// /// Initializes a new instance of the class. @@ -16,9 +16,9 @@ namespace Umbraco.Web.Routing /// The document lookups resolver. /// The content store. /// The nice urls resolver. - public RoutingContext( + internal RoutingContext( UmbracoContext umbracoContext, - DocumentLookupsResolver documentLookupsResolver, + DocumentLookupsResolver2 documentLookupsResolver, ContentStore contentStore, NiceUrlProvider niceUrlResolver) { @@ -36,16 +36,16 @@ namespace Umbraco.Web.Routing /// /// Gets the document lookups resolver. /// - public DocumentLookupsResolver DocumentLookupsResolver { get; private set; } + internal DocumentLookupsResolver2 DocumentLookupsResolver { get; private set; } /// /// Gets the content store. /// - public ContentStore ContentStore { get; private set; } + internal ContentStore ContentStore { get; private set; } /// /// Gets the nice urls provider. /// - public NiceUrlProvider NiceUrlProvider { get; private set; } + internal NiceUrlProvider NiceUrlProvider { get; private set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 60169ed3cd..9d9003c1a6 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -42,10 +42,22 @@ namespace Umbraco.Web //find and initialize the application startup handlers ApplicationStartupHandler.RegisterHandlers(); - // create the resolvers - DocumentLookupsResolver.Current = new DocumentLookupsResolver( - PluginTypeResolver.Current.ResolveLookups(), - new DefaultLastChanceLookup()); + // create the resolvers... + + LastChanceLookupResolver.Current = new LastChanceLookupResolver(new DefaultLastChanceLookup()); + + DocumentLookupsResolver2.Current = new DocumentLookupsResolver2( + //add all known resolvers in the correct order, devs can then modify this list on application startup either by binding to events + //or in their own global.asax + new IDocumentLookup[] + { + new LookupByNiceUrl(), + new LookupById(), + new LookupByNiceUrlAndTemplate(), + new LookupByProfile(), + new LookupByAlias() + }, + LastChanceLookupResolver.Current); RoutesCacheResolver.Current = new RoutesCacheResolver(new DefaultRoutesCache()); OnApplicationStarting(sender, e); diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 3c3bc1be52..df9fa000a6 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -13,119 +13,117 @@ using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Web { - // also look at IOHelper.ResolveUrlsFromTextString - nightmarish?! + // also look at IOHelper.ResolveUrlsFromTextString - nightmarish?! - // context.RewritePath supports ~/ or else must begin with /vdir - // Request.RawUrl is still there - // response.Redirect does?! always remap to /vdir?! + // context.RewritePath supports ~/ or else must begin with /vdir + // Request.RawUrl is still there + // response.Redirect does?! always remap to /vdir?! - public class UmbracoModule : IHttpModule - { + public class UmbracoModule : IHttpModule + { - /// + /// /// Entry point for a request - /// - /// - void ProcessRequest(HttpContextBase httpContext) - { - LogHelper.Debug("Start processing request"); - + /// + /// + void ProcessRequest(HttpContextBase httpContext) + { + LogHelper.Debug("Start processing request"); + //TODO: We need to ensure the below only executes for real requests (i.e. not css, favicon, etc...) // I'm pretty sure we need to bind to the PostHandlerAssigned (or whatever event) and follow the same // practices that is in umbraMVCo - var uri = httpContext.Request.Url; - var lpath = uri.AbsolutePath.ToLower(); + var uri = httpContext.Request.Url; + var lpath = uri.AbsolutePath.ToLower(); - // add Umbraco's signature header - if (!UmbracoSettings.RemoveUmbracoVersionHeader) - httpContext.Response.AddHeader("X-Umbraco-Version", string.Format("{0}.{1}", GlobalSettings.VersionMajor, GlobalSettings.VersionMinor)); + // add Umbraco's signature header + if (!UmbracoSettings.RemoveUmbracoVersionHeader) + httpContext.Response.AddHeader("X-Umbraco-Version", string.Format("{0}.{1}", GlobalSettings.VersionMajor, GlobalSettings.VersionMinor)); //create the legacy UmbracoContext global::umbraco.presentation.UmbracoContext.Current = new global::umbraco.presentation.UmbracoContext(httpContext); - //create the UmbracoContext singleton, one per request!! - var umbracoContext = new UmbracoContext( - httpContext, + //create the UmbracoContext singleton, one per request!! + var umbracoContext = new UmbracoContext( + httpContext, ApplicationContext.Current, - RoutesCacheResolver.Current.RoutesCache); - UmbracoContext.Current = umbracoContext; + RoutesCacheResolver.Current.RoutesCache); + UmbracoContext.Current = umbracoContext; - // NO! - // these are application-wide singletons! + //create request based objects (one per http request)... + + //create a content store + var contentStore = new ContentStore(umbracoContext); + //create the nice urls + var niceUrls = new NiceUrlProvider(contentStore, umbracoContext); + //create the RoutingContext + var routingContext = new RoutingContext( + umbracoContext, + DocumentLookupsResolver2.Current, + contentStore, + niceUrls); - //create a content store - var contentStore = new ContentStore(umbracoContext); - //create the nice urls - var niceUrls = new NiceUrlProvider(contentStore, umbracoContext); - //create the RoutingContext (one per http request) - var routingContext = new RoutingContext( - umbracoContext, - DocumentLookupsResolver.Current, - contentStore, - niceUrls); - // NOT HERE BUT SEE **THERE** BELOW - // create the new document request which will cleanup the uri once and for all - var docreq = new DocumentRequest(uri, routingContext); + var docreq = new DocumentRequest(uri, routingContext); // initialize the DocumentRequest on the UmbracoContext (this is circular dependency but i think in this case is ok) - umbracoContext.DocumentRequest = docreq; + umbracoContext.DocumentRequest = docreq; - //create the LegacyRequestInitializer (one per http request as it relies on the umbraco context!) - var legacyRequestInitializer = new LegacyRequestInitializer(umbracoContext); + //create the LegacyRequestInitializer (one per http request as it relies on the umbraco context!) + var legacyRequestInitializer = new LegacyRequestInitializer(umbracoContext); - // legacy - initialize legacy stuff - legacyRequestInitializer.InitializeRequest(); + // legacy - initialize legacy stuff + legacyRequestInitializer.InitializeRequest(); - // note - at that point the original legacy module did something do handle IIS custom 404 errors - // ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support - // "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain - // to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk. - // - // to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors - // so that they point to a non-existing page eg /redirect-404.aspx + // note - at that point the original legacy module did something do handle IIS custom 404 errors + // ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support + // "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain + // to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk. + // + // to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors + // so that they point to a non-existing page eg /redirect-404.aspx - var ok = true; + var ok = true; - // ensure this is a document request - ok = ok && EnsureDocumentRequest(httpContext, uri, lpath); - // ensure Umbraco is ready to serve documents - ok = ok && EnsureIsReady(httpContext, uri); - // ensure Umbraco is properly configured to serve documents - ok = ok && EnsureIsConfigured(httpContext, uri); - ok = ok && (!UmbracoSettings.EnableBaseRestHandler || EnsureNotBaseRestHandler(httpContext, lpath)); - ok = ok && (EnsureNotBaseRestHandler(httpContext, lpath)); + // ensure this is a document request + ok = ok && EnsureDocumentRequest(httpContext, uri, lpath); + // ensure Umbraco is ready to serve documents + ok = ok && EnsureIsReady(httpContext, uri); + // ensure Umbraco is properly configured to serve documents + ok = ok && EnsureIsConfigured(httpContext, uri); + ok = ok && (!UmbracoSettings.EnableBaseRestHandler || EnsureNotBaseRestHandler(httpContext, lpath)); + ok = ok && (EnsureNotBaseRestHandler(httpContext, lpath)); - if (!ok) - { + if (!ok) + { LogHelper.Debug("End processing request, not transfering to handler"); - return; - } + return; + } - // legacy - no idea what this is - LegacyCleanUmbPageFromQueryString(ref uri, ref lpath); + // legacy - no idea what this is + LegacyCleanUmbPageFromQueryString(ref uri, ref lpath); //**THERE** we should create the doc request // before, we're not sure we handling a doc request docreq.LookupDomain(); - if (docreq.IsRedirect) - httpContext.Response.Redirect(docreq.RedirectUrl, true); - Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture; - docreq.LookupDocument(); - if (docreq.IsRedirect) - httpContext.Response.Redirect(docreq.RedirectUrl, true); + if (docreq.IsRedirect) + httpContext.Response.Redirect(docreq.RedirectUrl, true); + Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture; + docreq.LookupDocument(); + if (docreq.IsRedirect) + httpContext.Response.Redirect(docreq.RedirectUrl, true); - if (docreq.Is404) - httpContext.Response.StatusCode = 404; + if (docreq.Is404) + httpContext.Response.StatusCode = 404; TransferRequest("~/default.aspx" + docreq.Uri.Query); - // it is up to default.aspx to figure out what to display in case - // there is no document (ugly 404 page?) or no template (blank page?) - } + // it is up to default.aspx to figure out what to display in case + // there is no document (ugly 404 page?) or no template (blank page?) + } /// /// Checks if the xml cache file needs to be updated/persisted @@ -142,7 +140,7 @@ namespace Umbraco.Web content.Instance.PersistXmlToFile(); } } - + /// /// Ensures that the request is a document request (i.e. one that the module should handle) /// @@ -150,199 +148,205 @@ namespace Umbraco.Web /// /// /// - bool EnsureDocumentRequest(HttpContextBase httpContext, Uri uri, string lpath) - { - var maybeDoc = true; + bool EnsureDocumentRequest(HttpContextBase httpContext, Uri uri, string lpath) + { + var maybeDoc = true; - // handle directory-urls used for asmx - // legacy - what's the point really? - if (maybeDoc && GlobalSettings.UseDirectoryUrls) - { - int asmxPos = lpath.IndexOf(".asmx/"); - if (asmxPos >= 0) - { - // use uri.AbsolutePath, not path, 'cos path has been lowercased - httpContext.RewritePath(uri.AbsolutePath.Substring(0, asmxPos + 5), // filePath - uri.AbsolutePath.Substring(asmxPos + 5), // pathInfo - uri.Query.TrimStart('?')); - maybeDoc = false; - } - } - - // a document request should be - // /foo/bar/nil - // /foo/bar/nil/ - // /foo/bar/nil.aspx - // where /foo is not a reserved path - - // if the path contains an extension that is not .aspx - // then it cannot be a document request - if (maybeDoc && lpath.Contains('.') && !lpath.EndsWith(".aspx")) - maybeDoc = false; - - // at that point, either we have no extension, or it is .aspx - - // if the path is reserved then it cannot be a document request - if (maybeDoc && GlobalSettings.IsReservedPathOrUrl(lpath)) - maybeDoc = false; - - if (!maybeDoc) + // handle directory-urls used for asmx + // legacy - what's the point really? + if (maybeDoc && GlobalSettings.UseDirectoryUrls) { - LogHelper.Warn("Not a document"); - } + int asmxPos = lpath.IndexOf(".asmx/"); + if (asmxPos >= 0) + { + // use uri.AbsolutePath, not path, 'cos path has been lowercased + httpContext.RewritePath(uri.AbsolutePath.Substring(0, asmxPos + 5), // filePath + uri.AbsolutePath.Substring(asmxPos + 5), // pathInfo + uri.Query.TrimStart('?')); + maybeDoc = false; + } + } - return maybeDoc; - } + // a document request should be + // /foo/bar/nil + // /foo/bar/nil/ + // /foo/bar/nil.aspx + // where /foo is not a reserved path - // ensures Umbraco is ready to handle requests - // if not, set status to 503 and transfer request, and return false - // if yes, return true - bool EnsureIsReady(HttpContextBase httpContext, Uri uri) - { - // ensure we are ready - if (!ApplicationContext.Current.IsReady) - { + // if the path contains an extension that is not .aspx + // then it cannot be a document request + if (maybeDoc && lpath.Contains('.') && !lpath.EndsWith(".aspx")) + maybeDoc = false; + + // at that point, either we have no extension, or it is .aspx + + // if the path is reserved then it cannot be a document request + if (maybeDoc && GlobalSettings.IsReservedPathOrUrl(lpath)) + maybeDoc = false; + + if (!maybeDoc) + { + LogHelper.Warn("Not a document"); + } + + return maybeDoc; + } + + // ensures Umbraco is ready to handle requests + // if not, set status to 503 and transfer request, and return false + // if yes, return true + bool EnsureIsReady(HttpContextBase httpContext, Uri uri) + { + // ensure we are ready + if (!ApplicationContext.Current.IsReady) + { LogHelper.Warn("Umbraco is not ready"); - - httpContext.Response.StatusCode = 503; + + httpContext.Response.StatusCode = 503; // fixme - default.aspx has to be ready for RequestContext.DocumentRequest==null // fixme - in fact we should transfer to an empty html page... - var bootUrl = UriUtility.ToAbsolute(UmbracoSettings.BootSplashPage); - + var bootUrl = UriUtility.ToAbsolute(UmbracoSettings.BootSplashPage); + if (UmbracoSettings.EnableSplashWhileLoading) // legacy - should go - { + { var configPath = UriUtility.ToAbsolute(SystemDirectories.Config); - bootUrl = string.Format("{0}/splashes/booting.aspx?url={1}", configPath, HttpUtility.UrlEncode(uri.ToString())); - // fixme ?orgurl=... ?retry=... - } - - TransferRequest(bootUrl); - return false; - } + bootUrl = string.Format("{0}/splashes/booting.aspx?url={1}", configPath, HttpUtility.UrlEncode(uri.ToString())); + // fixme ?orgurl=... ?retry=... + } - return true; - } + TransferRequest(bootUrl); + return false; + } - // ensures Umbraco is configured - // if not, redirect to install and return false - // if yes, return true - bool EnsureIsConfigured(HttpContextBase httpContext, Uri uri) - { - if (!ApplicationContext.Current.IsConfigured) - { + return true; + } + + // ensures Umbraco is configured + // if not, redirect to install and return false + // if yes, return true + bool EnsureIsConfigured(HttpContextBase httpContext, Uri uri) + { + if (!ApplicationContext.Current.IsConfigured) + { LogHelper.Warn("Umbraco is not configured"); string installPath = UriUtility.ToAbsolute(SystemDirectories.Install); - string installUrl = string.Format("{0}/default.aspx?redir=true&url={1}", installPath, HttpUtility.UrlEncode(uri.ToString())); - httpContext.Response.Redirect(installUrl, true); - return false; - } - return true; - } + string installUrl = string.Format("{0}/default.aspx?redir=true&url={1}", installPath, HttpUtility.UrlEncode(uri.ToString())); + httpContext.Response.Redirect(installUrl, true); + return false; + } + return true; + } - // checks if the current request is a /base REST handler request - // returns false if it is, otherwise true - bool EnsureNotBaseRestHandler(HttpContextBase httpContext, string lpath) - { - // the /base REST handler still lives in umbraco.dll and has - // not been refactored at the moment. it still is a module, - // although it should be a handler, or it should be replaced - // by clean WebAPI. + // checks if the current request is a /base REST handler request + // returns false if it is, otherwise true + bool EnsureNotBaseRestHandler(HttpContextBase httpContext, string lpath) + { + // the /base REST handler still lives in umbraco.dll and has + // not been refactored at the moment. it still is a module, + // although it should be a handler, or it should be replaced + // by clean WebAPI. - // fixme - do it once when initializing the module - string baseUrl = UriUtility.ToAbsolute(SystemDirectories.Base).ToLower(); - if (!baseUrl.EndsWith("/")) - baseUrl += "/"; - if (lpath.StartsWith(baseUrl)) - { + // fixme - do it once when initializing the module + string baseUrl = UriUtility.ToAbsolute(SystemDirectories.Base).ToLower(); + if (!baseUrl.EndsWith("/")) + baseUrl += "/"; + if (lpath.StartsWith(baseUrl)) + { LogHelper.Debug("Detected /base REST handler"); - return false; - } - return true; - } + return false; + } + return true; + } - // transfers the request using the fastest method available on the server - void TransferRequest(string path) - { + // transfers the request using the fastest method available on the server + void TransferRequest(string path) + { LogHelper.Debug("Transfering to " + path); - var integrated = HttpRuntime.UsingIntegratedPipeline; + var integrated = HttpRuntime.UsingIntegratedPipeline; - // fixme - are we doing this properly? - // fixme - handle virtual directory? - // fixme - this does not work 'cos it resets the HttpContext - // so we should move the DocumentRequest stuff etc back to default.aspx? - // but, also, with TransferRequest, auth & co will run on the new (default.aspx) url, - // is that really what we want? I need to talk about it with others. @zpqrtbnk - integrated = false; + // fixme - are we doing this properly? + // fixme - handle virtual directory? + // fixme - this does not work 'cos it resets the HttpContext + // so we should move the DocumentRequest stuff etc back to default.aspx? + // but, also, with TransferRequest, auth & co will run on the new (default.aspx) url, + // is that really what we want? I need to talk about it with others. @zpqrtbnk - // http://msmvps.com/blogs/luisabreu/archive/2007/10/09/are-you-using-the-new-transferrequest.aspx - // http://msdn.microsoft.com/en-us/library/aa344903.aspx - // http://forums.iis.net/t/1146511.aspx + // NOTE: SD: Need to look at how umbraMVCo does this. It is true that the TransferRequest initializes a new HttpContext, + // what we need to do is when we transfer to the handler we send a query string with the found page Id to be looked up + // after we have done our routing check. This however needs some though as we don't want to have to query for this + // page twice. Again, I'll check how umbraMVCo is doing it as I had though about that when i created it :) - if (integrated) - HttpContext.Current.Server.TransferRequest(path); - else - HttpContext.Current.RewritePath(path); - } + integrated = false; + + // http://msmvps.com/blogs/luisabreu/archive/2007/10/09/are-you-using-the-new-transferrequest.aspx + // http://msdn.microsoft.com/en-us/library/aa344903.aspx + // http://forums.iis.net/t/1146511.aspx + + if (integrated) + HttpContext.Current.Server.TransferRequest(path); + else + HttpContext.Current.RewritePath(path); + } - #region Legacy + #region Legacy - // "Clean umbPage from querystring, caused by .NET 2.0 default Auth Controls" - // but really, at the moment I have no idea what this does, and why... - void LegacyCleanUmbPageFromQueryString(ref Uri uri, ref string lpath) - { - string receivedQuery = uri.Query; - string path = uri.AbsolutePath; - string query = null; + // "Clean umbPage from querystring, caused by .NET 2.0 default Auth Controls" + // but really, at the moment I have no idea what this does, and why... + void LegacyCleanUmbPageFromQueryString(ref Uri uri, ref string lpath) + { + string receivedQuery = uri.Query; + string path = uri.AbsolutePath; + string query = null; - if (receivedQuery.Length > 0) - { - // Clean umbPage from querystring, caused by .NET 2.0 default Auth Controls - if (receivedQuery.IndexOf("umbPage") > 0) - { - int ampPos = receivedQuery.IndexOf('&'); - // query contains no ampersand? - if (ampPos < 0) - { - // no ampersand means no original query string - query = String.Empty; - // ampersand would occur past then end the of received query - ampPos = receivedQuery.Length; - } - else - { - // original query string past ampersand - query = receivedQuery.Substring(ampPos + 1, - receivedQuery.Length - ampPos - 1); - } - // get umbPage out of query string (9 = "&umbPage".Length() + 1) - path = receivedQuery.Substring(9, ampPos - 9); //this will fail if there are < 9 characters before the &umbPage query string + if (receivedQuery.Length > 0) + { + // Clean umbPage from querystring, caused by .NET 2.0 default Auth Controls + if (receivedQuery.IndexOf("umbPage") > 0) + { + int ampPos = receivedQuery.IndexOf('&'); + // query contains no ampersand? + if (ampPos < 0) + { + // no ampersand means no original query string + query = String.Empty; + // ampersand would occur past then end the of received query + ampPos = receivedQuery.Length; + } + else + { + // original query string past ampersand + query = receivedQuery.Substring(ampPos + 1, + receivedQuery.Length - ampPos - 1); + } + // get umbPage out of query string (9 = "&umbPage".Length() + 1) + path = receivedQuery.Substring(9, ampPos - 9); //this will fail if there are < 9 characters before the &umbPage query string - // --added when refactoring-- - uri = uri.Rewrite(path, query); - lpath = path.ToLower(); - } - //else - //{ - // // strip off question mark - // query = receivedQuery.Substring(1); - //} - } - } + // --added when refactoring-- + uri = uri.Rewrite(path, query); + lpath = path.ToLower(); + } + //else + //{ + // // strip off question mark + // query = receivedQuery.Substring(1); + //} + } + } - #endregion + #endregion - #region IHttpModule + #region IHttpModule - // initialize the module, this will trigger for each new application - // and there may be more than 1 application per application domain - public void Init(HttpApplication app) - { + // initialize the module, this will trigger for each new application + // and there may be more than 1 application per application domain + public void Init(HttpApplication app) + { // used to be done in PostAuthorizeRequest but then it disabled OutputCaching due // to rewriting happening too early in the chain (Alex Norcliffe 2010-02). app.PostResolveRequestCache += (sender, e) => @@ -352,19 +356,19 @@ namespace Umbraco.Web }; // used to check if the xml cache file needs to be updated/persisted - app.PostRequestHandlerExecute += (sender, e) => - { + app.PostRequestHandlerExecute += (sender, e) => + { var httpContext = ((HttpApplication)sender).Context; PersistXmlCache(new HttpContextWrapper(httpContext)); - }; + }; - // todo: initialize request errors handler - } + // todo: initialize request errors handler + } - public void Dispose() - { } + public void Dispose() + { } - #endregion + #endregion - } + } }