private void DisposeOldWebInterfaceServer()
        {
            const string LOG_TAG_PREFIX = "ApplicationServer::DisposeOldHttpServer::";

            try
            {
                using (var srv = this._webHandler)
                {
                    this._webHandler = null;
                }
            }
            catch (Exception ex)
            {
                this.Logger
                .Log(msg: ex.GetBaseException() ?? ex,
                     tag: LOG_TAG_PREFIX + "Dispose",
                     categories: LoggerFacadeCategories.Errors | LoggerFacadeCategories.Debug);
            }
        }
        private void StartServer()
        {
            const string LOG_TAG_PREFIX = "ApplicationServer::StartServer::";

            AggregateException ex = null;

            this.ReinitTrustedCompositionCatalog();

            // assemblies with services
            {
                var serviceDir = new DirectoryInfo(Path.Combine(this.WorkingDirectory, "services")).CreateDirectoryDeep();

                this.LoadAndAddTrustedAssemblies(serviceDir.GetFiles("*.dll"),
                                                 LOG_TAG_PREFIX);
            }

            // assemblies with functions
            {
                var funcDir = new DirectoryInfo(Path.Combine(this.WorkingDirectory, "funcs")).CreateDirectoryDeep();

                this.LoadAndAddTrustedAssemblies(funcDir.GetFiles("*.dll"),
                                                 LOG_TAG_PREFIX);
            }

            // web interface
            {
                IList <Assembly> webInterfaceAssemblies = new SynchronizedCollection <Assembly>();

                var webDir = new DirectoryInfo(Path.Combine(this.WorkingDirectory, "web")).CreateDirectoryDeep();
                this.LoadAndAddTrustedAssemblies(webDir.GetFiles("*.dll"),
                                                 LOG_TAG_PREFIX);

                try
                {
                    this.DisposeOldWebInterfaceServer();

                    //TODO read from configuration
                    var newWebInterfaceServer = ServiceLocator.Current.GetInstance <IHttpServer>();
                    {
                        // HTTPs ?
                        {
                            bool?useHttps;
                            this.StartupConfig
                            .TryGetValue <bool?>(category: CONFIG_CATEGORY_WEBINTERFACE,
                                                 name: CONFIG_VALUE_USE_HTTPS,
                                                 value: out useHttps,
                                                 defaultVal: DEFAULT_CONFIG_VALUE_USE_HTTPS);

                            newWebInterfaceServer.UseSecureHttp = useHttps ?? DEFAULT_CONFIG_VALUE_USE_HTTPS;
                        }

                        // TCP port
                        {
                            int?port;
                            this.StartupConfig
                            .TryGetValue <int?>(category: CONFIG_CATEGORY_WEBINTERFACE,
                                                name: CONFIG_VALUE_PORT,
                                                value: out port,
                                                defaultVal: DEFAULT_CONFIG_VALUE_WEBINTERFACE_PORT);

                            newWebInterfaceServer.Port = port ?? DEFAULT_CONFIG_VALUE_WEBINTERFACE_PORT;
                        }

                        if (newWebInterfaceServer.UseSecureHttp)
                        {
                            // SSL thumbprint
                            {
                                newWebInterfaceServer.SetSslCertificateByThumbprint(this.StartupConfig
                                                                                    .GetValue <IEnumerable <char> >(category: CONFIG_CATEGORY_WEBINTERFACE,
                                                                                                                    name: CONFIG_VALUE_SSL_THUMBPRINT));
                            }
                        }
                    }

                    var newHandler = new WebInterfaceHandler(this, newWebInterfaceServer);
                    this._webHandler = newHandler;

                    newHandler.Start();
                }
                catch (Exception e)
                {
                    this.Logger
                    .Log(msg: e.GetBaseException() ?? e,
                         tag: LOG_TAG_PREFIX + "WebInterface",
                         categories: LoggerFacadeCategories.Errors);

                    this.DisposeOldWebInterfaceServer();
                }
            }

            var moduleList = this.Modules;

            if (moduleList != null)
            {
                ex = moduleList.OfType <global::System.IDisposable>()
                     .ForAllAsync(ctx =>
                {
                    var m         = ctx.Item;
                    var doDispose = true;

                    var dispObj = m as ITMDisposable;
                    if (dispObj != null)
                    {
                        doDispose = !dispObj.IsDisposed;
                    }

                    if (doDispose)
                    {
                        m.Dispose();
                    }
                }, throwExceptions: false);
            }

            if (ex != null)
            {
                this.Logger
                .Log(msg: ex,
                     tag: LOG_TAG_PREFIX + "UnloadOldModules",
                     categories: LoggerFacadeCategories.Errors);
            }

            IList <IAppServerModule> newModules = new SynchronizedCollection <IAppServerModule>();

            var modDir = new DirectoryInfo(Path.Combine(this.WorkingDirectory, "modules")).CreateDirectoryDeep();
            {
                ex = modDir.GetFiles("*.dll")
                     .ForAllAsync(ctx =>
                {
                    var f = ctx.Item;

                    var trustedCatalog = ctx.State.CompositionCatalog.Clone(cloneCatalogData: true);
                    var asmName        = AssemblyName.GetAssemblyName(f.FullName);
                    if (!trustedCatalog.IsTrustedAssembly(asmName))
                    {
#if DEBUG
                        var s = string.Format("INSERT INTO [Security].[TrustedAssemblies] (TrustedAssemblyKey, Name) VALUES (0x{0}, N'{1}');",
                                              asmName.GetPublicKey().AsHexString(),
                                              asmName.FullName);
#endif
                        ctx.State
                        .Logger
                        .Log(categories: LoggerFacadeCategories.Warnings,
                             msg: string.Format("'{0}' is no trusted module!",
                                                f.FullName));

                        return;
                    }

                    var asmBlob = File.ReadAllBytes(f.FullName);
                    var asm     = Assembly.Load(asmBlob);

                    trustedCatalog.AddAssembly(asm);

                    CompositionContainer container;
                    DelegateServiceLocator serviceLocator;
                    {
                        var catalog = new AggregateCatalog();
                        catalog.Catalogs.Add(trustedCatalog);

                        container = new CompositionContainer(catalog,
                                                             isThreadSafe: true);

                        serviceLocator = new DelegateServiceLocator(new ExportProviderServiceLocator(container));
                    }

                    var modules = serviceLocator.GetAllInstances <IAppServerModule>().AsArray();
                    if (modules.Length == 1)
                    {
                        CompositionHelper.ComposeExportedValueEx(container,
                                                                 modules[0]);
                    }
                    else
                    {
                        foreach (var m in modules)
                        {
                            CompositionHelper.ComposeExportedValue(container,
                                                                   m,
                                                                   m.GetType());
                        }
                    }

                    modules.ForAll(ctx2 =>
                    {
                        var m = ctx2.Item;
                        if (m.IsInitialized)
                        {
                            // no need to initialize
                            return;
                        }

                        //TODO: add implementation(s)
                        var logger = new AggregateLogger();

                        var moduleRootDir = new DirectoryInfo(Path.Combine(ctx2.State.ModuleDirectory,
                                                                           m.Name)).CreateDirectoryDeep();

                        var moduleCtx    = new SimpleAppServerModuleContext(m);
                        moduleCtx.Config = new IniFileConfigRepository(Path.Combine(moduleRootDir.FullName,
                                                                                    "config.ini"));
                        moduleCtx.InnerServiceLocator = ctx2.State.ServiceLocator;
                        moduleCtx.Logger       = logger;
                        moduleCtx.OtherModules = ctx2.State.AllModules
                                                 .Where(CreateWherePredicateForExtractingOtherModules(m));
                        moduleCtx.SetAssemblyFile(ctx2.State.AssemblyFile.FullName);

                        var moduleInitCtx           = new SimpleAppServerModuleInitContext();
                        moduleInitCtx.ModuleContext = moduleCtx;
                        moduleInitCtx.RootDirectory = moduleRootDir.FullName;

                        m.Initialize(moduleInitCtx);

                        ctx2.State
                        .NewModules
                        .Add(m);
                    }, actionState: new
                    {
                        AllModules      = modules,
                        AssemblyFile    = f,
                        ModuleDirectory = ctx.State.ModuleDirectory,
                        NewModules      = ctx.State.NewModules,
                        ServiceLocator  = serviceLocator,
                    }, throwExceptions: true);
                }, actionState: new
                {
                    CompositionCatalog = this.TrustedCompositionCatalog
                                         .Clone(cloneCatalogData: false),
                    Logger          = this.Logger,
                    ModuleDirectory = modDir.FullName,
                    NewModules      = newModules,
                }, throwExceptions: false);

                if (ex != null)
                {
                    this.Logger
                    .Log(msg: ex,
                         tag: LOG_TAG_PREFIX + "LoadModules",
                         categories: LoggerFacadeCategories.Errors);
                }
            }

            this.Modules = newModules.Where(m => m.IsInitialized)
                           .ToArray();

            if (this.Modules.Length > 0)
            {
                this.Logger
                .Log(msg: string.Format("{0} modules were loaded.", this.Modules.Length),
                     tag: LOG_TAG_PREFIX + "LoadModules",
                     categories: LoggerFacadeCategories.Information);
            }
            else
            {
                this.Logger
                .Log(msg: "No module was loaded.",
                     tag: LOG_TAG_PREFIX + "LoadModules",
                     categories: LoggerFacadeCategories.Warnings);
            }

            this.RefreshEntityAssemblyList();

            ex = newModules.Where(m => m.CanStart &&
                                  m.IsInitialized)
                 .ForAllAsync(ctx =>
            {
                var m = ctx.Item;

                m.Start();
            }, throwExceptions: false);

            if (ex != null)
            {
                this.Logger
                .Log(msg: ex,
                     tag: LOG_TAG_PREFIX + "StartModules",
                     categories: LoggerFacadeCategories.Errors);
            }
        }