/// <summary>
        /// Register the editor controllers
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="typeFinder"></param>
        public virtual void RegisterEditorControllers(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_editorControllersRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <UmbracoComponentRegistrar>("RegisterEditorControllers start took {0}ms", () => timer);
                _editorControllersRegistered = true;
            }))
            {
                //now register each type in the container and also add it to our collection
                foreach (var t in FindTypesInRequiredAssemblies <AbstractEditorController>(typeFinder))
                {
                    var editorType = t;

                    RegisterComponent <AbstractEditorController, EditorAttribute, EditorMetadata>(
                        t, builder, true,
                        (pluginDef, attribute, registrar) =>
                        registrar
                        .WithMetadata <EditorMetadata, string>(am => am.ControllerName, UmbracoController.GetControllerName(editorType))
                        .WithMetadata <EditorMetadata, bool>(am => am.HasChildActionDashboards, attribute.HasChildActionDashboards)
                        .WithMetadata <EditorMetadata, bool>(am => am.IsInternalUmbracoEditor,
                                                             editorType.GetCustomAttributes(typeof(UmbracoEditorAttribute), false).Any()));
                }
            }
        }
Пример #2
0
        public virtual void RegisterMacroEngines(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_macroEnginesRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterMacroEngines start took {0}ms", () => timer);
                _macroEnginesRegistered = true;
            }))
            {
                //now register each type in the container and also add it to our collection);
                foreach (var t in FindTypesInRequiredAssemblies <AbstractMacroEngine>(typeFinder))
                {
                    var engineType = t;
                    RegisterComponent <AbstractMacroEngine, MacroEngineAttribute, MacroEngineMetadata>(
                        t, builder, true,
                        (pluginDef, attribute, registrar) =>
                        registrar
                        .WithMetadata <MacroEngineMetadata, string>(am => am.EngineName, attribute.EngineName)
                        .WithMetadata <MacroEngineMetadata, bool>(am => am.IsInternalRebelEngine,
                                                                  engineType.GetCustomAttributes(typeof(RebelMacroEngineAttribute), false).Any())
                        .ScopedAs.Singleton());                                         //only need one each
                }
            }
        }
Пример #3
0
 public void ReadWriterQueryById()
 {
     using (DisposableTimer.Start(x => Console.WriteLine("ReadWriterQueryById took {0}ms", x)))
     {
         // Test provider directly rather than going via Hive
         using (var uow = _xmlReader.CreateReadOnlyUnitOfWork())
         {
             using (DisposableTimer.Start(x => Console.WriteLine("Query and resolution took {0}ms", x)))
             {
                 var item =
                     ((EntityRepositoryReader)uow.ReadRepository).QueryContext.Query().Where(
                         x => x.Id == new HiveEntityUri(1048)).FirstOrDefault();
                 Assert.IsNotNull(item);
                 Assert.AreEqual(item.Id.AsInt, 1048);
             }
         }
         using (var uow = _mappingGroup.CreateReadOnlyUnitOfWork())
         {
             using (DisposableTimer.Start(x => Console.WriteLine("Query and resolution via Hive took {0}ms", x)))
             {
                 var item =
                     uow.ReadRepository.QueryContext.Query().Where(
                         x => x.Id == new HiveEntityUri(1048)).FirstOrDefault();
                 Assert.IsNotNull(item);
                 Assert.AreEqual(item.Id.AsInt, 1048);
             }
         }
     }
 }
