예제 #1
0
        /// <summary>
        /// Boots the runtime within a timer.
        /// </summary>
        protected virtual IFactory Boot(IRegister register, DisposableTimer timer)
        {
            Composition composition = null;

            try
            {
                // Setup event listener
                UnattendedInstalled += CoreRuntime_UnattendedInstalled;

                // throws if not full-trust
                new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand();

                // run handlers
                RuntimeOptions.DoRuntimeBoot(ProfilingLogger);

                // application caches
                var appCaches = GetAppCaches();

                // database factory
                var databaseFactory = GetDatabaseFactory();

                // configs
                var configs = GetConfigs();

                // type loader
                var typeLoader = new TypeLoader(appCaches.RuntimeCache, configs.Global().LocalTempPath, ProfilingLogger);

                // runtime state
                // beware! must use '() => _factory.GetInstance<T>()' and NOT '_factory.GetInstance<T>'
                // as the second one captures the current value (null) and therefore fails
                _state = new RuntimeState(Logger,
                                          configs.Settings(), configs.Global(),
                                          new Lazy <IMainDom>(() => _factory.GetInstance <IMainDom>()),
                                          new Lazy <IServerRegistrar>(() => _factory.GetInstance <IServerRegistrar>()))
                {
                    Level = RuntimeLevel.Boot
                };

                // TODO: remove this in netcore, this is purely backwards compat hacks with the empty ctor
                if (MainDom == null)
                {
                    MainDom = new MainDom(Logger, new MainDomSemaphoreLock(Logger));
                }


                // create the composition
                composition = new Composition(register, typeLoader, ProfilingLogger, _state, configs);
                composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state);

                // run handlers
                RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory);



                // register runtime-level services
                // there should be none, really - this is here "just in case"
                Compose(composition);

                // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
                AcquireMainDom(MainDom);

                // determine our runtime level
                DetermineRuntimeLevel(databaseFactory, ProfilingLogger);

                // get composers, and compose
                var composerTypes = ResolveComposerTypes(typeLoader);

                IEnumerable <Attribute> enableDisableAttributes;
                using (ProfilingLogger.DebugDuration <CoreRuntime>("Scanning enable/disable composer attributes"))
                {
                    enableDisableAttributes = typeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute));
                }

                var composers = new Composers(composition, composerTypes, enableDisableAttributes, ProfilingLogger);
                composers.Compose();

                // create the factory
                _factory = Current.Factory = composition.CreateFactory();

                // determines if unattended install is enabled and performs it if required
                DoUnattendedInstall(databaseFactory);

                // determine our runtime level (AFTER UNATTENDED INSTALL)
                // TODO: Feels kinda weird to call this again
                DetermineRuntimeLevel(databaseFactory, ProfilingLogger);

                // if level is Run and reason is UpgradeMigrations, that means we need to perform an unattended upgrade
                if (_state.Reason == RuntimeLevelReason.UpgradeMigrations && _state.Level == RuntimeLevel.Run)
                {
                    // do the upgrade
                    DoUnattendedUpgrade(_factory.GetInstance <DatabaseBuilder>());

                    // upgrade is done, set reason to Run
                    _state.Reason = RuntimeLevelReason.Run;
                }

                // create & initialize the components
                _components = _factory.GetInstance <ComponentCollection>();
                _components.Initialize();
            }
            catch (Exception e)
            {
                var bfe = e as BootFailedException ?? new BootFailedException("Boot failed.", e);

                if (_state != null)
                {
                    _state.Level = RuntimeLevel.BootFailed;
                    _state.BootFailedException = bfe;
                }

                timer?.Fail(exception: bfe); // be sure to log the exception - even if we repeat ourselves

                // if something goes wrong above, we may end up with no factory
                // meaning nothing can get the runtime state, etc - so let's try
                // to make sure we have a factory
                if (_factory == null)
                {
                    try
                    {
                        _factory = Current.Factory = composition?.CreateFactory();
                    }
                    catch
                    {
                        // In this case we are basically dead, we do not have a factory but we need
                        // to report on the state so we need to manually set that, this is the only time
                        // we ever do this.
                        Current.RuntimeState = _state;
                    }
                }

                Debugger.Break();

                // throwing here can cause w3wp to hard-crash and we want to avoid it.
                // instead, we're logging the exception and setting level to BootFailed.
                // various parts of Umbraco such as UmbracoModule and UmbracoDefaultOwinStartup
                // understand this and will nullify themselves, while UmbracoModule will
                // throw a BootFailedException for every requests.
            }

            return(_factory);
        }