Пример #1
0
        public CodeCacheManager(XtallStrategy strategy)
        {
            if (strategy == null)
                throw new ArgumentNullException("strategy");
            if (strategy.Context.Url == null)
                throw new ArgumentNullException("strategy.Context.Url");
            if (strategy.Context.Manifest == null)
                throw new ArgumentNullException("strategy.Context.Manifest");
            _strategy = strategy;

            var manifest = _strategy.Context.Manifest;

            if (manifest.ProductName == null)
                throw new ArgumentNullException("The manifest must specify a product name");

            UrlKey = Uri.EscapeDataString(strategy.Context.Url.ToLower());

            _strategy.LogAction("determining the product folder");
            ProductFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), manifest.ProductName);
            _strategy.LogStatus("assigned the product folder as '{0}'", ProductFolder);

            _strategy.LogAction("determining the site folder");
            SiteFolder = Path.Combine(ProductFolder, "Sites", UrlKey);
            _strategy.LogStatus("assigned the site folder as '{0}'", SiteFolder);

            _strategy.LogAction("determining the cache folder");
            CacheFolder = Path.Combine(ProductFolder, "Cache");
            _strategy.LogStatus("assigned the cache folder as '{0}'", CacheFolder);

            _strategy.LogAction("determining the run folder");
            RunFolder = Path.Combine(ProductFolder, "Run", manifest.Md5Hash);
            _strategy.LogStatus("assigned the run folder as '{0}'", RunFolder);

            _strategy.LogAction("creating a mutex to guard the cache");
            _mutex = new Mutex(false, "XtallCacheGuard:" + manifest.ProductName);
            _strategy.LogAction("acquiring the mutex to guard the cache");
            try
            {
                _strategy.LogAction("waiting for access to the cache");
                if (!_mutex.WaitOne(TimeSpan.FromSeconds(5)))
                {
                    _mutex.Dispose();
                    _mutex = null;
                    throw new Exception("Another instance of this application is currently updating your computer. You may retry after it has finished.");
                }
            }
            catch (AbandonedMutexException)
            {
                // suppressed; this is OK (for us...prolly not for the poor sot that died)
            }
            _strategy.LogStatus("acquired access to the cache");
        }
Пример #2
0
        public bool Run(string[] args, XtallStrategy strategy = null)
        {
            _args = args;
            _options = new Options(args);
            _strategy = strategy ?? new XtallStrategy();

            try
            {
                _strategy.LogStatus("starting with command line: {0}", string.Join(" ", args));

                if (_options.Keyed.Keys.Contains("uninstall:"))
                {
                    Uninstall(_options.Keyed["uninstall:"]);
                    return false;
                }

                if (_options.Loose.Count == 0)
                    throw new ArgumentException("Site URL was not specified on the command line");

                _strategy.InternalContext.Url = _options.Loose[0];
                var @unsafe = true; // TODO get the strategy to handle this new Uri(_strategy.Context.Url).Scheme != "https";

                // TODO: block unsafe unless environment is set up for it
                if (_options.Keyed.ContainsKey("debug:"))
                {
                    _strategy.LogStatus("debug requested from the command line; no cache management will be used");
                    _strategy.InternalContext.Manifest = ManifestManager.Load(File.ReadAllText(_options.Keyed["debug:"]));
                    _strategy.OnVerified();
                    _strategy.OnStatus("Debugging", 1.0);
                    _strategy.OnSuccess();
                }
                else
                {
                    _strategy.OnStatus("Connecting and verifying", 0);
                    if (!@unsafe)
                    {
                        _strategy.LogAction("setting the certificate validator");
                        ServicePointManager.CheckCertificateRevocationList = true;
                        ServicePointManager.ServerCertificateValidationCallback = CheckServerCertificate;
                    }
                    else
                    {
                        _strategy.LogStatus("skipping server authentication checks");
                    }

                    _strategy.LogAction("getting the manifest");
                    string manifestXml;
                    using (var ms = new MemoryStream())
                    {
                        _strategy.GetResource(_strategy.Context.Url + "/info", ms, t => t.StartsWith("text/xml"));
                        ms.Seek(0, SeekOrigin.Begin);
                        using (var sr = new StreamReader(ms))
                            manifestXml = sr.ReadToEnd();
                    }

                    _strategy.LogAction("loading the manifest (first 100 characters are '{0}')", manifestXml.Substring(0, 100));
                    _strategy.InternalContext.Manifest = ManifestManager.Load(manifestXml);

                    _strategy.LogAction("creating a code cache manager");
                    using (var cacheManager = new CodeCacheManager(_strategy))
                    {
                        _strategy.LogAction("ensuring the boot package");

                        var candidate = Assembly.GetEntryAssembly().Location;
                        var bootPath = cacheManager.EnsureBoot(candidate);

                        if (bootPath == null)
                        {
                            _strategy.LogStatus("current process is the appropriate boot process");

                            _strategy.OnVerified();
                            _strategy.OnStatus("Loading", 0);

                            UpdateInstall(cacheManager, candidate, _options.Keyed.Keys.Contains("install"));
                            cacheManager.EnsureManifest();
                            _strategy.OnStatus("Loaded", 1.0);
                            _strategy.OnSuccess();

                        }
                        else
                        {
                            _strategy.LogStatus("current process is not executing the required image");
                            _strategy.LogAction("switching to image '{0}'", bootPath);
                            _strategy.OnStatus("Transferring", 0);

                            using (var p = Process.Start(bootPath, string.Join(" ", _args.Select(x => '"' + x + '"'))))
                            {
                            }

                            _strategy.OnTransfer();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _strategy.OnFailure(ex);
            }

            return _strategy.WaitToProceed();
        }