diff --git a/src/Umbraco.Examine/IIndexCreator.cs b/src/Umbraco.Examine/IIndexCreator.cs new file mode 100644 index 0000000000..3b8f683990 --- /dev/null +++ b/src/Umbraco.Examine/IIndexCreator.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Examine; + +namespace Umbraco.Examine +{ + /// + /// Creates 's + /// + public interface IIndexCreator + { + IEnumerable Create(); + } +} diff --git a/src/Umbraco.Examine/IIndexDiagnostics.cs b/src/Umbraco.Examine/IIndexDiagnostics.cs index 04ca4a6ab9..29d530c2d0 100644 --- a/src/Umbraco.Examine/IIndexDiagnostics.cs +++ b/src/Umbraco.Examine/IIndexDiagnostics.cs @@ -1,12 +1,9 @@ using System; using System.Collections.Generic; -using Examine; using Umbraco.Core; namespace Umbraco.Examine { - - /// /// Exposes diagnostic information about an index /// diff --git a/src/Umbraco.Examine/LuceneIndexCreator.cs b/src/Umbraco.Examine/LuceneIndexCreator.cs new file mode 100644 index 0000000000..572de1e8a8 --- /dev/null +++ b/src/Umbraco.Examine/LuceneIndexCreator.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.IO; +using Examine; +using Examine.LuceneEngine.Directories; +using Lucene.Net.Store; +using Umbraco.Core.IO; + +namespace Umbraco.Examine +{ + /// + /// + /// Abstract class for creating Lucene based Indexes + /// + public abstract class LuceneIndexCreator : IIndexCreator + { + public abstract IEnumerable Create(); + + /// + /// Creates a file system based Lucene with the correct locking guidelines for Umbraco + /// + /// + /// + public virtual Lucene.Net.Store.Directory CreateFileSystemLuceneDirectory(string name) + { + //TODO: We should have a single AppSetting to be able to specify a default DirectoryFactory so we can have a single + //setting to configure all indexes that use this to easily swap the directory to Sync/%temp%/blog, etc... + + var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name)); + if (!dirInfo.Exists) + System.IO.Directory.CreateDirectory(dirInfo.FullName); + + var luceneDir = new SimpleFSDirectory(dirInfo); + + //we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain + //terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock + //which simply checks the existence of the lock file + // The full syntax of this is: new NoPrefixSimpleFsLockFactory(dirInfo) + // however, we are setting the DefaultLockFactory in startup so we'll use that instead since it can be managed globally. + luceneDir.SetLockFactory(DirectoryFactory.DefaultLockFactory(dirInfo)); + return luceneDir; + } + } +} diff --git a/src/Umbraco.Examine/Umbraco.Examine.csproj b/src/Umbraco.Examine/Umbraco.Examine.csproj index 0aedf6e754..66b1f09068 100644 --- a/src/Umbraco.Examine/Umbraco.Examine.csproj +++ b/src/Umbraco.Examine/Umbraco.Examine.csproj @@ -66,6 +66,7 @@ + @@ -88,6 +89,7 @@ + Properties\SolutionInfo.cs diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config index 7b5a9e5e2a..bd75e97c38 100644 --- a/src/Umbraco.Web.UI/config/trees.Release.config +++ b/src/Umbraco.Web.UI/config/trees.Release.config @@ -30,9 +30,5 @@ - - - - - + diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 2b99f8751f..7f7aeca8a7 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -30,9 +30,5 @@ - - - - - + diff --git a/src/Umbraco.Web/Search/IUmbracoIndexesCreator.cs b/src/Umbraco.Web/Search/IUmbracoIndexesCreator.cs index 58014597d2..d654e4effd 100644 --- a/src/Umbraco.Web/Search/IUmbracoIndexesCreator.cs +++ b/src/Umbraco.Web/Search/IUmbracoIndexesCreator.cs @@ -1,13 +1,14 @@ using System.Collections.Generic; using Examine; +using Umbraco.Examine; namespace Umbraco.Web.Search { + /// /// /// Used to create the Umbraco indexes /// - public interface IUmbracoIndexesCreator + public interface IUmbracoIndexesCreator : IIndexCreator { - IEnumerable Create(); } } diff --git a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs index f8b2c6ef8b..3723dedc48 100644 --- a/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs +++ b/src/Umbraco.Web/Search/UmbracoIndexesCreator.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Search /// /// Creates the indexes used by Umbraco /// - public class UmbracoIndexesCreator : IUmbracoIndexesCreator + public class UmbracoIndexesCreator : LuceneIndexCreator, IUmbracoIndexesCreator { //TODO: we should inject the different IValueSetValidator so devs can just register them instead of overriding this class? @@ -45,7 +45,7 @@ namespace Umbraco.Web.Search /// Creates the Umbraco indexes /// /// - public IEnumerable Create() + public override IEnumerable Create() { return new [] { @@ -61,7 +61,7 @@ namespace Umbraco.Web.Search Constants.UmbracoIndexes.InternalIndexName, //fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes UmbracoExamineIndex.UmbracoIndexFieldDefinitions, - GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath), + CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath), new CultureInvariantWhitespaceAnalyzer(), ProfilingLogger, LanguageService, @@ -75,7 +75,7 @@ namespace Umbraco.Web.Search Constants.UmbracoIndexes.ExternalIndexName, //fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes UmbracoExamineIndex.UmbracoIndexFieldDefinitions, - GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath), + CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath), new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30), ProfilingLogger, LanguageService, @@ -89,27 +89,13 @@ namespace Umbraco.Web.Search Constants.UmbracoIndexes.MembersIndexName, //fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes UmbracoExamineIndex.UmbracoIndexFieldDefinitions, - GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath), + CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath), new CultureInvariantWhitespaceAnalyzer(), ProfilingLogger, GetMemberValueSetValidator()); return index; } - - public virtual Lucene.Net.Store.Directory GetFileSystemLuceneDirectory(string name) - { - var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name)); - if (!dirInfo.Exists) - System.IO.Directory.CreateDirectory(dirInfo.FullName); - - var luceneDir = new SimpleFSDirectory(dirInfo); - //we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain - //terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock - //which simply checks the existence of the lock file - luceneDir.SetLockFactory(new NoPrefixSimpleFsLockFactory(dirInfo)); - return luceneDir; - } - + public virtual IContentValueSetValidator GetContentValueSetValidator() { return new ContentValueSetValidator(false, true, PublicAccessService); diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index c1192b6909..d824f32f4b 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -78,10 +78,20 @@ namespace Umbraco.Web.Trees } } - var multiTree = TreeRootNode.CreateMultiTreeRoot(collection); - multiTree.Name = Services.TextService.Localize("sections/" + application); + if(collection.Count > 0) + { + var multiTree = TreeRootNode.CreateMultiTreeRoot(collection); + multiTree.Name = Services.TextService.Localize("sections/" + application); - return multiTree; + return multiTree; + } + + //Otherwise its a application/section with no trees (aka a full screen app) + //For example we do not have a Forms tree definied in C# & can not attribute with [Tree(isSingleNodeTree:true0] + var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); + var section = Services.TextService.Localize("sections/" + application); + + return TreeRootNode.CreateSingleTreeRoot(rootId, null, null, section, TreeNodeCollection.Empty, true); } var rootNodeGroups = new List();