From 646e96ab15c6d6fac7d43617921ce628fde78ca1 Mon Sep 17 00:00:00 2001 From: "shannon@ShandemVaio" Date: Wed, 1 Aug 2012 22:06:15 +0600 Subject: [PATCH] Changed PluginResolverType to PluginManager. Reinstated Resolution and ResolverBase since this gives us more control over all Resolvers and streamlines them. Created IBootManager, CoreBootManager and WebBootManager to handle the application initialization including the creation of Resolvers. This means that if people are using the dlls outside of the web app, they can run the boot strappers to initialize everything. --- src/Umbraco.Core/ApplicationContext.cs | 19 +- src/Umbraco.Core/CacheRefreshersResolver.cs | 67 +++-- src/Umbraco.Core/CoreBootManager.cs | 76 +++++ src/Umbraco.Core/DataTypesResolver.cs | 17 +- src/Umbraco.Core/IBootManager.cs | 31 ++ .../LegacyTransientObjectsResolver.cs | 14 +- src/Umbraco.Core/PluginManager.cs | 268 ++++++++++++++++++ .../Resolving/ManyObjectsResolverBase.cs | 23 +- src/Umbraco.Core/Resolving/Resolution.cs | 35 +++ src/Umbraco.Core/Resolving/ResolverBase.cs | 44 +++ .../Resolving/SingleObjectResolverBase.cs | 4 +- src/Umbraco.Core/Umbraco.Core.csproj | 6 +- .../CacheRefresherFactoryTests.cs | 4 +- src/Umbraco.Tests/ContentStoreTests.cs | 6 +- src/Umbraco.Tests/DataTypeFactoryTests.cs | 4 +- src/Umbraco.Tests/MacroControlFactoryTests.cs | 4 +- src/Umbraco.Tests/MacroEngineFactoryTests.cs | 4 +- src/Umbraco.Tests/MediaFactoryTests.cs | 4 +- .../PackageActionFactoryTests.cs | 4 +- ...tensions.cs => PluginManagerExtensions.cs} | 6 +- ...ResolverTests.cs => PluginManagerTests.cs} | 32 +-- src/Umbraco.Tests/Umbraco.Tests.csproj | 4 +- .../ThumbnailProvidersResolver.cs | 18 +- ...tensions.cs => PluginManagerExtensions.cs} | 10 +- .../Routing/DocumentLookupsResolver.cs | 28 +- src/Umbraco.Web/Routing/DocumentRequest.cs | 2 +- .../Routing/LastChanceLookupResolver.cs | 16 +- .../Routing/RoutesCacheResolver.cs | 17 +- src/Umbraco.Web/Umbraco.Web.csproj | 3 +- src/Umbraco.Web/UmbracoApplication.cs | 47 ++- src/Umbraco.Web/UmbracoApplication.cs.orig | 87 ++++++ src/Umbraco.Web/WebBootManager.cs | 61 ++++ src/Umbraco.Web/umbraco.presentation/macro.cs | 2 +- .../umbraco/Trees/TreeDefinitionCollection.cs | 2 +- .../umbracobase/restExtension.cs | 2 +- ...tensions.cs => PluginManagerExtensions.cs} | 6 +- .../RazorDynamicNode/DynamicNode.cs | 2 +- .../umbraco.MacroEngines.csproj | 2 +- .../ApplicationRegistrar.cs | 2 +- .../ApplicationStartupHandler.cs | 4 +- .../ApplicationTreeRegistrar.cs | 2 +- ...tensions.cs => PluginManagerExtensions.cs} | 12 +- .../umbraco.businesslogic.csproj | 2 +- src/umbraco.cms/Actions/Action.cs | 8 +- ...tensions.cs => PluginManagerExtensions.cs} | 14 +- .../PackageInstance/PackageActions.cs | 4 +- .../businesslogic/macro/MacroEngineFactory.cs | 4 +- .../businesslogic/media/MediaFactory.cs | 4 +- src/umbraco.cms/umbraco.cms.csproj | 2 +- ...tensions.cs => PluginManagerExtensions.cs} | 6 +- .../macrocontainer/MacroControlFactory.cs | 4 +- .../umbraco.editorControls.csproj | 2 +- 52 files changed, 808 insertions(+), 243 deletions(-) create mode 100644 src/Umbraco.Core/CoreBootManager.cs create mode 100644 src/Umbraco.Core/IBootManager.cs create mode 100644 src/Umbraco.Core/PluginManager.cs create mode 100644 src/Umbraco.Core/Resolving/Resolution.cs create mode 100644 src/Umbraco.Core/Resolving/ResolverBase.cs rename src/Umbraco.Tests/{PluginTypeResolverExtensions.cs => PluginManagerExtensions.cs} (60%) rename src/Umbraco.Tests/{PluginTypeResolverTests.cs => PluginManagerTests.cs} (71%) rename src/Umbraco.Web/{PluginTypeResolverExtensions.cs => PluginManagerExtensions.cs} (83%) create mode 100644 src/Umbraco.Web/UmbracoApplication.cs.orig create mode 100644 src/Umbraco.Web/WebBootManager.cs rename src/umbraco.MacroEngines/{PluginTypeResolverExtensions.cs => PluginManagerExtensions.cs} (82%) rename src/umbraco.businesslogic/{PluginTypeResolverExtensions.cs => PluginManagerExtensions.cs} (85%) rename src/umbraco.cms/{PluginTypeResolverExtensions.cs => PluginManagerExtensions.cs} (83%) rename src/umbraco.editorControls/{PluginTypeResolverExtensions.cs => PluginManagerExtensions.cs} (84%) diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs index 37ff9b388b..03c6154124 100644 --- a/src/Umbraco.Core/ApplicationContext.cs +++ b/src/Umbraco.Core/ApplicationContext.cs @@ -1,6 +1,8 @@ using System; using System.Configuration; using System.Diagnostics; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; namespace Umbraco.Core @@ -61,17 +63,6 @@ namespace Umbraco.Core } } - //TODO: This is temporary as we cannot reference umbraco.businesslogic as this will give a circular reference - // CURRENT UMBRACO VERSION ID - private const string _currentVersion = "4.8.0"; - private string CurrentVersion - { - get - { - // change this to be hardcoded in the binary - return _currentVersion; - } - } private bool Configured { get @@ -79,14 +70,12 @@ namespace Umbraco.Core try { string configStatus = ConfigurationStatus; - string currentVersion = CurrentVersion; + string currentVersion = GlobalSettings.CurrentVersion; if (currentVersion != configStatus) { - //Log.Add(LogTypes.Debug, User.GetUser(0), -1, - // "CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + - // "'"); + LogHelper.Info("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'"); } diff --git a/src/Umbraco.Core/CacheRefreshersResolver.cs b/src/Umbraco.Core/CacheRefreshersResolver.cs index 1f8108b369..a4dd818144 100644 --- a/src/Umbraco.Core/CacheRefreshersResolver.cs +++ b/src/Umbraco.Core/CacheRefreshersResolver.cs @@ -6,25 +6,60 @@ using umbraco.interfaces; namespace Umbraco.Core { + ///// + ///// A resolver to return all ICacheRefresher objects + ///// + //internal sealed class CacheRefreshersResolver : LegacyTransientObjectsResolver + //{ + + // #region Singleton + + // private static readonly CacheRefreshersResolver Instance = new CacheRefreshersResolver(PluginTypeResolver.Current.ResolveCacheRefreshers()); + + // public static CacheRefreshersResolver Current + // { + // get { return Instance; } + // } + // #endregion + + // #region Constructors + // static CacheRefreshersResolver() { } + + // /// + // /// Constructor + // /// + // /// + // internal CacheRefreshersResolver(IEnumerable refreshers) + // : base(refreshers) + // { + + // } + // #endregion + + // /// + // /// Gets the implementations. + // /// + // public IEnumerable CacheResolvers + // { + // get + // { + // EnsureRefreshersList(); + // return Values; + // } + // } + + // protected override Guid GetUniqueIdentifier(ICacheRefresher obj) + // { + // return obj.UniqueIdentifier; + // } + //} + /// /// A resolver to return all ICacheRefresher objects /// - internal sealed class CacheRefreshersResolver : LegacyTransientObjectsResolver + internal sealed class CacheRefreshersResolver : LegacyTransientObjectsResolver { - - #region Singleton - - private static readonly CacheRefreshersResolver Instance = new CacheRefreshersResolver(PluginTypeResolver.Current.ResolveCacheRefreshers()); - - public static CacheRefreshersResolver Current - { - get { return Instance; } - } - #endregion - - #region Constructors - static CacheRefreshersResolver() { } - + /// /// Constructor /// @@ -34,7 +69,7 @@ namespace Umbraco.Core { } - #endregion + /// /// Gets the implementations. diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs new file mode 100644 index 0000000000..5dcd90570f --- /dev/null +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Umbraco.Core.Logging; +using Umbraco.Core.Resolving; + +namespace Umbraco.Core +{ + /// + /// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application + /// + /// + /// This does not provide any startup functionality relating to web objects + /// + internal class CoreBootManager : IBootManager + { + + private DisposableTimer _timer; + + public virtual IBootManager Initialize() + { + LogHelper.Info("Umbraco application starting"); + _timer = DisposableTimer.Start(x => LogHelper.Info("Umbraco application startup complete" + " (took " + x + "ms)")); + + //create the ApplicationContext + ApplicationContext.Current = new ApplicationContext() + { + IsReady = true // fixme + }; + + InitializeResolvers(); + return this; + } + + /// + /// Fires after initialization and calls the callback to allow for customizations to occur + /// + /// + /// + public virtual IBootManager Startup(Action afterStartup) + { + afterStartup(ApplicationContext.Current); + return this; + } + + /// + /// Fires after startup and calls the callback once customizations are locked + /// + /// + /// + public virtual IBootManager Complete(Action afterComplete) + { + //freeze resolution to not allow Resolvers to be modified + Resolution.Freeze(); + + //stop the timer and log the output + _timer.Dispose(); + + afterComplete(ApplicationContext.Current); + return this; + } + + /// + /// Create the resolvers + /// + protected virtual void InitializeResolvers() + { + CacheRefreshersResolver.Current = new CacheRefreshersResolver( + PluginManager.Current.ResolveCacheRefreshers()); + + DataTypesResolver.Current = new DataTypesResolver( + PluginManager.Current.ResolveDataTypes()); + } + } +} diff --git a/src/Umbraco.Core/DataTypesResolver.cs b/src/Umbraco.Core/DataTypesResolver.cs index d7effb5690..e69cdab42a 100644 --- a/src/Umbraco.Core/DataTypesResolver.cs +++ b/src/Umbraco.Core/DataTypesResolver.cs @@ -7,22 +7,10 @@ namespace Umbraco.Core /// /// A resolver to return all IDataType objects /// - internal sealed class DataTypesResolver : LegacyTransientObjectsResolver + internal sealed class DataTypesResolver : LegacyTransientObjectsResolver { - #region Singleton - - private static readonly DataTypesResolver Instance = new DataTypesResolver(PluginTypeResolver.Current.ResolveDataTypes()); - - public static DataTypesResolver Current - { - get { return Instance; } - } - #endregion - - #region Constructors - static DataTypesResolver() { } - + /// /// Constructor /// @@ -32,7 +20,6 @@ namespace Umbraco.Core { } - #endregion /// /// Gets the implementations. diff --git a/src/Umbraco.Core/IBootManager.cs b/src/Umbraco.Core/IBootManager.cs new file mode 100644 index 0000000000..bb184c05ed --- /dev/null +++ b/src/Umbraco.Core/IBootManager.cs @@ -0,0 +1,31 @@ +using System; + +namespace Umbraco.Core +{ + /// + /// A bootstrapper interface for the Umbraco application + /// + internal interface IBootManager + { + /// + /// Fires first in the application startup process before any customizations can occur + /// + /// + IBootManager Initialize(); + + /// + /// Fires after initialization and calls the callback to allow for customizations to occur + /// + /// + /// + IBootManager Startup(Action afterStartup); + + /// + /// Fires after startup and calls the callback once customizations are locked + /// + /// + /// + IBootManager Complete(Action afterComplete); + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/LegacyTransientObjectsResolver.cs b/src/Umbraco.Core/LegacyTransientObjectsResolver.cs index 36b88c7c03..725be196cd 100644 --- a/src/Umbraco.Core/LegacyTransientObjectsResolver.cs +++ b/src/Umbraco.Core/LegacyTransientObjectsResolver.cs @@ -9,15 +9,17 @@ namespace Umbraco.Core /// /// A base resolver used for old legacy factories such as the DataTypeFactory or CacheResolverFactory. /// - /// + /// + /// /// /// This class contains basic functionality to mimic the functionality in these old factories since they all return /// transient objects (though this should be changed) and the method GetById needs to lookup a type to an ID and since /// these old classes don't contain metadata, the objects need to be instantiated first to get their metadata, we then store this /// for use in the GetById method. /// - internal abstract class LegacyTransientObjectsResolver : ManyObjectsResolverBase - where T : class + internal abstract class LegacyTransientObjectsResolver : ManyObjectsResolverBase + where TResolved : class + where TResolver : class { #region Constructors @@ -53,19 +55,19 @@ namespace Umbraco.Core /// /// /// - protected abstract Guid GetUniqueIdentifier(T obj); + protected abstract Guid GetUniqueIdentifier(TResolved obj); /// /// Returns a new ICacheRefresher instance by id /// /// /// - public T GetById(Guid id) + public TResolved GetById(Guid id) { EnsureRefreshersList(); return !_trackIdToType.ContainsKey(id) ? null - : PluginTypeResolver.Current.CreateInstance(_trackIdToType[id]); + : PluginManager.Current.CreateInstance(_trackIdToType[id]); } /// diff --git a/src/Umbraco.Core/PluginManager.cs b/src/Umbraco.Core/PluginManager.cs new file mode 100644 index 0000000000..2ce7a9691a --- /dev/null +++ b/src/Umbraco.Core/PluginManager.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using Umbraco.Core.Logging; +using umbraco.interfaces; + +namespace Umbraco.Core +{ + + /// + /// Used to resolve all plugin types and cache them and is also used to instantiate plugin types + /// + /// + /// + /// This class should be used to resolve all plugin types, the TypeFinder should not be used directly! + /// + /// This class can expose extension methods to resolve custom plugins + /// + /// + internal class PluginManager + { + + internal PluginManager() + { + } + + static PluginManager _resolver; + static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim(); + + /// + /// We will ensure that no matter what, only one of these is created, this is to ensure that caching always takes place + /// + /// + /// The setter is generally only used for unit tests + /// + internal static PluginManager Current + { + get + { + using (var l = new UpgradeableReadLock(Lock)) + { + if (_resolver == null) + { + l.UpgradeToWriteLock(); + _resolver = new PluginManager(); + } + return _resolver; + } + } + set { _resolver = value; } + } + + private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); + private readonly HashSet _types = new HashSet(); + private IEnumerable _assemblies; + + /// + /// Returns all classes attributed with XsltExtensionAttribute attribute + /// + /// + internal IEnumerable ResolveCacheRefreshers() + { + return ResolveTypes(); + } + + /// + /// Returns all available IDataType in application + /// + /// + internal IEnumerable ResolveDataTypes() + { + return ResolveTypes(); + } + + /// + /// Gets/sets which assemblies to scan when type finding, generally used for unit testing, if not explicitly set + /// this will search all assemblies known to have plugins and exclude ones known to not have them. + /// + internal IEnumerable AssembliesToScan + { + get { return _assemblies ?? (_assemblies = TypeFinder2.GetAssembliesWithKnownExclusions()); } + set { _assemblies = value; } + } + + /// + /// Used to resolve and create instances of the specified type based on the resolved/cached plugin types + /// + /// + /// set to true if an exception is to be thrown if there is an error during instantiation + /// + internal IEnumerable FindAndCreateInstances(bool throwException = false) + { + var types = ResolveTypes(); + return CreateInstances(types, throwException); + } + + /// + /// Used to create instances of the specified type based on the resolved/cached plugin types + /// + /// + /// + /// set to true if an exception is to be thrown if there is an error during instantiation + /// + internal IEnumerable CreateInstances(IEnumerable types, bool throwException = false) + { + var typesAsArray = types.ToArray(); + 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))) + { + var instances = new List(); + foreach (var t in typesAsArray) + { + try + { + var typeInstance = (T)Activator.CreateInstance(t); + instances.Add(typeInstance); + } + catch (Exception ex) + { + + LogHelper.Error(String.Format("Error creating type {0}", t.FullName), ex); + + if (throwException) + { + throw ex; + } + } + } + return instances; + } + } + + /// + /// Used to create an instance of the specified type based on the resolved/cached plugin types + /// + /// + /// + /// + /// + internal T CreateInstance(Type type, bool throwException = false) + { + var instances = CreateInstances(new[] { type }, throwException); + return instances.FirstOrDefault(); + } + + private IEnumerable ResolveTypes(Func> finder, bool typeIsAttribute = false) + { + using (var readLock = new UpgradeableReadLock(_lock)) + { + using (DisposableTimer.TraceDuration( + String.Format("Starting resolution types of {0}", typeof(T).FullName), + String.Format("Completed resolution of types of {0}", typeof(T).FullName))) + { + //check if the TypeList already exists, if so return it, if not we'll create it + var typeList = _types.SingleOrDefault(x => x.GetListType().IsType()); + if (typeList == null) + { + //upgrade to a write lock since we're adding to the collection + readLock.UpgradeToWriteLock(); + + typeList = new TypeList(typeIsAttribute); + + foreach (var t in finder()) + { + typeList.AddType(t); + } + + //add the type list to the collection + _types.Add(typeList); + } + return typeList.GetTypes(); + } + } + } + + /// + /// Generic method to find the specified type and cache the result + /// + /// + /// + internal IEnumerable ResolveTypes() + { + return ResolveTypes(() => TypeFinder2.FindClassesOfType(AssembliesToScan)); + } + + /// + /// Generic method to find the specified type that has an attribute and cache the result + /// + /// + /// + /// + internal IEnumerable ResolveTypesWithAttribute() + where TAttribute : Attribute + { + return ResolveTypes(() => TypeFinder2.FindClassesOfTypeWithAttribute(AssembliesToScan)); + } + + /// + /// Generic method to find any type that has the specified attribute + /// + /// + /// + internal IEnumerable ResolveAttributedTypes() + where TAttribute : Attribute + { + return ResolveTypes( + () => TypeFinder2.FindClassesWithAttribute(AssembliesToScan), + true); + } + + /// + /// Used for unit tests + /// + /// + internal HashSet GetTypeLists() + { + return _types; + } + + + + #region Private classes + internal abstract class TypeList + { + public abstract void AddType(Type t); + public abstract Type GetListType(); + public abstract IEnumerable GetTypes(); + } + + internal class TypeList : TypeList + { + private readonly bool _typeIsAttribute; + + public TypeList(bool typeIsAttribute = false) + { + _typeIsAttribute = typeIsAttribute; + } + + private readonly List _types = new List(); + + public override void AddType(Type t) + { + + //if the type is an attribute type we won't do the type check + if (_typeIsAttribute || t.IsType()) + { + _types.Add(t); + } + } + + public override Type GetListType() + { + return typeof(T); + } + + public override IEnumerable GetTypes() + { + return _types; + } + } + #endregion + } +} diff --git a/src/Umbraco.Core/Resolving/ManyObjectsResolverBase.cs b/src/Umbraco.Core/Resolving/ManyObjectsResolverBase.cs index ee75e56666..77e6d9ae24 100644 --- a/src/Umbraco.Core/Resolving/ManyObjectsResolverBase.cs +++ b/src/Umbraco.Core/Resolving/ManyObjectsResolverBase.cs @@ -5,15 +5,16 @@ using System.Web; namespace Umbraco.Core.Resolving { - internal abstract class ManyObjectsResolverBase - where TResolved : class + internal abstract class ManyObjectsResolverBase : ResolverBase + where TResolved : class + where TResolver : class { private List _applicationInstances = null; private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); #region Constructors /// - /// 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. /// /// The lifetime scope of instantiated objects, default is per Application protected ManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application) @@ -32,7 +33,7 @@ namespace Umbraco.Core.Resolving } /// - /// 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. /// with creation of objects based on an HttpRequest lifetime scope. /// /// @@ -44,7 +45,7 @@ namespace Umbraco.Core.Resolving } /// - /// 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. /// If set to true will resolve singleton objects which will be created once for the lifetime of the application @@ -55,7 +56,7 @@ namespace Umbraco.Core.Resolving } /// - /// 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 /// with creation of objects based on an HttpRequest lifetime scope. /// /// @@ -90,6 +91,10 @@ namespace Umbraco.Core.Resolving { get { + //We cannot return values unless resolution is locked + if (!Resolution.IsFrozen) + throw new InvalidOperationException("Values cannot be returned until Resolution is frozen"); + switch (LifetimeScope) { case ObjectLifetimeScope.HttpRequest: @@ -103,7 +108,7 @@ namespace Umbraco.Core.Resolving l.UpgradeToWriteLock(); //add the items to the context items (based on full type name) CurrentHttpContext.Items[this.GetType().FullName] = new List( - PluginTypeResolver.Current.CreateInstances(InstanceTypes)); + PluginManager.Current.CreateInstances(InstanceTypes)); } return (List)CurrentHttpContext.Items[this.GetType().FullName]; } @@ -115,14 +120,14 @@ namespace Umbraco.Core.Resolving { l.UpgradeToWriteLock(); _applicationInstances = new List( - PluginTypeResolver.Current.CreateInstances(InstanceTypes)); + PluginManager.Current.CreateInstances(InstanceTypes)); } return _applicationInstances; } case ObjectLifetimeScope.Transient: default: //create new instances each time - return PluginTypeResolver.Current.CreateInstances(InstanceTypes); + return PluginManager.Current.CreateInstances(InstanceTypes); } } } diff --git a/src/Umbraco.Core/Resolving/Resolution.cs b/src/Umbraco.Core/Resolving/Resolution.cs new file mode 100644 index 0000000000..1309e5af83 --- /dev/null +++ b/src/Umbraco.Core/Resolving/Resolution.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Resolving +{ + + + + // notes: nothing in Resolving is thread-safe because everything should happen when the app is starting + + internal class Resolution + { + public static event EventHandler Frozen; + + public static bool IsFrozen { get; private set; } + + public static void EnsureNotFrozen() + { + if (Resolution.IsFrozen) + throw new InvalidOperationException("Resolution is frozen. It is not possible to modify resolvers once resolution is frozen."); + } + + public static void Freeze() + { + if (Resolution.IsFrozen) + throw new InvalidOperationException("Resolution is frozen. It is not possible to freeze it again."); + + IsFrozen = true; + if (Frozen != null) + Frozen(null, null); + } + } +} diff --git a/src/Umbraco.Core/Resolving/ResolverBase.cs b/src/Umbraco.Core/Resolving/ResolverBase.cs new file mode 100644 index 0000000000..e64e39dac4 --- /dev/null +++ b/src/Umbraco.Core/Resolving/ResolverBase.cs @@ -0,0 +1,44 @@ +using System; +using System.Threading; + +namespace Umbraco.Core.Resolving +{ + /// + /// base class for resolvers which declare a singleton accessor + /// + /// + internal abstract class ResolverBase + where TResolver : class + { + static TResolver _resolver; + + //TODO: This is not correct, this will be the same lock for all ResolverBase classes!! + // this will work i suppose but not really ideal + 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/SingleObjectResolverBase.cs b/src/Umbraco.Core/Resolving/SingleObjectResolverBase.cs index 08c587ed8f..3aba9c29a9 100644 --- a/src/Umbraco.Core/Resolving/SingleObjectResolverBase.cs +++ b/src/Umbraco.Core/Resolving/SingleObjectResolverBase.cs @@ -6,12 +6,14 @@ namespace Umbraco.Core.Resolving /// A Resolver to return and set a Single registered object. /// /// + /// /// /// 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 SingleObjectResolverBase + internal abstract class SingleObjectResolverBase : ResolverBase where TResolved : class + where TResolver : class { TResolved _resolved; readonly bool _canBeNull; diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 8b8582f60a..d2e0432f2a 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -50,6 +50,7 @@ + @@ -58,6 +59,7 @@ + @@ -72,6 +74,8 @@ + + @@ -82,7 +86,7 @@ - + diff --git a/src/Umbraco.Tests/CacheRefresherFactoryTests.cs b/src/Umbraco.Tests/CacheRefresherFactoryTests.cs index 51c9a9ffa4..04fdb589eb 100644 --- a/src/Umbraco.Tests/CacheRefresherFactoryTests.cs +++ b/src/Umbraco.Tests/CacheRefresherFactoryTests.cs @@ -16,10 +16,10 @@ namespace Umbraco.Tests TestHelper.SetupLog4NetForTests(); //this ensures its reset - PluginTypeResolver.Current = new PluginTypeResolver(); + PluginManager.Current = new PluginManager(); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginTypeResolver.Current.AssembliesToScan = new[] + PluginManager.Current.AssembliesToScan = new[] { this.GetType().Assembly }; diff --git a/src/Umbraco.Tests/ContentStoreTests.cs b/src/Umbraco.Tests/ContentStoreTests.cs index 5cf28c2b14..ff79acf745 100644 --- a/src/Umbraco.Tests/ContentStoreTests.cs +++ b/src/Umbraco.Tests/ContentStoreTests.cs @@ -70,7 +70,7 @@ namespace Umbraco.Tests { } - private sealed class TransientObjectsResolver : ManyObjectsResolverBase + private sealed class TransientObjectsResolver : ManyObjectsResolverBase { public TransientObjectsResolver() : base(ObjectLifetimeScope.Transient) @@ -83,7 +83,7 @@ namespace Umbraco.Tests } } - private sealed class ApplicationObjectsResolver : ManyObjectsResolverBase + private sealed class ApplicationObjectsResolver : ManyObjectsResolverBase { public ApplicationObjectsResolver() : base(ObjectLifetimeScope.Application) @@ -96,7 +96,7 @@ namespace Umbraco.Tests } } - private sealed class HttpRequestObjectsResolver : ManyObjectsResolverBase + private sealed class HttpRequestObjectsResolver : ManyObjectsResolverBase { public HttpRequestObjectsResolver(HttpContextBase httpContext) : base(httpContext) diff --git a/src/Umbraco.Tests/DataTypeFactoryTests.cs b/src/Umbraco.Tests/DataTypeFactoryTests.cs index 61e75a7338..b3b48f5b01 100644 --- a/src/Umbraco.Tests/DataTypeFactoryTests.cs +++ b/src/Umbraco.Tests/DataTypeFactoryTests.cs @@ -17,10 +17,10 @@ namespace Umbraco.Tests TestHelper.SetupLog4NetForTests(); //this ensures its reset - PluginTypeResolver.Current = new PluginTypeResolver(); + PluginManager.Current = new PluginManager(); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginTypeResolver.Current.AssembliesToScan = new[] + PluginManager.Current.AssembliesToScan = new[] { this.GetType().Assembly }; diff --git a/src/Umbraco.Tests/MacroControlFactoryTests.cs b/src/Umbraco.Tests/MacroControlFactoryTests.cs index 6ffe33b90d..1d7b5fa762 100644 --- a/src/Umbraco.Tests/MacroControlFactoryTests.cs +++ b/src/Umbraco.Tests/MacroControlFactoryTests.cs @@ -18,10 +18,10 @@ namespace Umbraco.Tests TestHelper.SetupLog4NetForTests(); //this ensures its reset - PluginTypeResolver.Current = new PluginTypeResolver(); + PluginManager.Current = new PluginManager(); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginTypeResolver.Current.AssembliesToScan = new[] + PluginManager.Current.AssembliesToScan = new[] { this.GetType().Assembly }; diff --git a/src/Umbraco.Tests/MacroEngineFactoryTests.cs b/src/Umbraco.Tests/MacroEngineFactoryTests.cs index 46046cd0d5..4a058e272e 100644 --- a/src/Umbraco.Tests/MacroEngineFactoryTests.cs +++ b/src/Umbraco.Tests/MacroEngineFactoryTests.cs @@ -18,10 +18,10 @@ namespace Umbraco.Tests TestHelper.SetupLog4NetForTests(); //this ensures its reset - PluginTypeResolver.Current = new PluginTypeResolver(); + PluginManager.Current = new PluginManager(); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginTypeResolver.Current.AssembliesToScan = new[] + PluginManager.Current.AssembliesToScan = new[] { this.GetType().Assembly }; diff --git a/src/Umbraco.Tests/MediaFactoryTests.cs b/src/Umbraco.Tests/MediaFactoryTests.cs index 26c5dc7c90..58fd81d446 100644 --- a/src/Umbraco.Tests/MediaFactoryTests.cs +++ b/src/Umbraco.Tests/MediaFactoryTests.cs @@ -18,10 +18,10 @@ namespace Umbraco.Tests TestHelper.SetupLog4NetForTests(); //this ensures its reset - PluginTypeResolver.Current = new PluginTypeResolver(); + PluginManager.Current = new PluginManager(); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginTypeResolver.Current.AssembliesToScan = new[] + PluginManager.Current.AssembliesToScan = new[] { this.GetType().Assembly }; diff --git a/src/Umbraco.Tests/PackageActionFactoryTests.cs b/src/Umbraco.Tests/PackageActionFactoryTests.cs index c1ec556b74..7df707a44c 100644 --- a/src/Umbraco.Tests/PackageActionFactoryTests.cs +++ b/src/Umbraco.Tests/PackageActionFactoryTests.cs @@ -18,10 +18,10 @@ namespace Umbraco.Tests TestHelper.SetupLog4NetForTests(); //this ensures its reset - PluginTypeResolver.Current = new PluginTypeResolver(); + PluginManager.Current = new PluginManager(); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginTypeResolver.Current.AssembliesToScan = new[] + PluginManager.Current.AssembliesToScan = new[] { this.GetType().Assembly }; diff --git a/src/Umbraco.Tests/PluginTypeResolverExtensions.cs b/src/Umbraco.Tests/PluginManagerExtensions.cs similarity index 60% rename from src/Umbraco.Tests/PluginTypeResolverExtensions.cs rename to src/Umbraco.Tests/PluginManagerExtensions.cs index 91fd0b9010..0daad7be44 100644 --- a/src/Umbraco.Tests/PluginTypeResolverExtensions.cs +++ b/src/Umbraco.Tests/PluginManagerExtensions.cs @@ -7,11 +7,11 @@ namespace Umbraco.Tests /// /// Used for PluginTypeResolverTests /// - internal static class PluginTypeResolverExtensions + internal static class PluginManagerExtensions { - public static IEnumerable ResolveFindMeTypes(this PluginTypeResolver resolver) + public static IEnumerable ResolveFindMeTypes(this PluginManager resolver) { - return resolver.ResolveTypes(); + return resolver.ResolveTypes(); } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/PluginTypeResolverTests.cs b/src/Umbraco.Tests/PluginManagerTests.cs similarity index 71% rename from src/Umbraco.Tests/PluginTypeResolverTests.cs rename to src/Umbraco.Tests/PluginManagerTests.cs index c954690536..f193dc75bf 100644 --- a/src/Umbraco.Tests/PluginTypeResolverTests.cs +++ b/src/Umbraco.Tests/PluginManagerTests.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests { [TestFixture] - public class PluginTypeResolverTests + public class PluginManagerTests { [SetUp] @@ -28,11 +28,11 @@ namespace Umbraco.Tests TestHelper.SetupLog4NetForTests(); //this ensures its reset - PluginTypeResolver.Current = new PluginTypeResolver(); + PluginManager.Current = new PluginManager(); //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver //TODO: Should probably update this so it only searches this assembly and add custom types to be found - PluginTypeResolver.Current.AssembliesToScan = new[] + PluginManager.Current.AssembliesToScan = new[] { this.GetType().Assembly, typeof(ApplicationStartupHandler).Assembly, @@ -58,80 +58,80 @@ namespace Umbraco.Tests [Test] public void Ensure_Only_One_Type_List_Created() { - var foundTypes1 = PluginTypeResolver.Current.ResolveFindMeTypes(); - var foundTypes2 = PluginTypeResolver.Current.ResolveFindMeTypes(); + var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); + var foundTypes2 = PluginManager.Current.ResolveFindMeTypes(); Assert.AreEqual(1, - PluginTypeResolver.Current.GetTypeLists() + PluginManager.Current.GetTypeLists() .Count(x => x.GetListType() == typeof (IFindMe))); } [Test] public void Resolves_Types() { - var foundTypes1 = PluginTypeResolver.Current.ResolveFindMeTypes(); + var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); Assert.AreEqual(2, foundTypes1.Count()); } [Test] public void Resolves_Attributed_Trees() { - var trees = PluginTypeResolver.Current.ResolveAttributedTrees(); + var trees = PluginManager.Current.ResolveAttributedTrees(); Assert.AreEqual(26, trees.Count()); } [Test] public void Resolves_Actions() { - var actions = PluginTypeResolver.Current.ResolveActions(); + var actions = PluginManager.Current.ResolveActions(); Assert.AreEqual(36, actions.Count()); } [Test] public void Resolves_Trees() { - var trees = PluginTypeResolver.Current.ResolveTrees(); + var trees = PluginManager.Current.ResolveTrees(); Assert.AreEqual(36, trees.Count()); } [Test] public void Resolves_Applications() { - var apps = PluginTypeResolver.Current.ResolveApplications(); + var apps = PluginManager.Current.ResolveApplications(); Assert.AreEqual(7, apps.Count()); } [Test] public void Resolves_Action_Handlers() { - var types = PluginTypeResolver.Current.ResolveActionHandlers(); + var types = PluginManager.Current.ResolveActionHandlers(); Assert.AreEqual(1, types.Count()); } [Test] public void Resolves_DataTypes() { - var types = PluginTypeResolver.Current.ResolveDataTypes(); + var types = PluginManager.Current.ResolveDataTypes(); Assert.AreEqual(36, types.Count()); } [Test] public void Resolves_RazorDataTypeModels() { - var types = PluginTypeResolver.Current.ResolveRazorDataTypeModels(); + var types = PluginManager.Current.ResolveRazorDataTypeModels(); Assert.AreEqual(1, types.Count()); } [Test] public void Resolves_RestExtensions() { - var types = PluginTypeResolver.Current.ResolveRestExtensions(); + var types = PluginManager.Current.ResolveRestExtensions(); Assert.AreEqual(2, types.Count()); } [Test] public void Resolves_XsltExtensions() { - var types = PluginTypeResolver.Current.ResolveXsltExtensions(); + var types = PluginManager.Current.ResolveXsltExtensions(); Assert.AreEqual(1, types.Count()); } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index ad37c917d3..a1ab039a98 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -63,8 +63,8 @@ - - + + diff --git a/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs b/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs index 69097746d1..2d76bb6be2 100644 --- a/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs +++ b/src/Umbraco.Web/Media/ThumbnailProviders/ThumbnailProvidersResolver.cs @@ -11,23 +11,10 @@ using umbraco.BusinessLogic.Utils; namespace Umbraco.Web.Media.ThumbnailProviders { - internal sealed class ThumbnailProvidersResolver : ManyObjectsResolverBase + internal sealed class ThumbnailProvidersResolver : ManyObjectsResolverBase { - #region Singleton - - private static readonly ThumbnailProvidersResolver Instance = - new ThumbnailProvidersResolver(PluginTypeResolver.Current.ResolveThumbnailProviders()); - - public static ThumbnailProvidersResolver Current - { - get { return Instance; } - } - #endregion - - #region Constructors - static ThumbnailProvidersResolver() { } - + /// /// Constructor /// @@ -37,7 +24,6 @@ namespace Umbraco.Web.Media.ThumbnailProviders { } - #endregion public IEnumerable Providers { diff --git a/src/Umbraco.Web/PluginTypeResolverExtensions.cs b/src/Umbraco.Web/PluginManagerExtensions.cs similarity index 83% rename from src/Umbraco.Web/PluginTypeResolverExtensions.cs rename to src/Umbraco.Web/PluginManagerExtensions.cs index 67f578ba3d..63658d19ba 100644 --- a/src/Umbraco.Web/PluginTypeResolverExtensions.cs +++ b/src/Umbraco.Web/PluginManagerExtensions.cs @@ -14,14 +14,14 @@ namespace Umbraco.Web /// /// Extension methods for the PluginTypeResolver /// - public static class PluginTypeResolverExtensions + public static class PluginManagerExtensions { /// /// Returns all available ITrees in application /// /// /// - internal static IEnumerable ResolveTrees(this PluginTypeResolver resolver) + internal static IEnumerable ResolveTrees(this PluginManager resolver) { return resolver.ResolveTypes(); } @@ -31,7 +31,7 @@ namespace Umbraco.Web /// /// /// - internal static IEnumerable ResolveRestExtensions(this PluginTypeResolver resolver) + internal static IEnumerable ResolveRestExtensions(this PluginManager resolver) { return resolver.ResolveAttributedTypes(); } @@ -41,7 +41,7 @@ namespace Umbraco.Web /// /// /// - internal static IEnumerable ResolveXsltExtensions(this PluginTypeResolver resolver) + internal static IEnumerable ResolveXsltExtensions(this PluginManager resolver) { return resolver.ResolveAttributedTypes(); } @@ -51,7 +51,7 @@ namespace Umbraco.Web /// /// /// - internal static IEnumerable ResolveThumbnailProviders(this PluginTypeResolver resolver) + internal static IEnumerable ResolveThumbnailProviders(this PluginManager resolver) { return resolver.ResolveTypes(); } diff --git a/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs b/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs index 1692144def..7122d73584 100644 --- a/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs +++ b/src/Umbraco.Web/Routing/DocumentLookupsResolver.cs @@ -13,30 +13,9 @@ namespace Umbraco.Web.Routing /// /// A multiply registered resolver to manage all IDocumentLookup objects /// - internal sealed class DocumentLookupsResolver : ManyObjectsResolverBase + internal sealed class DocumentLookupsResolver : ManyObjectsResolverBase { - #region Singleton - private static readonly DocumentLookupsResolver Instance = new DocumentLookupsResolver( - //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. We could also in the future allow these to be plugin types to be searched by searching for - //any IDocumentLookup with a supplied attribute and find them here and add them to the list - new[] - { - typeof (LookupByNiceUrl), - typeof (LookupById), - typeof (LookupByNiceUrlAndTemplate), - typeof (LookupByProfile), - typeof (LookupByAlias) - }); - - public static DocumentLookupsResolver Current - { - get { return Instance; } - } - #endregion - - #region Constructors - static DocumentLookupsResolver() { } + internal DocumentLookupsResolver(IEnumerable lookups) { foreach (var l in lookups) @@ -44,8 +23,7 @@ namespace Umbraco.Web.Routing this.AddType(l); } } - #endregion - + /// /// Gets the implementations. /// diff --git a/src/Umbraco.Web/Routing/DocumentRequest.cs b/src/Umbraco.Web/Routing/DocumentRequest.cs index 725954542e..3f54cf5866 100644 --- a/src/Umbraco.Web/Routing/DocumentRequest.cs +++ b/src/Umbraco.Web/Routing/DocumentRequest.cs @@ -206,7 +206,7 @@ namespace Umbraco.Web.Routing // the first successful resolver, if any, will set this.Node, and may also set this.Template // some lookups may implement caching - using (DisposableTimer.DebugDuration( + 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")))) { diff --git a/src/Umbraco.Web/Routing/LastChanceLookupResolver.cs b/src/Umbraco.Web/Routing/LastChanceLookupResolver.cs index c5582ba86b..11bfaa4ba1 100644 --- a/src/Umbraco.Web/Routing/LastChanceLookupResolver.cs +++ b/src/Umbraco.Web/Routing/LastChanceLookupResolver.cs @@ -6,24 +6,14 @@ namespace Umbraco.Web.Routing /// /// A singly registered object resolver to manage the IDocumentLastChanceLookup /// - internal sealed class LastChanceLookupResolver : SingleObjectResolverBase + internal sealed class LastChanceLookupResolver : SingleObjectResolverBase { - #region Singleton - private static readonly LastChanceLookupResolver Instance = new LastChanceLookupResolver(new DefaultLastChanceLookup()); - public static LastChanceLookupResolver Current - { - get { return Instance; } - } - #endregion - - #region Constructors - static LastChanceLookupResolver() { } + internal LastChanceLookupResolver(IDocumentLastChanceLookup lastChanceLookup) { Value = lastChanceLookup; } - #endregion - + /// /// Can be used by developers at runtime to set their DocumentLastChanceLookup at app startup /// diff --git a/src/Umbraco.Web/Routing/RoutesCacheResolver.cs b/src/Umbraco.Web/Routing/RoutesCacheResolver.cs index 08dda9b427..25a194571c 100644 --- a/src/Umbraco.Web/Routing/RoutesCacheResolver.cs +++ b/src/Umbraco.Web/Routing/RoutesCacheResolver.cs @@ -6,20 +6,9 @@ namespace Umbraco.Web.Routing /// /// Resolves the implementation. /// - internal sealed class RoutesCacheResolver : SingleObjectResolverBase + internal sealed class RoutesCacheResolver : SingleObjectResolverBase { - #region Singleton - - private static readonly RoutesCacheResolver Instance = new RoutesCacheResolver(new DefaultRoutesCache()); - - public static RoutesCacheResolver Current - { - get { return Instance; } - } - #endregion - - #region Constructors - static RoutesCacheResolver() { } + /// /// Initializes a new instance of the class with an implementation. /// @@ -27,8 +16,6 @@ namespace Umbraco.Web.Routing internal RoutesCacheResolver(IRoutesCache routesCache) : base(routesCache) { } - #endregion - /// diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 46c88a3387..de9c357565 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -239,6 +239,7 @@ Properties\SolutionInfo.cs + @@ -256,7 +257,7 @@ - + diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index e1fb8d7c1f..0c74bc516c 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; -using System.Web.Mvc; using Umbraco.Core; using Umbraco.Web.Routing; using umbraco.businesslogic; @@ -15,8 +14,11 @@ namespace Umbraco.Web /// public class UmbracoApplication : System.Web.HttpApplication { - public static event EventHandler ApplicationStarting; - + private readonly IBootManager _bootManager = new WebBootManager(); + + public static event EventHandler ApplicationStarting; + public static event EventHandler ApplicationStarted; + /// /// Initializes the Umbraco application /// @@ -24,26 +26,12 @@ namespace Umbraco.Web /// protected void Application_Start(object sender, EventArgs e) { - using (DisposableTimer.TraceDuration( - "Umbraco application starting", - "Umbraco application startup complete")) - { - // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK] - ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency"; - ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings; - - //create the ApplicationContext - ApplicationContext.Current = new ApplicationContext() - { - IsReady = true // fixme, do we need this? - }; - - //find and initialize the application startup handlers - ApplicationStartupHandler.RegisterHandlers(); - - OnApplicationStarting(sender, e); - } - } + //boot up the application + _bootManager + .Initialize() + .Startup(appContext => OnApplicationStarting(sender, e)) + .Complete(appContext => OnApplicationStarted(sender, e)); + } /// /// Developers can override this method to modify objects on startup @@ -55,7 +43,18 @@ namespace Umbraco.Web if (ApplicationStarting != null) ApplicationStarting(sender, e); } - + + /// + /// Developers can override this method to do anything they need to do once the application startup routine is completed. + /// + /// + /// + protected virtual void OnApplicationStarted(object sender, EventArgs e) + { + if (ApplicationStarted != null) + ApplicationStarted(sender, e); + } + protected virtual void Application_Error(object sender, EventArgs e) { diff --git a/src/Umbraco.Web/UmbracoApplication.cs.orig b/src/Umbraco.Web/UmbracoApplication.cs.orig new file mode 100644 index 0000000000..402929c4c2 --- /dev/null +++ b/src/Umbraco.Web/UmbracoApplication.cs.orig @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Web.Mvc; +using Umbraco.Core; +using Umbraco.Web.Routing; +using umbraco.businesslogic; + +namespace Umbraco.Web +{ + /// + /// The Umbraco global.asax class + /// + public class UmbracoApplication : System.Web.HttpApplication + { + public static event EventHandler ApplicationStarting; + + public static event EventHandler ApplicationStarted; + + /// + /// Initializes the Umbraco application + /// + /// + /// + protected void Application_Start(object sender, EventArgs e) + { + using (DisposableTimer.TraceDuration( + "Umbraco application starting", + "Umbraco application startup complete")) + { + // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK] + ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency"; + ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings; + + //create the ApplicationContext + ApplicationContext.Current = new ApplicationContext() + { + IsReady = true // fixme + }; + + //find and initialize the application startup handlers + ApplicationStartupHandler.RegisterHandlers(); + + OnApplicationStarting(sender, e); + + //all resolvers are now frozen and cannot be modified + Umbraco.Core.Resolving.Resolution.Freeze(); + + OnApplicationStarted(sender, e); + } + } + + /// + /// Developers can override this method to modify objects on startup + /// + /// + /// + protected virtual void OnApplicationStarting(object sender, EventArgs e) + { + if (ApplicationStarting != null) + ApplicationStarting(sender, e); + } + + /// + /// Developers can override this method to do anything they need to do once the application startup routine is completed. + /// + /// + /// + protected virtual void OnApplicationStarted(object sender, EventArgs e) + { + if (ApplicationStarted != null) + ApplicationStarted(sender, e); + } + + protected virtual void Application_Error(object sender, EventArgs e) + { + + } + + protected virtual void Application_End(object sender, EventArgs e) + { + + } + } +} diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs new file mode 100644 index 0000000000..fb91f72b5c --- /dev/null +++ b/src/Umbraco.Web/WebBootManager.cs @@ -0,0 +1,61 @@ +using System; +using Umbraco.Core; +using Umbraco.Web.Routing; +using umbraco.businesslogic; + +namespace Umbraco.Web +{ + + /// + /// A bootstrapper for the Umbraco application which initializes all objects including the Web portion of the application + /// + internal class WebBootManager : CoreBootManager + { + public void Boot() + { + InitializeResolvers(); + } + + /// + /// Initialize objects before anything during the boot cycle happens + /// + /// + public override IBootManager Initialize() + { + base.Initialize(); + + // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK] + ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency"; + ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings; + + //find and initialize the application startup handlers + ApplicationStartupHandler.RegisterHandlers(); + + return this; + } + + /// + /// Initializes all web based and core resolves + /// + protected override void InitializeResolvers() + { + base.InitializeResolvers(); + + LastChanceLookupResolver.Current = new LastChanceLookupResolver(new DefaultLastChanceLookup()); + + DocumentLookupsResolver.Current = new DocumentLookupsResolver( + //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 Type[] + { + typeof(LookupByNiceUrl), + typeof(LookupById), + typeof(LookupByNiceUrlAndTemplate), + typeof(LookupByProfile), + typeof(LookupByAlias) + }); + RoutesCacheResolver.Current = new RoutesCacheResolver(new DefaultRoutesCache()); + } + + } +} diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index b0138fcf64..231b413bef 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -846,7 +846,7 @@ namespace umbraco // zb-00042 #29949 : do not hide errors, refactor - var foundExtensions = Umbraco.Web.PluginTypeResolverExtensions.ResolveXsltExtensions(PluginTypeResolver.Current); + var foundExtensions = Umbraco.Web.PluginManagerExtensions.ResolveXsltExtensions(PluginManager.Current); foreach (var xsltType in foundExtensions) { var tpAttributes = xsltType.GetCustomAttributes(typeof(XsltExtensionAttribute), true); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs index 316c060772..e8aca83c1a 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs @@ -151,7 +151,7 @@ namespace umbraco.cms.presentation.Trees l.UpgradeToWriteLock(); - var foundITrees = PluginTypeResolver.Current.ResolveTrees(); + var foundITrees = PluginManager.Current.ResolveTrees(); var objTrees = ApplicationTree.getAll(); var appTrees = new List(); diff --git a/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs b/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs index 45a8927c25..da9491e08e 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs @@ -97,7 +97,7 @@ namespace umbraco.presentation.umbracobase { //check for RestExtensionAttribute - var restExtensions = PluginTypeResolver.Current.ResolveRestExtensions(); + var restExtensions = PluginManager.Current.ResolveRestExtensions(); foreach (var t in restExtensions) { diff --git a/src/umbraco.MacroEngines/PluginTypeResolverExtensions.cs b/src/umbraco.MacroEngines/PluginManagerExtensions.cs similarity index 82% rename from src/umbraco.MacroEngines/PluginTypeResolverExtensions.cs rename to src/umbraco.MacroEngines/PluginManagerExtensions.cs index 8a6383af9b..34ddd66b66 100644 --- a/src/umbraco.MacroEngines/PluginTypeResolverExtensions.cs +++ b/src/umbraco.MacroEngines/PluginManagerExtensions.cs @@ -8,15 +8,15 @@ namespace umbraco.MacroEngines /// /// Extension methods for the PluginTypeResolver /// - public static class PluginTypeResolverExtensions - { + public static class PluginManagerExtensions + { /// /// Returns all available IMacroGuiRendering in application /// /// /// - internal static IEnumerable ResolveRazorDataTypeModels(this PluginTypeResolver resolver) + internal static IEnumerable ResolveRazorDataTypeModels(this PluginManager resolver) { return resolver.ResolveTypesWithAttribute(); } diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs index 145a1f7d75..2ac11ce535 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs @@ -451,7 +451,7 @@ namespace umbraco.MacroEngines HttpContext.Current.Trace.Write("RazorDataTypeModelTypes cache is empty, populating cache using PluginTypeResolver..."); try { - PluginTypeResolver.Current.ResolveRazorDataTypeModels() + PluginManager.Current.ResolveRazorDataTypeModels() .ToList() .ConvertAll(type => { diff --git a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj index 19b2bdafac..645eca379c 100644 --- a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj +++ b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj @@ -77,7 +77,7 @@ Properties\SolutionInfo.cs - + diff --git a/src/umbraco.businesslogic/ApplicationRegistrar.cs b/src/umbraco.businesslogic/ApplicationRegistrar.cs index 29cd59ba37..db1921ec0c 100644 --- a/src/umbraco.businesslogic/ApplicationRegistrar.cs +++ b/src/umbraco.businesslogic/ApplicationRegistrar.cs @@ -30,7 +30,7 @@ namespace umbraco.BusinessLogic public ApplicationRegistrar() { // Load all Applications by attribute and add them to the XML config - var types = PluginTypeResolver.Current.ResolveApplications(); + var types = PluginManager.Current.ResolveApplications(); //since applications don't populate their metadata from the attribute and because it is an interface, //we need to interrogate the attributes for the data. Would be better to have a base class that contains diff --git a/src/umbraco.businesslogic/ApplicationStartupHandler.cs b/src/umbraco.businesslogic/ApplicationStartupHandler.cs index 6dc3237d02..62590219c3 100644 --- a/src/umbraco.businesslogic/ApplicationStartupHandler.cs +++ b/src/umbraco.businesslogic/ApplicationStartupHandler.cs @@ -28,8 +28,8 @@ namespace umbraco.businesslogic //now we just create the types... this is kind of silly since these objects don't actually do anything //except run their constructors. - var instances = PluginTypeResolver.Current.CreateInstances( - PluginTypeResolver.Current.ResolveApplicationStartupHandlers()); + var instances = PluginManager.Current.CreateInstances( + PluginManager.Current.ResolveApplicationStartupHandlers()); } } diff --git a/src/umbraco.businesslogic/ApplicationTreeRegistrar.cs b/src/umbraco.businesslogic/ApplicationTreeRegistrar.cs index 635a0af87d..6eb4c2244b 100644 --- a/src/umbraco.businesslogic/ApplicationTreeRegistrar.cs +++ b/src/umbraco.businesslogic/ApplicationTreeRegistrar.cs @@ -31,7 +31,7 @@ namespace umbraco.BusinessLogic public ApplicationTreeRegistrar() { // Load all Trees by attribute and add them to the XML config - var types = PluginTypeResolver.Current.ResolveAttributedTrees(); + var types = PluginManager.Current.ResolveAttributedTrees(); var items = types .Select(x => diff --git a/src/umbraco.businesslogic/PluginTypeResolverExtensions.cs b/src/umbraco.businesslogic/PluginManagerExtensions.cs similarity index 85% rename from src/umbraco.businesslogic/PluginTypeResolverExtensions.cs rename to src/umbraco.businesslogic/PluginManagerExtensions.cs index 2398ac7b78..a87dd2aede 100644 --- a/src/umbraco.businesslogic/PluginTypeResolverExtensions.cs +++ b/src/umbraco.businesslogic/PluginManagerExtensions.cs @@ -8,14 +8,14 @@ namespace umbraco.businesslogic /// /// Extension methods for the PluginTypeResolver /// - public static class PluginTypeResolverExtensions - { + public static class PluginManagerExtensions + { /// /// Returns all available IApplicationStartupHandler objects /// /// /// - internal static IEnumerable ResolveApplicationStartupHandlers(this PluginTypeResolver resolver) + internal static IEnumerable ResolveApplicationStartupHandlers(this PluginManager resolver) { return resolver.ResolveTypes(); } @@ -25,7 +25,7 @@ namespace umbraco.businesslogic /// /// /// - internal static IEnumerable ResolveApplications(this PluginTypeResolver resolver) + internal static IEnumerable ResolveApplications(this PluginManager resolver) { return resolver.ResolveTypesWithAttribute(); } @@ -35,12 +35,10 @@ namespace umbraco.businesslogic /// /// /// - internal static IEnumerable ResolveAttributedTrees(this PluginTypeResolver resolver) + internal static IEnumerable ResolveAttributedTrees(this PluginManager resolver) { return resolver.ResolveTypesWithAttribute(); } - - } } \ No newline at end of file diff --git a/src/umbraco.businesslogic/umbraco.businesslogic.csproj b/src/umbraco.businesslogic/umbraco.businesslogic.csproj index 933db4bd12..ca64da53c1 100644 --- a/src/umbraco.businesslogic/umbraco.businesslogic.csproj +++ b/src/umbraco.businesslogic/umbraco.businesslogic.csproj @@ -149,7 +149,7 @@ - + Code diff --git a/src/umbraco.cms/Actions/Action.cs b/src/umbraco.cms/Actions/Action.cs index 43288279c2..65bbedfaab 100644 --- a/src/umbraco.cms/Actions/Action.cs +++ b/src/umbraco.cms/Actions/Action.cs @@ -65,8 +65,8 @@ namespace umbraco.BusinessLogic.Actions if (ActionHandlers.Count == 0) { ActionHandlers.AddRange( - PluginTypeResolver.Current.CreateInstances( - PluginTypeResolver.Current.ResolveActionHandlers())); + PluginManager.Current.CreateInstances( + PluginManager.Current.ResolveActionHandlers())); } } @@ -79,14 +79,14 @@ namespace umbraco.BusinessLogic.Actions if (Actions.Count == 0) { - var foundIActions = PluginTypeResolver.Current.ResolveActions(); + var foundIActions = PluginManager.Current.ResolveActions(); foreach (var type in foundIActions) { IAction typeInstance; var instance = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); //if the singletone initializer is not found, try simply creating an instance of the IAction if it supports public constructors if (instance == null) - typeInstance = PluginTypeResolver.Current.CreateInstance(type); + typeInstance = PluginManager.Current.CreateInstance(type); else typeInstance = instance.GetValue(null, null) as IAction; diff --git a/src/umbraco.cms/PluginTypeResolverExtensions.cs b/src/umbraco.cms/PluginManagerExtensions.cs similarity index 83% rename from src/umbraco.cms/PluginTypeResolverExtensions.cs rename to src/umbraco.cms/PluginManagerExtensions.cs index b2e8545cc6..3700cab27f 100644 --- a/src/umbraco.cms/PluginTypeResolverExtensions.cs +++ b/src/umbraco.cms/PluginManagerExtensions.cs @@ -12,15 +12,15 @@ namespace umbraco.cms /// /// Extension methods for the PluginTypeResolver /// - public static class PluginTypeResolverExtensions - { + public static class PluginManagerExtensions + { /// /// Returns all available IActionHandler in application /// /// /// - internal static IEnumerable ResolveActionHandlers(this PluginTypeResolver resolver) + internal static IEnumerable ResolveActionHandlers(this PluginManager resolver) { return resolver.ResolveTypes(); } @@ -30,7 +30,7 @@ namespace umbraco.cms /// /// /// - internal static IEnumerable ResolveActions(this PluginTypeResolver resolver) + internal static IEnumerable ResolveActions(this PluginManager resolver) { return resolver.ResolveTypes(); } @@ -40,7 +40,7 @@ namespace umbraco.cms /// /// /// - internal static IEnumerable ResolveMacroEngines(this PluginTypeResolver resolver) + internal static IEnumerable ResolveMacroEngines(this PluginManager resolver) { return resolver.ResolveTypes(); } @@ -50,7 +50,7 @@ namespace umbraco.cms /// /// /// - internal static IEnumerable ResolveMediaFactories(this PluginTypeResolver resolver) + internal static IEnumerable ResolveMediaFactories(this PluginManager resolver) { return resolver.ResolveTypes(); } @@ -60,7 +60,7 @@ namespace umbraco.cms /// /// /// - internal static IEnumerable ResolvePackageActions(this PluginTypeResolver resolver) + internal static IEnumerable ResolvePackageActions(this PluginManager resolver) { return resolver.ResolveTypes(); } diff --git a/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageActions.cs b/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageActions.cs index 151de71d00..38e1ea1933 100644 --- a/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageActions.cs +++ b/src/umbraco.cms/businesslogic/Packager/PackageInstance/PackageActions.cs @@ -32,8 +32,8 @@ namespace umbraco.cms.businesslogic.packager private static void RegisterPackageActions() { PackageActions.AddRange( - PluginTypeResolver.Current.CreateInstances( - PluginTypeResolver.Current.ResolvePackageActions())); + PluginManager.Current.CreateInstances( + PluginManager.Current.ResolvePackageActions())); } /// diff --git a/src/umbraco.cms/businesslogic/macro/MacroEngineFactory.cs b/src/umbraco.cms/businesslogic/macro/MacroEngineFactory.cs index fe5406c76c..722ec762c3 100644 --- a/src/umbraco.cms/businesslogic/macro/MacroEngineFactory.cs +++ b/src/umbraco.cms/businesslogic/macro/MacroEngineFactory.cs @@ -34,8 +34,8 @@ namespace umbraco.cms.businesslogic.macro AllEngines.Clear(); AllEngines.AddRange( - PluginTypeResolver.Current.CreateInstances( - PluginTypeResolver.Current.ResolveMacroEngines())); + PluginManager.Current.CreateInstances( + PluginManager.Current.ResolveMacroEngines())); _isInitialized = true; } diff --git a/src/umbraco.cms/businesslogic/media/MediaFactory.cs b/src/umbraco.cms/businesslogic/media/MediaFactory.cs index da9154549d..985784e757 100644 --- a/src/umbraco.cms/businesslogic/media/MediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/MediaFactory.cs @@ -23,8 +23,8 @@ namespace umbraco.cms.businesslogic.media private static void Initialize() { Factories.AddRange( - PluginTypeResolver.Current.CreateInstances( - PluginTypeResolver.Current.ResolveMediaFactories())); + PluginManager.Current.CreateInstances( + PluginManager.Current.ResolveMediaFactories())); Factories.Sort((f1, f2) => f1.Priority.CompareTo(f2.Priority)); } diff --git a/src/umbraco.cms/umbraco.cms.csproj b/src/umbraco.cms/umbraco.cms.csproj index bdd3b9639d..e297ee8cc7 100644 --- a/src/umbraco.cms/umbraco.cms.csproj +++ b/src/umbraco.cms/umbraco.cms.csproj @@ -267,7 +267,7 @@ - + Code diff --git a/src/umbraco.editorControls/PluginTypeResolverExtensions.cs b/src/umbraco.editorControls/PluginManagerExtensions.cs similarity index 84% rename from src/umbraco.editorControls/PluginTypeResolverExtensions.cs rename to src/umbraco.editorControls/PluginManagerExtensions.cs index ae557087a1..813cac2655 100644 --- a/src/umbraco.editorControls/PluginTypeResolverExtensions.cs +++ b/src/umbraco.editorControls/PluginManagerExtensions.cs @@ -11,15 +11,15 @@ namespace umbraco.editorControls /// /// Extension methods for the PluginTypeResolver /// - public static class PluginTypeResolverExtensions - { + public static class PluginManagerExtensions + { /// /// Returns all available IMacroGuiRendering in application /// /// /// - internal static IEnumerable ResolveMacroRenderings(this PluginTypeResolver resolver) + internal static IEnumerable ResolveMacroRenderings(this PluginManager resolver) { return resolver.ResolveTypes(); } diff --git a/src/umbraco.editorControls/macrocontainer/MacroControlFactory.cs b/src/umbraco.editorControls/macrocontainer/MacroControlFactory.cs index da2b1d301b..ec05126721 100644 --- a/src/umbraco.editorControls/macrocontainer/MacroControlFactory.cs +++ b/src/umbraco.editorControls/macrocontainer/MacroControlFactory.cs @@ -33,7 +33,7 @@ namespace umbraco.editorControls.macrocontainer internal static Control GetMacroRenderControlByType(PersistableMacroProperty prop, string uniqueID) { var m = MacroControlTypes.FindLast(macroGuiCcontrol => macroGuiCcontrol.ToString() == string.Format("{0}.{1}", prop.AssemblyName, prop.TypeName)); - var instance = PluginTypeResolver.Current.CreateInstance(m); + var instance = PluginManager.Current.CreateInstance(m); if (instance != null) { if (!string.IsNullOrEmpty(prop.Value)) @@ -77,7 +77,7 @@ namespace umbraco.editorControls.macrocontainer readLock.UpgradeToWriteLock(); - _macroControlTypes = new List(PluginTypeResolver.Current.ResolveMacroRenderings()); + _macroControlTypes = new List(PluginManager.Current.ResolveMacroRenderings()); } return _macroControlTypes; diff --git a/src/umbraco.editorControls/umbraco.editorControls.csproj b/src/umbraco.editorControls/umbraco.editorControls.csproj index e3a392ee94..c8899da840 100644 --- a/src/umbraco.editorControls/umbraco.editorControls.csproj +++ b/src/umbraco.editorControls/umbraco.editorControls.csproj @@ -176,7 +176,7 @@ - + Code