Пример #4
0
        /// <summary>
        /// Registers the permissions.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <param name="typeFinder">The type finder.</param>
        public virtual void RegisterPermissions(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_permissionsRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterPermissions start took {0}ms", () => timer);
                _permissionsRegistered = true;
            }))
            {
                foreach (var t in FindTypesInRequiredAssemblies <Permission>(typeFinder))
                {
                    RegisterComponent <Permission, PermissionAttribute, PermissionMetadata>(t, builder, true,
                                                                                            (pluginDef, attribute, registrar) =>
                                                                                            registrar
                                                                                            .WithMetadata <PermissionMetadata, string>(metadata => metadata.Name, attribute.Name)
                                                                                            .WithMetadata <PermissionMetadata, string>(metadata => metadata.Type, attribute.Type)
                                                                                            .WithMetadata <PermissionMetadata, UserType>(metadata => metadata.UserType, attribute.UserType)
                                                                                            .ScopedAs.Singleton()); //only need one each
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Register the tree controllers
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="typeFinder"></param>
        public virtual void RegisterTreeControllers(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_treeControllersRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterTreeControllers start took {0}ms", () => timer);
                _treeControllersRegistered = true;
            }))
            {
                //now register each type in the container and also add it to our collection
                foreach (var t in FindTypesInRequiredAssemblies <TreeController>(typeFinder))
                {
                    var treeType = t;

                    RegisterComponent <TreeController, TreeAttribute, TreeMetadata>(t, builder, true,
                                                                                    (pluginDef, attribute, registrar) =>
                                                                                    registrar
                                                                                    .WithMetadata <EditorMetadata, string>(am => am.ControllerName, RebelController.GetControllerName(treeType))
                                                                                    .WithMetadata <TreeMetadata, string>(am => am.TreeTitle, attribute.TreeTitle)
                                                                                    .WithMetadata <TreeMetadata, bool>(am => am.IsInternalRebelTree,
                                                                                                                       treeType.GetCustomAttributes(typeof(RebelTreeAttribute), false).Any()));
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Registers all tasks.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <param name="typeFinder">The type finder.</param>
        /// <remarks></remarks>
        public virtual void RegisterTasks(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_tasksRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterTasks start took {0}ms", () => timer);
                _tasksRegistered = true;
            }))
            {
                foreach (var t in FindTypesInRequiredAssemblies <AbstractTask>(typeFinder))
                {
                    RegisterComponent <AbstractTask, TaskAttribute, TaskMetadata>(t, builder, false,
                                                                                  (pluginDef, attribute, registrar) =>
                    {
                        //if there's no attribute since we're not requiring that all AbstractTasks have one,
                        //then don't register it into IoC as it might be something like our 'Delegate' task
                        //or another custom one that is added to the task manager at runtime
                        if (attribute == null)
                        {
                            return;
                        }

                        registrar
                        .WithMetadata <TaskMetadata, string>(metadata => metadata.TriggerName, attribute.Trigger)
                        .WithMetadata <TaskMetadata, bool>(metadata => metadata.ContinueOnError, attribute.ContinueOnFailure)
                        .ScopedAs.Singleton();
                    });         //only need one each
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Registers all RebelPropertyEditors
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="typeFinder"></param>
        public virtual void RegisterPropertyEditors(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_propEditorsRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterPropertyEditors start took {0}ms", () => timer);
                _propEditorsRegistered = true;
            }))
            {
                foreach (var t in FindTypesInRequiredAssemblies <PropertyEditor>(typeFinder))
                {
                    var propEditorType = t;

                    //builder.ForType(propEditorType).Register();

                    RegisterComponent <PropertyEditor, PropertyEditorAttribute, PropertyEditorMetadata>(t, builder, true,
                                                                                                        (pluginDef, attribute, registrar) =>
                                                                                                        registrar
                                                                                                        .WithMetadata <PropertyEditorMetadata, string>(am => am.Name, attribute.Name)
                                                                                                        .WithMetadata <PropertyEditorMetadata, string>(am => am.Alias, attribute.Alias)
                                                                                                        .WithMetadata <PropertyEditorMetadata, bool>(am => am.IsContentPropertyEditor, attribute.IsContentPropertyEditor)
                                                                                                        .WithMetadata <PropertyEditorMetadata, bool>(am => am.IsParameterEditor, attribute.IsParameterEditor)
                                                                                                        .WithMetadata <PropertyEditorMetadata, bool>(am => am.IsInternalRebelEditor,
                                                                                                                                                     propEditorType.GetCustomAttributes(typeof(RebelPropertyEditorAttribute), false).Any()));
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Finds & Registers the Surface controllers
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="typeFinder"></param>
        public virtual void RegisterSurfaceControllers(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_surfaceControllersRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterSurfaceControllers start took {0}ms", () => timer);
                _surfaceControllersRegistered = true;
            }))
            {
                //now register each type in the container and also add it to our collection);
                foreach (var t in FindTypesInRequiredAssemblies <SurfaceController>(typeFinder))
                {
                    var surfaceType = t;

                    RegisterComponent <SurfaceController, SurfaceAttribute, SurfaceMetadata>(
                        t, builder, false,
                        (pluginDef, attribute, registrar) =>
                        registrar
                        .WithMetadata <SurfaceMetadata, string>(am => am.ControllerName, RebelController.GetControllerName(surfaceType))
                        .WithMetadata <SurfaceMetadata, bool>(am => am.HasChildActionMacros,
                                                              surfaceType.GetMethods().Any(a => a.GetCustomAttributes(typeof(ChildActionOnlyAttribute), false).Any())));
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Registers all menu items
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="typeFinder"></param>
        public virtual void RegisterMenuItems(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_menuItemsRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterMenuItems start took {0}ms", () => timer);
                _menuItemsRegistered = true;
            }))
            {
                foreach (var t in FindTypesInRequiredAssemblies <MenuItem>(typeFinder))
                {
                    RegisterComponent <MenuItem, MenuItemAttribute, MenuItemMetadata>(t, builder, true,
                                                                                      (pluginDef, attribute, registrar) =>
                                                                                      registrar
                                                                                      .WithMetadata <MenuItemMetadata, string>(am => am.Title, attribute.Title)
                                                                                      .WithMetadata <MenuItemMetadata, bool>(am => am.SeperatorBefore, attribute.SeparatorBefore)
                                                                                      .WithMetadata <MenuItemMetadata, bool>(am => am.SeperatorAfter, attribute.SeparatorAfter)
                                                                                      .WithMetadata <MenuItemMetadata, string>(am => am.Icon, attribute.Icon)
                                                                                      .WithMetadata <MenuItemMetadata, string>(am => am.OnClientClick, attribute.OnClientClick)
                                                                                      .ScopedAs.Singleton()); //only need one each
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Returns an ActionResult for the specified Macro.
        /// </summary>
        /// <param name="macroAlias"></param>
        /// <param name="currentControllerContext"></param>
        /// <param name="isForRichTextEditor">If the request is to render the contents in the back office rich text editor</param>
        /// <param name="resolveContent">callback to get the 'Content' model</param>
        public ActionResult RenderMacro(
            string macroAlias,
            IDictionary <string, string> macroParams,
            ControllerContext currentControllerContext,
            bool isForRichTextEditor,
            Func <Content> resolveContent)
        {
            using (DisposableTimer.Start(timer =>
                                         LogHelper.TraceIfEnabled <MacroRenderer>("RenderMacro for {0} took {1}ms", () => macroAlias, () => timer)))
            {
                try
                {
                    // get the macro's model
                    var macroModel = GetMacroModel(macroAlias);

                    if (isForRichTextEditor && !macroModel.Item1.RenderContentInEditor)
                    {
                        return(NoRichTextRenderMode(macroAlias));
                    }
                    else
                    {
                        return(GetMacroResult(macroAlias, () => macroModel.Item1, resolveContent, macroParams, currentControllerContext));
                    }
                }
                catch (ApplicationException ex)
                {
                    //if there's an exception, display a friendly message and log the error
                    var txt   = "Macro.RenderingFailed.Message".Localize(this, new { Error = ex.Message, MacroName = macroAlias });
                    var title = "Macro.RenderingFailed.Title".Localize();
                    LogHelper.Error <MacroRenderer>(txt, ex);
                    return(MacroError(txt, title));
                }
            }
        }
Пример #11
0
 public BootManager(HttpApplication app)
 {
     _timer = DisposableTimer.Start(timer => LogHelper.TraceIfEnabled <BootManager>("Application start took {0}ms", () => timer));
     _app   = app;
     LogHelper.TraceIfEnabled <BootManager>("Created");
     _rebelWireup = new RebelContainerBuilder <HttpApplication>(_app);
 }
Пример #12
0
 public static DisposableTimer Start(string sessionId, string startMessage, string endMessage, params IDataParameter[] parameters)
 {
     if (Enabled)
     {
         CustomQueryReporting.ReportQuery(sessionId, ProfilerLoggingPrefix + startMessage, parameters, 0, 0, 0);
         return(DisposableTimer.Start(x => CustomQueryReporting.ReportQuery(sessionId, ProfilerLoggingPrefix + endMessage, parameters, (int)x, (int)x, 0)));
     }
     return(DisposableTimer.Start(
                x =>
     {
     }));
 }
Пример #13
0
        /// <summary>
        /// Renders/executes the provided macro ActionResult.
        /// </summary>
        /// <remarks>Macro rendering time is traced.</remarks>
        private static string GetMacroStringOutput(string macroAlias, ActionResult ar, ControllerContext currentControllerContext)
        {
            using (DisposableTimer.Start(timer =>
                                         LogHelper.TraceIfEnabled <MacroRenderer>("GetMacroStringOutput for {0} took {1}ms", () => macroAlias, () => timer)))
            {
                if (ar is ViewResultBase)
                {
                    var viewResult = (ViewResultBase)ar;

                    return(currentControllerContext.RenderViewResultAsString(viewResult));
                }
                if (ar is ContentResult)
                {
                    var contentResult = (ContentResult)ar;
                    return(contentResult.Content);
                }
                throw new NotSupportedException("Its not possible to retreive the output of a macro that doesn't return a ViewResultBase");
            }
        }
Пример #14
0
        public virtual void RegisterDashboardMatchRules(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_dashboardMatchRulesRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterDashboardMatchRules start took {0}ms", () => timer);
                _dashboardMatchRulesRegistered = true;
            }))
            {
                //now register each type in the container and also add it to our collection);
                foreach (var t in FindTypesInRequiredAssemblies <DashboardMatchRule>(typeFinder))
                {
                    RegisterComponent <DashboardMatchRule, DashboardRuleMetadata>(t, builder, null);
                }
            }
        }
