context: using System;
  using System.Collections.Generic;
  using System.Configuration;
  using System.Data;
  using System.IO;
  using System.Reflection;
  using System.Text;
  using System.Web;
  using N2.Configuration;
  using N2.Definitions;
  using N2.Definitions.Static;
  using N2.Details;
  using N2.Edit.Trash;
  using N2.Edit.Versioning;
  using N2.Engine;
  using N2.Installation;
  using N2.Persistence;
  using N2.Persistence.NH;
  using N2.Persistence.Serialization;
  using N2.Plugin;
  using N2.Web;
  using NHibernate;
  using NHibernate.Driver;
  using NHibernate.SqlTypes;
  using NHibernate.Tool.hbm2ddl;
  using Environment = NHibernate.Cfg.Environment;
  using System.Linq;
  
  namespace N2.Edit.Installation
  {
      public abstract class InstallationManager
      {
          public const string InstallationAppPath = "Installation.AppPath";
          public const string installationHost = "Installation.Host";
          public const string installationAssemblyVersion = "Installation.AssemblyVersion";
          public const string installationFileVersion = "Installation.FileVersion";
          public const string installationFeatures = "Installation.Features";
          public const string installationImageSizes = "Installation.ImageSizes";
  
          public abstract string CheckConnection(out string stackTrace);
          public abstract string CheckDatabase();
          public abstract string CheckRootItem();
          public abstract string CheckStartPage();
          public abstract DatabaseStatus GetStatus();
          public abstract void Upgrade();
          public abstract void Install();
          public abstract IEnumerable<ContentItem> ExecuteQuery(string query);
          public abstract string ExportSchema();
          public abstract void ExportSchema(TextWriter output);
          public abstract string ExportUpgradeSchema();
          ConnectionMonitor connectionContext;
          private Importer importer;
          private IWebContext webContext;
          private IPersister persister;
          private ContentActivator activator;
  
          public InstallationManager(ConnectionMonitor connectionContext, Importer importer, IWebContext webContext, IPersister persister, ContentActivator activator)
          {
              this.connectionContext = connectionContext;
              this.importer = importer;
              this.webContext = webContext;
              this.persister = persister;
              this.activator = activator;
          }
  
          public virtual void UpdateStatus(SystemStatusLevel currentLevel)
          {
              connectionContext.SetConnected(currentLevel);
          }
  
          public virtual ContentItem InsertExportFile(Stream stream, string filename)
          {
              IImportRecord record = importer.Read(stream, filename);
              record.RootItem["Installation.AppPath"] = N2.Web.Url.ToAbsolute("~/");
              try
              {
                  record.RootItem["Installation.Host"] = webContext.Url.HostUrl.ToString();
              }
              catch (HttpException)
              {
                  // silently ignore "Request is not available in this context" when calling this from init
              }
  
              importer.Import(record, null, ImportOption.All);
  
              return record.RootItem;
          }
  
          public virtual ContentItem InsertRootNode(Type type, string name, string title)
          {
              ContentItem item = activator.CreateInstance(type, null);
              item.Name = name;
              item.Title = title;
              item[InstallationAppPath] = N2.Web.Url.ToAbsolute("~/");
              item[installationHost] = webContext.Url.HostUrl.ToString();
              persister.Save(item);
              return item;
          }
  
          public virtual ContentItem InsertStartPage(Type type, ContentItem root, string name, string title)
          {
              ContentItem item = activator.CreateInstance(type, root);
              item.Name = name;
              item.Title = title;
              persister.Save(item);
              return item;
          }
  
          /// <summary>Gets definitions suitable as start pages.</summary>
          /// <returns>An enumeration of item definitions.</returns>
          public virtual IEnumerable<ItemDefinition> GetStartDefinitions(IEnumerable<ItemDefinition> allDefinitions)
          {
              ICollection<ItemDefinition> preferred = new List<ItemDefinition>();
              ICollection<ItemDefinition> fallback = new List<ItemDefinition>();
  
              foreach (ItemDefinition d in allDefinitions)
              {
                  InstallerHint hint = d.Installer;
  
                  if (Is(hint, InstallerHint.PreferredStartPage))
                      preferred.Add(d);
                  if (!Is(hint, InstallerHint.NeverStartPage))
                      fallback.Add(d);
              }
  
              if (preferred.Count == 0)
                  preferred = fallback;
  
              return preferred;
          }
  
          /// <summary>Gets definitions suitable as root nodes.</summary>
          /// <returns>An enumeration of item definitions.</returns>
          public virtual IEnumerable<ItemDefinition> GetRootDefinitions(IEnumerable<ItemDefinition> allDefinitions)
          {
              ICollection<ItemDefinition> preferred = new List<ItemDefinition>();
              ICollection<ItemDefinition> fallback = new List<ItemDefinition>();
  
              foreach (ItemDefinition d in allDefinitions)
              {
                  InstallerHint hint = d.Installer;
  
                  if (Is(hint, InstallerHint.PreferredRootPage))
                      preferred.Add(d);
                  if (!Is(hint, InstallerHint.NeverRootPage))
                      fallback.Add(d);
              }
  
              if (preferred.Count == 0)
                  preferred = fallback;
  
              return preferred;
          }
  
          /// <summary>Gets definitions suitable as start pages and root node.</summary>
          /// <returns>An enumeration of item definitions.</returns>
          public virtual IEnumerable<ItemDefinition> GetRootAndStartDefinitions(IEnumerable<ItemDefinition> allDefinitions)
          {
              ICollection<ItemDefinition> preferred = new List<ItemDefinition>();
              ICollection<ItemDefinition> fallback = new List<ItemDefinition>();
  
              foreach (ItemDefinition d in allDefinitions)
              {
                  InstallerHint hint = d.Installer;
  
                  if (Is(hint, InstallerHint.PreferredRootPage) || Is(hint, InstallerHint.PreferredStartPage))
                      preferred.Add(d);
                  if (!Is(hint, InstallerHint.NeverRootPage) && !Is(hint, InstallerHint.NeverStartPage))
                      fallback.Add(d);
              }
  
              if (preferred.Count == 0)
                  preferred = fallback;
  
              return preferred;
          }
  
          /// <summary>Checks installer hint bit flags.</summary>
          /// <param name="flags">The defined flags.</param>
          /// <param name="expected">The expected flags.</param>
          /// <returns>True if the defined contains the expected.</returns>
          public static bool Is(InstallerHint flags, InstallerHint expected)
          {
              return (flags & expected) == expected;
          }
      }
  
      /// <summary>
      /// Wraps functionality to request database status and generate n2's 
      /// database schema on multiple database flavours.
      /// </summary>
      [Service]
      [Service(typeof(InstallationManager))]
      public class NHInstallationManager : InstallationManager
      {
          private readonly Engine.Logger<NHInstallationManager> logger;
  
          IConfigurationBuilder configurationBuilder;
          ContentActivator activator;
          Importer importer;
          IPersister persister;
          ISessionProvider sessionProvider;
          IHost host;
          IWebContext webContext;
          DefinitionMap map;
          ConnectionMonitor connectionContext;
          DatabaseSection config;
          bool isDatabaseFileSystemEnbled = false;
          NHibernate.Cfg.Configuration cfg;
  
          public NHInstallationManager(IHost host, DefinitionMap map, ContentActivator activator, Importer importer, IPersister persister, ISessionProvider sessionProvider, IConfigurationBuilder configurationBuilder, IWebContext webContext, ConnectionMonitor connectionContext, DatabaseSection config)
              : base(connectionContext, importer, webContext, persister, activator)
          {
              this.host = host;
              this.map = map;
              this.activator = activator;
              this.importer = importer;
              this.persister = persister;
              this.sessionProvider = sessionProvider;
              this.configurationBuilder = configurationBuilder;
              this.webContext = webContext;
              this.connectionContext = connectionContext;
              this.config = config;
              this.isDatabaseFileSystemEnbled = config.Files.StorageLocation == FileStoreLocation.Database;
          }
  
          protected NHibernate.Cfg.Configuration Cfg
          {
              get { return cfg ?? (cfg = configurationBuilder.BuildConfiguration()); }
          }
  
          public static string GetResourceString(string resourceKey)
          {
              Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceKey);
              StreamReader sr = new StreamReader(s);
              return sr.ReadToEnd();
          }
  
          const bool ConsoleOutput = false;
          const bool DatabaseExport = true;
          const bool NoDatabaseExport = false;
  
          /// <summary>Executes sql create database scripts.</summary>
          public override void Install()
          {
              ClearNHCache();
  
              SchemaExport exporter = new SchemaExport(Cfg);
              exporter.Create(ConsoleOutput, DatabaseExport);
          }
  
          private void ClearNHCache()
          {
              var sf = configurationBuilder.BuildSessionFactory();
              sf.EvictQueries();
              foreach (var collectionMetadata in sf.GetAllCollectionMetadata())
                  sf.EvictCollection(collectionMetadata.Key);
              foreach (var classMetadata in sf.GetAllClassMetadata())
                  sf.EvictEntity(classMetadata.Key);
          }
  
          public override void ExportSchema(TextWriter output)
          {
              SchemaExport exporter = new SchemaExport(Cfg);
              exporter.Execute(ConsoleOutput, NoDatabaseExport, false, null, output);
          }
  
          public override string ExportSchema()
          {
              StringBuilder sql = new StringBuilder();
              using (StringWriter sw = new StringWriter(sql))
              {
                  ExportSchema(sw);
              }
              return sql.ToString();
          }
  
  
  
          public override void Upgrade()
          {
              SchemaUpdate schemaUpdater = new SchemaUpdate(Cfg);
              schemaUpdater.Execute(true, true);
  
              ClearNHCache();
  
              var status = GetStatus();
              if (status.RootItem != null)
              {
                  status.RootItem[InstallationManager.installationAssemblyVersion] = typeof(N2.Context).Assembly.GetName().Version.ToString();
                  status.RootItem[InstallationManager.installationFileVersion] = typeof(N2.Context).Assembly.GetFileVersion();
                  persister.Save(status.RootItem);
              }
          }
  
          public override string ExportUpgradeSchema()
          {
  
gt:             SchemaUpdate schemaUpdater = new SchemaUpdate(Cfg);