public static boolean doBootstrapperUpdate(Stack<String> updateQueue, JSONObject versionsConfig) {
        
        Logger.info("Updater.doBootstrapperUpdate", "Starting update...");
        
        //Show progress
        GlobalDialogs.showProgressDialog();
        GlobalDialogs.setProgressCaption("Cleaning...");
        GlobalDialogs.setProgressIndeterminate(true);
        
        //Clean patch directory
        Logger.info("Updater.doBootstrapperUpdate", "Cleaning patch directory...");
        try {
            if (new File("./update/mupdatepatch").isDirectory()) {
                FileUtils.deleteDirectory(new File("./update/mupdatepatch"));
            }
        } catch (IOException ex) {
            Logger.error("Updater.doBootstrapperUpdate", "Failed to clean the patch directory!", false, ex);
            GlobalDialogs.hideProgressDialog();
            GlobalDialogs.showNotification("Failed to clean the patch directory!");
            return false;
        }
        
        //Download and extract patches
        while (!updateQueue.empty()) {
            //Load update from JSON
            String updateName = updateQueue.pop();
            JSONObject update = getVersionByName(updateName, "mupdate", versionsConfig);
            
            //Update status
            GlobalDialogs.setProgressCaption("Getting patch '" + updateName + "'...");

            //Download version patch
            Logger.info("Updater.doBootstrapperUpdate", "Downloading patch '" + updateName + "'...");
            try {
                FileUtils.copyURLToFile(new URL(update.get("patch").toString()), new File("./update/mupdate-" + updateName + "-patch.zip"));
            } catch (IOException ex) {
                Logger.error("Updater.doBootstrapperUpdate", "Failed to download patch!", false, ex);
                GlobalDialogs.hideProgressDialog();
                GlobalDialogs.showNotification("Failed to download patch '" + updateName + "'!");
                return false;
            }

            //Extract version patch
            Logger.info("Updater.doUpdate", "Extracting patch '" + updateName + "'...");
            try {
                Util.decompressZipfile("./update/mupdate-" + updateName + "-patch.zip", "./update/mupdatepatch");
            } catch (ZipException ex) {
                Logger.error("Updater.doBootstrapperUpdate", "Failed to extract patch!", false, ex);
                GlobalDialogs.hideProgressDialog();
                GlobalDialogs.showNotification("Failed to extract patch '" + updateName + "'!");
                return false;
            }
        }
        
        //Update status
        GlobalDialogs.setProgressCaption("Applying patches...");
        
        //Apply patch
        Logger.info("Updater.doBootstrapperUpdate", "Applying patch directory...");
        try {
            FileUtils.copyDirectory(new File("./update/mupdatepatch"), new File("./update"));
        } catch (IOException ex) {
            Logger.error("Updater.doBootstrapperUpdate", "Failed to apply patch!", false, ex);
            GlobalDialogs.hideProgressDialog();
            GlobalDialogs.showNotification("Failed to apply MUpdate patch!");
            return false;
        }
        
        //Hide progress window
        GlobalDialogs.hideProgressDialog();
        
        return true;
    }