Пример #15
0
        /// <summary>
        /// Registers all RebelParameterEditors
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="typeFinder"></param>
        public virtual void RegisterParameterEditors(IContainerBuilder builder, TypeFinder typeFinder)
        {
            if (_paramEditorsRegistered)
            {
                return;
            }

            using (DisposableTimer.Start(timer =>
            {
                LogHelper.TraceIfEnabled <RebelComponentRegistrar>("RegisterParameterEditors start took {0}ms", () => timer);
                _paramEditorsRegistered = true;
            }))
            {
                foreach (var t in FindTypesInRequiredAssemblies <AbstractParameterEditor>(typeFinder))
                {
                    RegisterComponent <AbstractParameterEditor, ParameterEditorAttribute, ParameterEditorMetadata>(t, builder, true,
                                                                                                                   (pluginDef, attribute, registrar) =>
                                                                                                                   registrar
                                                                                                                   .WithMetadata <ParameterEditorMetadata, string>(am => am.Name, attribute.Name)
                                                                                                                   .WithMetadata <ParameterEditorMetadata, string>(am => am.Alias, attribute.Alias)
                                                                                                                   .WithMetadata <ParameterEditorMetadata, Guid>(am => am.PropertyEditorId, attribute.PropertyEditorId));
                }
            }
        }
