context: 
  using System;
  using System.IO;
  using System.Resources;
  using System.Web.Configuration;
  using ScrewTurn.Wiki.PluginFramework;
  
  namespace ScrewTurn.Wiki {
  
  	/// <summary>
  	/// Provides tools for starting and shutting down the wiki engine.
  	/// </summary>
  	public static class StartupTools {
  
  		/// <summary>
  		/// Gets the Settings Storage Provider configuration string from web.config.
  		/// </summary>
  		/// <returns>The configuration string.</returns>
  		public static string GetSettingsStorageProviderConfiguration() {
  			string config = WebConfigurationManager.AppSettings["SettingsStorageProviderConfig"];
  			if(config != null) return config;
  			else return "";
  		}
  
  		/// <summary>
  		/// Updates the DLLs into the settings storage provider, if appropriate.
  		/// </summary>
  		/// <param name="provider">The provider.</param>
  		/// <param name="settingsProviderAsmName">The file name of the assembly that contains the current Settings Storage Provider.</param>
  		private static void UpdateDllsIntoSettingsProvider(ISettingsStorageProviderV30 provider, string settingsProviderAsmName) {
  			// Look into public\Plugins (hardcoded)
  			string fullPath = Path.Combine(Settings.PublicDirectory, "Plugins");
  
  			if(!Directory.Exists(fullPath)) return;
  
  			string[] dlls = Directory.GetFiles(fullPath, "*.dll");
  			string[] installedDlls = provider.ListPluginAssemblies();
  
  			foreach(string dll in dlls) {
  				bool found = false;
  				string filename = Path.GetFileName(dll);
  				foreach(string instDll in installedDlls) {
  					if(instDll.ToLowerInvariant() == filename.ToLowerInvariant()) {
  						found = true;
  						break;
  					}
  				}
  
  				if(!found && filename.ToLowerInvariant() == settingsProviderAsmName.ToLowerInvariant()) {
  					found = true;
  				}
  
  				if(found) {
  					// Update DLL
  					provider.StorePluginAssembly(filename, File.ReadAllBytes(dll));
  				}
  			}
  		}
  
  		/// <summary>
  		/// Performs all needed startup operations.
  		/// </summary>
  		public static void Startup() {
  			// Load Host
  			Host.Instance = new Host();
  
  			// Load config
  			ISettingsStorageProviderV30 ssp = ProviderLoader.LoadSettingsStorageProvider(WebConfigurationManager.AppSettings["SettingsStorageProvider"]);
  			ssp.Init(Host.Instance, GetSettingsStorageProviderConfiguration());
  			Collectors.SettingsProvider = ssp;
  
  			if(!(ssp is SettingsStorageProvider)) {
  				// Update DLLs from public\Plugins
  				UpdateDllsIntoSettingsProvider(ssp, ProviderLoader.SettingsStorageProviderAssemblyName);
  			}
  
  			if(ssp.IsFirstApplicationStart()) {
  				if(ssp.GetMetaDataItem(MetaDataItem.AccountActivationMessage, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.AccountActivationMessage, null, Defaults.AccountActivationMessageContent);
  				if(ssp.GetMetaDataItem(MetaDataItem.EditNotice, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.EditNotice, null, Defaults.EditNoticeContent);
  				if(ssp.GetMetaDataItem(MetaDataItem.Footer, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.Footer, null, Defaults.FooterContent);
  				if(ssp.GetMetaDataItem(MetaDataItem.Header, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.Header, null, Defaults.HeaderContent);
  				if(ssp.GetMetaDataItem(MetaDataItem.PasswordResetProcedureMessage, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.PasswordResetProcedureMessage, null, Defaults.PasswordResetProcedureMessageContent);
  				if(ssp.GetMetaDataItem(MetaDataItem.Sidebar, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.Sidebar, null, Defaults.SidebarContent);
  				if(ssp.GetMetaDataItem(MetaDataItem.PageChangeMessage, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.PageChangeMessage, null, Defaults.PageChangeMessage);
  				if(ssp.GetMetaDataItem(MetaDataItem.DiscussionChangeMessage, null) == "")
  					ssp.SetMetaDataItem(MetaDataItem.DiscussionChangeMessage, null, Defaults.DiscussionChangeMessage);
  				if(ssp.GetMetaDataItem(MetaDataItem.ApproveDraftMessage, null) == "") {
  					ssp.SetMetaDataItem(MetaDataItem.ApproveDraftMessage, null, Defaults.ApproveDraftMessage);
  				}
  			}
  
  			MimeTypes.Init();
  
  			// Load Providers
  			Collectors.FileNames = new System.Collections.Generic.Dictionary<string, string>(10);
  			Collectors.UsersProviderCollector = new ProviderCollector<IUsersStorageProviderV30>();
  			Collectors.PagesProviderCollector = new ProviderCollector<IPagesStorageProviderV30>();
  			Collectors.FilesProviderCollector = new ProviderCollector<IFilesStorageProviderV30>();
  			Collectors.FormatterProviderCollector = new ProviderCollector<IFormatterProviderV30>();
  			Collectors.CacheProviderCollector = new ProviderCollector<ICacheProviderV30>();
  			Collectors.DisabledUsersProviderCollector = new ProviderCollector<IUsersStorageProviderV30>();
  			Collectors.DisabledPagesProviderCollector = new ProviderCollector<IPagesStorageProviderV30>();
  			Collectors.DisabledFilesProviderCollector = new ProviderCollector<IFilesStorageProviderV30>();
  			Collectors.DisabledFormatterProviderCollector = new ProviderCollector<IFormatterProviderV30>();
  			Collectors.DisabledCacheProviderCollector = new ProviderCollector<ICacheProviderV30>();
  
  			// Load built-in providers
  
  			// Files storage providers have to be loaded BEFORE users storage providers in order to properly set permissions
  			FilesStorageProvider f = new FilesStorageProvider();
  			if(!ProviderLoader.IsDisabled(f.GetType().FullName)) {
  				f.Init(Host.Instance, "");
  				Collectors.FilesProviderCollector.AddProvider(f);
  				Log.LogEntry("Provider " + f.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
  			}
  			else {
  				Collectors.DisabledFilesProviderCollector.AddProvider(f);
  				Log.LogEntry("Provider " + f.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
  			}
  
  			UsersStorageProvider u = new UsersStorageProvider();
  			if(!ProviderLoader.IsDisabled(u.GetType().FullName)) {
  				u.Init(Host.Instance, "");
  				Collectors.UsersProviderCollector.AddProvider(u);
  				Log.LogEntry("Provider " + u.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
  			}
  			else {
  				Collectors.DisabledUsersProviderCollector.AddProvider(u);
  				Log.LogEntry("Provider " + u.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
  			}
  
  			// Load Users (pages storage providers might need access to users/groups data for upgrading from 2.0 to 3.0)
  			ProviderLoader.FullLoad(true, false, false, false, false);
  			//Users.Instance = new Users();
  			bool groupsCreated = VerifyAndCreateDefaultGroups();
  
  			PagesStorageProvider p = new PagesStorageProvider();
  			if(!ProviderLoader.IsDisabled(p.GetType().FullName)) {
  				p.Init(Host.Instance, "");
  				Collectors.PagesProviderCollector.AddProvider(p);
  				Log.LogEntry("Provider " + p.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
  			}
  			else {
  				Collectors.DisabledPagesProviderCollector.AddProvider(p);
  				Log.LogEntry("Provider " + p.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
  			}
  
  			CacheProvider c = new CacheProvider();
  			if(!ProviderLoader.IsDisabled(c.GetType().FullName)) {
  				c.Init(Host.Instance, "");
  				Collectors.CacheProviderCollector.AddProvider(c);
  				Log.LogEntry("Provider " + c.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
  			}
  			else {
  				Collectors.DisabledCacheProviderCollector.AddProvider(c);
  				Log.LogEntry("Provider " + c.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
  			}
  
  			// Load all other providers
  			ProviderLoader.FullLoad(false, true, true, true, true);
  
  			if(groupsCreated) {
  				// It is necessary to set default permissions for file management
  				UserGroup administratorsGroup = Users.FindUserGroup(Settings.AdministratorsGroup);
  				UserGroup anonymousGroup = Users.FindUserGroup(Settings.AnonymousGroup);
  				UserGroup usersGroup = Users.FindUserGroup(Settings.UsersGroup);
  
  				SetAdministratorsGroupDefaultPermissions(administratorsGroup);
  				SetUsersGroupDefaultPermissions(usersGroup);
  				SetAnonymousGroupDefaultPermissions(anonymousGroup);
  			}
  
  			// Init cache
  			//Cache.Instance = new Cache(Collectors.CacheProviderCollector.GetProvider(Settings.DefaultCacheProvider));
  			if(Collectors.CacheProviderCollector.GetProvider(Settings.DefaultCacheProvider) == null) {
  				Log.LogEntry("Default Cache Provider was not loaded, backing to integrated provider", EntryType.Error, Log.SystemUsername);
  				Settings.DefaultCacheProvider = typeof(CacheProvider).FullName;
  				Collectors.TryEnable(Settings.DefaultCacheProvider);
  			}
  
  			// Create the Main Page, if needed
  			if(Pages.FindPage(Settings.DefaultPage) == null) CreateMainPage();
  
  			Log.LogEntry("ScrewTurn Wiki is ready", EntryType.General, Log.SystemUsername);
  
  			System.Threading.ThreadPool.QueueUserWorkItem(ignored => {
  				if((DateTime.Now - Settings.LastPageIndexing).TotalDays > 7) {
  					Settings.LastPageIndexing = DateTime.Now;
  					System.Threading.Thread.Sleep(10000);
  					using(MemoryStream ms = new MemoryStream()) {
  						using(StreamWriter wr = new System.IO.StreamWriter(ms)) {
  							System.Web.HttpContext.Current = new System.Web.HttpContext(new System.Web.Hosting.SimpleWorkerRequest("", "", wr));
  							foreach(var provider in Collectors.PagesProviderCollector.AllProviders) {
  								if(!provider.ReadOnly) {
  									Log.LogEntry("Starting automatic rebuilding index for provider: " + provider.Information.Name, EntryType.General, Log.SystemUsername);
  									provider.RebuildIndex();
  									Log.LogEntry("Finished automatic rebuilding index for provider: " + provider.Information.Name, EntryType.General, Log.SystemUsername);
  								}
  							}
  						}
  					}
  				}
  			});
  		}
  
  		/// <summary>
  		/// Verifies the existence of the default user groups and creates them if necessary.
  		/// </summary>
  		/// <returns><c>true</c> if the groups were created, <c>false</c> otherwise.</returns>
  		private static bool VerifyAndCreateDefaultGroups() {
  			UserGroup administratorsGroup = Users.FindUserGroup(Settings.AdministratorsGroup);
  			UserGroup anonymousGroup = Users.FindUserGroup(Settings.AnonymousGroup);
  
gt: 			UserGroup usersGroup = Users.FindUserGroup(Settings.UsersGroup);