//--- Class Methods ---
        static int Main(string[] args) {
            string site = "", username = "", password = "";
            bool verbose = false, dryrun = false;
            bool showHelp = false;
            string configFile = "";
            var options = new Options() {
                { "s=|site=", "Site address", s => site = s },
                { "u=|username", "Username", u => username = u },
                { "p=|password", "Password", p => password = p },
                { "v|verbose", "Enable verbose output", v => {verbose = true;} },
                { "d|dryrun", "Only perform a dry run, do not change actual data", d => {dryrun = true;} },
            };

            // Validate arguments
            if(args == null || args.Length == 0) {
                showHelp = true;
            } else {
                try {
                    var trailingOptions = options.Parse(args).ToArray();

                    if(trailingOptions.Length < 1) {
                        showHelp = true;
                    } else {
                        configFile = Path.GetFullPath(trailingOptions.First());
                    }
                } catch(InvalidOperationException) {
                    showHelp = true;
                }
                if(string.IsNullOrEmpty(site)) {
                    Console.Write("Site: ");
                    site = Console.ReadLine();
                }
                if(string.IsNullOrEmpty(username)) {
                    Console.Write("Username: "******"Password: "******"No sitename was specified");
                CheckArg(username, "No username was specified");
                CheckArg(password, "No password was specified");
            }
            if(showHelp) {
                ShowHelp(options);
                return -1;
            }

            // Read config File
            XDoc config;
            try {
                config = XDocFactory.LoadFrom(configFile, MimeType.XML);
            } catch(FileNotFoundException) {
                Console.Error.WriteLine("ERROR: Could not find file: {0}", configFile);
                return -1;
            }

            // Create page list from config file
            var pageList = new List<Page>();
            foreach(var pageXml in config["//page"]) {
                var pagePath = pageXml["path"].AsText;
                if(string.IsNullOrEmpty(pagePath)) {
                    Console.Error.WriteLine("WARNING: page path was not specified: \n\n{0}", pageXml);
                    continue;
                }
                var cascade = pageXml["@cascade"].AsText ?? "none";
                var restriction = pageXml["restriction"].AsText ?? "Public";
                var grants = new List<XDoc>();
                foreach(var grant in pageXml["grant"]) {
                    grants.Add(grant);
                }
                var p = new Page(pagePath, cascade, restriction, grants);
                pageList.Add(p);
                if(verbose) {
                    Console.WriteLine(p.ToString());
                }
            }
            if(pageList.Count == 0) {
                Console.Error.WriteLine("ERROR: No page configurations were parsed from the XML config file.");
                return -1;
            }

            // Test connection to MindTouch
            if(!site.StartsWith("http://") && !site.StartsWith("https://")) {
                site = "http://" + site;
            }
            var plug = Plug.New(new XUri(site)).At("@api", "deki").WithCredentials(username, password);
            DreamMessage msg;

            // Check connection with MindTouch
            try {
                msg = plug.At("site", "status").Get();
            } catch(Exception ex) {
                Console.Error.WriteLine("ERROR: cannot connect to {0} with the provided credentials", site);
                return -1;
            }

            // Update pages
            if(!dryrun) {
                foreach(var page in pageList) {  
                    UpdatePage(plug, page, verbose);       
                }
            }
            return 0;
        }
 /// <summary>
 /// Update security Doc on MindTouch page
 /// </summary>
 /// <param name="plug">Authenticated Plug to use to connect to mindtouch</param>
 /// <param name="page">Page class that contains all information to perform the update</param>
 /// <param name="verbose">Print verbose information</param>
 private static void UpdatePage(Plug plug, Page page, bool verbose) {
     if(verbose) {
         Console.WriteLine("Processing page: " + page.Path);
     }
     string encodedPath = XUri.DoubleEncode(page.Path);
     DreamMessage msg;
     var securityDoc = new XDoc("security");
     securityDoc.Add(new XDoc("permissions.page").Elem("restriction", page.Restriction));
     securityDoc.Start("grants");
     foreach(var grant in page.Grants) {
         securityDoc.Add(grant);
     }
     securityDoc.End();
     try {
         msg = plug.At("pages", "=" + encodedPath, "security").With("cascade", page.Cascade).Put(securityDoc);
     } catch(Exception ex) {
         Console.Error.WriteLine("WARNING: processing of page {0} failed", page.Path);
         if(verbose) {
             Console.Error.WriteLine(ex.Message);
             Console.Error.WriteLine(ex.StackTrace);
         }
     }
 }