Пример #16
0
 public IDisposable Step(string name)
 {
     LogHelper.Debug(typeof(LogProfiler), "Starting - " + name);
     return(DisposableTimer.Start(l => LogHelper.Info(typeof(LogProfiler), () => name + " (took " + l + "ms)")));
 }
Пример #17
0
        /// <summary>
        /// Finds a TypedEntity based on the Uri
        /// </summary>
        /// <param name="fullUrlIncludingDomain"></param>
        /// <param name="revisionStatusType"></param>
        /// <returns></returns>
        public EntityRouteResult FindEntityByUrl(Uri fullUrlIncludingDomain, RevisionStatusType revisionStatusType = null)
        {
            Mandate.ParameterNotNull(fullUrlIncludingDomain.Scheme, "Scheme");

            var statusTypeCacheKey = (revisionStatusType != null) ? revisionStatusType.Alias : string.Empty;

            //cache key is full uri except query string and revision status
            var cacheKey = EntityMappedKey + "-" + fullUrlIncludingDomain.GetLeftPart(UriPartial.Path) + "-" + statusTypeCacheKey;

            //TODO: We need to change how the NiceUrls are cached because if we store them in one entry as a dictionary in cache, then
            // we can do a reverse lookup to see if we've already generated the URL for the entity which may match the fullUrlIncludingDomain,
            // if so, then all we have to do is return the entity with the cached ID.

            return(ApplicationContext.FrameworkContext.ApplicationCache
                   .GetOrCreate(cacheKey, () =>
            {
                using (DisposableTimer.Start(timer =>
                                             LogHelper.TraceIfEnabled <DefaultRoutingEngine>("FindEntityByUrl (not from cache) for URL {0} took {1}ms", () => fullUrlIncludingDomain, () => timer)))
                {
                    ReadonlyGroupUnitFactory <IContentStore> persistenceManager;

                    using (DisposableTimer.TraceDuration <DefaultRoutingEngine>("FindEntityByUrl: Getting a reader", "FindEntityByUrl: Got a reader"))
                        persistenceManager = ApplicationContext.Hive.GetReader <IContentStore>(fullUrlIncludingDomain);

                    if (persistenceManager != null)
                    {
                        IReadonlyGroupUnit <IContentStore> readonlyGroupUnit;
                        using (DisposableTimer.TraceDuration <DefaultRoutingEngine>("FindEntityByUrl: Opening a reader", "FindEntityByUrl: Opened a reader"))
                            readonlyGroupUnit = persistenceManager.CreateReadonly();

                        using (var uow = readonlyGroupUnit)
                        {
                            //first, lets check if it's an ID URL
                            var trimmedAppPath = _httpContext.Request.ApplicationPath.TrimEnd('/');
                            var appPathLength = trimmedAppPath.Length;

                            // gate-check for the incoming url because some code (e.g. the alt-template checker) could be unaware of vdirs etc.
                            var absolutePath = fullUrlIncludingDomain.AbsolutePath;
                            var path = (absolutePath.Length < appPathLength) ? absolutePath : absolutePath.Substring(appPathLength, absolutePath.Length - appPathLength);

                            var urlId = HiveId.TryParse(path.TrimStart('/'));
                            if (urlId.Success && urlId.Result.ProviderGroupRoot != null)
                            {
                                LogHelper.TraceIfEnabled <DefaultRoutingEngine>("In FindEntityByUrl: Resolving entity by Id URL (Id: {0} ", () => urlId.Result.ToFriendlyString());
                                try
                                {
                                    //var entityById = uow.Repositories.Revisions.GetLatestRevision<TypedEntity>(urlId.Result, revisionStatusType);
                                    var entityById = uow.Repositories.OfRevisionType(revisionStatusType).InIds(urlId.Result.AsEnumerableOfOne()).FirstOrDefault();
                                    if (entityById == null)
                                    {
                                        LogHelper.Warn <DefaultRoutingEngine>("In FindEntityByUrl: Resolving entity by Id URL failed (Id: {0} ", urlId.Result.ToFriendlyString());
                                        return null;
                                    }
                                    return new HttpRuntimeCacheParameters <EntityRouteResult>(new EntityRouteResult(entityById, EntityRouteStatus.SuccessById));
                                }
                                catch (ArgumentException)
                                {
                                    //this occurs if the Id parsed but 'not really'
                                    return null;
                                }
                            }

                            TypedEntity lastItemFound;
                            //is the current requesting hostname/port in our list ?
                            if (DomainList.ContainsHostname(fullUrlIncludingDomain.Authority))
                            {
                                //domain found so get the first item assigned to this domain
                                LogHelper.TraceIfEnabled <DefaultRoutingEngine>("In FindEntityByUrl: Resolving entity by Domain URL {0}", () => fullUrlIncludingDomain.Authority);
                                var hostnameEntry = DomainList[fullUrlIncludingDomain.Authority];
                                //lastRevisionFound = uow.Repositories.Revisions.GetLatestRevision<TypedEntity>(hostnameEntry.ContentId, revisionStatusType);
                                lastItemFound = uow.Repositories.OfRevisionType(revisionStatusType).InIds(hostnameEntry.ContentId.AsEnumerableOfOne()).FirstOrDefault();
                                Mandate.That(lastItemFound != null, x => new InvalidOperationException("Could not find an entity with a revision status of '" + revisionStatusType.Alias + "', having a hostname '" + fullUrlIncludingDomain.Authority + "' and id: " + hostnameEntry.ContentId));
                            }
                            else
                            {
                                //no domain found for the current request, so we need to find the first routable node that doesn't require a domain
                                LogHelper.TraceIfEnabled <DefaultRoutingEngine>("In FindEntityByUrl: Resolving entity by Non-Domain URL");
                                //var root = uow.Repositories.Revisions.GetLatestRevision<TypedEntity>(FixedHiveIds.ContentVirtualRoot, revisionStatusType);
                                //Mandate.That(root != null, x => new InvalidOperationException("Could not find the content root"));
                                var domainListIds = DomainList.Select(d => d.ContentId).ToArray();

                                var firstLevelRelations =
                                    uow.Repositories.GetChildRelations(FixedHiveIds.ContentVirtualRoot, FixedRelationTypes.DefaultRelationType).OrderBy(
                                        x => x.Ordinal).ToArray();

                                //try to find a first level node that doesn't exist in our domain list
                                var firstNonHostnameEntity = firstLevelRelations.FirstOrDefault(x => !domainListIds.Contains(x.DestinationId));

                                // Issue #U5-112
                                // If we have found no entities that are NOT assigned to a domain, given that we have already tried to find
                                // content matching the current request's domain, we cannot route any content, therefore return null

                                // Also return null if there is no content
                                if (firstNonHostnameEntity == null || !firstLevelRelations.Any())
                                {
                                    return null;
                                }

                                var idToUse = firstNonHostnameEntity.DestinationId;
                                using (DisposableTimer.TraceDuration <DefaultRoutingEngine>("FindEntityByUrl: Querying for " + idToUse, "FindEntityByUrl: Query"))
                                    lastItemFound = uow.Repositories.OfRevisionType(revisionStatusType).InIds(idToUse.AsEnumerableOfOne()).FirstOrDefault();

                                ////if there is no first level node anywhere, then there is no content. Show a friendly message
                                //if (firstNonHostnameEntity == null && !firstLevelRelations.Any())
                                //    return null;

                                ////if we have a first level node not assigned to a domain, use the first, otherwise if all nodes are assigned to domains, then just use the first
                                //var idToUse = firstNonHostnameEntity == null ? firstLevelRelations.First().DestinationId : firstNonHostnameEntity.DestinationId;
                                //lastItemFound = uow.Repositories.OfRevisionType(revisionStatusType).InIds(idToUse.AsEnumerableOfOne()).FirstOrDefault();
                            }


                            // Now we will have the path from the current application root like:
                            //      /this/is/a/path/to/a/document
                            // Now we need to walk down the tree
                            if (lastItemFound != null && !string.IsNullOrWhiteSpace(path) && path != "/")
                            {
                                using (DisposableTimer.TraceDuration <DefaultRoutingEngine>("FindEntityByUrl: Calling GetEntityByPath for " + lastItemFound.Id + " " + path, "FindEntityByUrl: GetEntityByPath"))
                                    lastItemFound = uow
                                                    .Repositories
                                                    .GetEntityByPath <TypedEntity>(lastItemFound.Id,
                                                                                   path,
                                                                                   revisionStatusType,
                                                                                   true);
                            }

                            if (lastItemFound == null)
                            {
                                return new HttpRuntimeCacheParameters <EntityRouteResult>(
                                    new EntityRouteResult(null, EntityRouteStatus.FailedNotFoundByName));
                            }

                            return new HttpRuntimeCacheParameters <EntityRouteResult>(
                                new EntityRouteResult(lastItemFound, EntityRouteStatus.SuccessWithoutHostname));
                        }
                    }

                    return null;
                }
            }));
        }
        /// <summary>
        /// Finds a TypedEntity based on the Uri
        /// </summary>
        /// <param name="fullUrlIncludingDomain"></param>
        /// <param name="revisionStatusType"></param>
        /// <returns></returns>
        public EntityRouteResult FindEntityByUrl(Uri fullUrlIncludingDomain, RevisionStatusType revisionStatusType)
        {
            Mandate.ParameterNotNull(fullUrlIncludingDomain.Scheme, "Scheme");

            //cache key is full uri except query string and revision status
            var cacheKey = EntityMappedKey + "-" + fullUrlIncludingDomain.GetLeftPart(UriPartial.Path) + "-" + revisionStatusType;

            //TODO: We need to change how the NiceUrls are cached because if we store them in one entry as a dictionary in cache, then
            // we can do a reverse lookup to see if we've already generated the URL for the entity which may match the fullUrlIncludingDomain,
            // if so, then all we have to do is return the entity with the cached ID.

            return(ApplicationContext.FrameworkContext.ApplicationCache
                   .GetOrCreate(cacheKey, () =>
            {
                using (DisposableTimer.Start(timer =>
                                             LogHelper.TraceIfEnabled <DefaultRoutingEngine>("FindEntityByUrl for URL {0} took {1}ms", () => fullUrlIncludingDomain, () => timer)))
                {
                    var persistenceManager = ApplicationContext.Hive.GetReader <IContentStore>(fullUrlIncludingDomain);
                    if (persistenceManager != null)
                    {
                        using (var uow = persistenceManager.CreateReadonly())
                        {
                            //first, lets check if it's an ID URL
                            var path = fullUrlIncludingDomain.AbsolutePath.Substring(
                                _httpContext.Request.ApplicationPath.TrimEnd('/').Length,
                                fullUrlIncludingDomain.AbsolutePath.Length - _httpContext.Request.ApplicationPath.TrimEnd('/').Length);
                            var urlId = HiveId.TryParse(path.TrimStart('/'));
                            if (urlId.Success && urlId.Result.ProviderGroupRoot != null)
                            {
                                LogHelper.TraceIfEnabled <DefaultRoutingEngine>("Resolving entity by Id URL (Id: {0} ", () => urlId.Result.ToFriendlyString());
                                try
                                {
                                    var entityById = uow.Repositories.Revisions.GetLatestRevision <TypedEntity>(urlId.Result, revisionStatusType);
                                    if (entityById == null)
                                    {
                                        LogHelper.Warn <DefaultRoutingEngine>("Resolving entity by Id URL failed (Id: {0} ", urlId.Result.ToFriendlyString());
                                        return null;
                                    }
                                    return new HttpRuntimeCacheParameters <EntityRouteResult>(
                                        new EntityRouteResult(entityById.Item, EntityRouteStatus.SuccessById));
                                }
                                catch (ArgumentException)
                                {
                                    //this occurs if the Id parsed but 'not really'
                                    return null;
                                }
                            }

                            Revision <TypedEntity> lastRevisionFound;
                            TypedEntity lastItemFound;
                            //is the current requesting hostname/port in our list ?
                            if (DomainList.ContainsHostname(fullUrlIncludingDomain.Authority))
                            {
                                //domain found so get the first item assigned to this domain
                                LogHelper.TraceIfEnabled <DefaultRoutingEngine>("Resolving entity by Domain URL");
                                var hostnameEntry = DomainList[fullUrlIncludingDomain.Authority];
                                lastRevisionFound = uow.Repositories.Revisions.GetLatestRevision <TypedEntity>(hostnameEntry.ContentId, revisionStatusType);
                                Mandate.That(lastRevisionFound != null, x => new InvalidOperationException("Could not find an entity with a revision status of '" + revisionStatusType.Alias + "', having a hostname '" + fullUrlIncludingDomain.Authority + "' and id: " + hostnameEntry.ContentId));
                                lastItemFound = lastRevisionFound.Item;
                            }
                            else
                            {
                                //no domain found for the current request, so we need to find the first routable node that doesn't require a domain
                                LogHelper.TraceIfEnabled <DefaultRoutingEngine>("Resolving entity by Non-Domain URL");
                                //var root = uow.Repositories.Revisions.GetLatestRevision<TypedEntity>(FixedHiveIds.ContentVirtualRoot, revisionStatusType);
                                //Mandate.That(root != null, x => new InvalidOperationException("Could not find the content root"));
                                var domainListIds = DomainList.Select(d => d.ContentId);

                                var firstLevelRelations =
                                    uow.Repositories.GetChildRelations(FixedHiveIds.ContentVirtualRoot, FixedRelationTypes.DefaultRelationType).OrderBy(
                                        x => x.Ordinal).ToArray();

                                //try to find a first level node that doesn't exist in our domain list
                                var firstNonHostnameEntity = firstLevelRelations.FirstOrDefault(x => !domainListIds.Contains(x.DestinationId));

                                //if there is no first level node anywhere, then there is no content. Show a friendly message
                                if (firstNonHostnameEntity == null && firstLevelRelations.Count() == 0)
                                {
                                    return null;
                                }

                                //if we have a first level node not assigned to a domain, use the first, otherwise if all nodes are assigned to domains, then just use the first
                                lastRevisionFound = uow.Repositories.Revisions.GetLatestRevision <TypedEntity>(
                                    firstNonHostnameEntity == null
                                                ? firstLevelRelations.First().DestinationId
                                                : firstNonHostnameEntity.DestinationId, revisionStatusType);

                                lastItemFound = lastRevisionFound != null ? lastRevisionFound.Item : null;
                            }


                            // Now we will have the path from the current application root like:
                            //      /this/is/a/path/to/a/document
                            // Now we need to walk down the tree
                            if (lastItemFound != null && !string.IsNullOrWhiteSpace(path) && path != "/")
                            {
                                lastItemFound = uow.Repositories.GetEntityByPath <TypedEntity>(lastItemFound.Id, path, revisionStatusType, true);
                            }

                            if (lastItemFound == null)
                            {
                                return new HttpRuntimeCacheParameters <EntityRouteResult>(
                                    new EntityRouteResult(null, EntityRouteStatus.FailedNotFoundByName));
                            }

                            return new HttpRuntimeCacheParameters <EntityRouteResult>(
                                new EntityRouteResult(lastItemFound, EntityRouteStatus.SuccessWithoutHostname));
                        }
                    }

                    return null;
                }
            }));
        }