divconq.tool.Updater.java Source code

Java tutorial

Introduction

Here is the source code for divconq.tool.Updater.java

Source

/* ************************************************************************
#
#  DivConq
#
#  http://divconq.com/
#
#  Copyright:
#    Copyright 2014 eTimeline, LLC. All rights reserved.
#
#  License:
#    See the license.txt file in the project's top-level directory for details.
#
#  Authors:
#    * Andy White
#
************************************************************************ */
package divconq.tool;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;

import divconq.lang.op.FuncResult;
import divconq.lang.op.OperationResult;
import divconq.struct.CompositeParser;
import divconq.struct.CompositeStruct;
import divconq.struct.ListStruct;
import divconq.struct.RecordStruct;
import divconq.struct.Struct;
import divconq.util.HashUtil;
import divconq.util.IOUtil;
import divconq.util.StringUtil;

public class Updater {
    public static Path DEPLOYED_PATH = Paths.get("./config/deployed.json");

    public static void main(String[] args) {
        boolean updated = Updater.tryUpdate();

        while (updated) {
            System.out.println();
            System.out.println("Checking for additional updates");
            System.out.println();

            updated = Updater.tryUpdate();
        }

        System.out.println("Updates completed!");
    }

    static public FuncResult<RecordStruct> loadDeployed() {
        FuncResult<RecordStruct> res = new FuncResult<>();

        FuncResult<CompositeStruct> pres = CompositeParser.parseJson(DEPLOYED_PATH);

        if (!pres.hasErrors())
            res.setResult((RecordStruct) pres.getResult());

        return res;
    }

    static public OperationResult saveDeployed(RecordStruct deployed) {
        OperationResult res = new OperationResult();
        IOUtil.saveEntireFile(Updater.DEPLOYED_PATH, deployed.toPrettyString());
        return res;
    }

    static public boolean tryUpdate() {
        @SuppressWarnings("resource")
        final Scanner scan = new Scanner(System.in);

        FuncResult<RecordStruct> ldres = Updater.loadDeployed();

        if (ldres.hasErrors()) {
            System.out.println("Error reading deployed.json file: " + ldres.getMessage());
            return false;
        }

        RecordStruct deployed = ldres.getResult();

        String ver = deployed.getFieldAsString("Version");
        String packfolder = deployed.getFieldAsString("PackageFolder");
        String packprefix = deployed.getFieldAsString("PackagePrefix");

        if (StringUtil.isEmpty(ver) || StringUtil.isEmpty(packfolder)) {
            System.out.println("Error reading deployed.json file: Missing Version or PackageFolder");
            return false;
        }

        if (StringUtil.isEmpty(packprefix))
            packprefix = "DivConq";

        System.out.println("Current Version: " + ver);

        Path packpath = Paths.get(packfolder);

        if (!Files.exists(packpath) || !Files.isDirectory(packpath)) {
            System.out.println("Error reading PackageFolder - it may not exist or is not a folder.");
            return false;
        }

        File pp = packpath.toFile();
        RecordStruct deployment = null;
        File matchpack = null;

        for (File f : pp.listFiles()) {
            if (!f.getName().startsWith(packprefix + "-") || !f.getName().endsWith("-bin.zip"))
                continue;

            System.out.println("Checking: " + f.getName());

            // if not a match before, clear this
            deployment = null;

            try {
                ZipFile zf = new ZipFile(f);

                Enumeration<ZipArchiveEntry> entries = zf.getEntries();

                while (entries.hasMoreElements()) {
                    ZipArchiveEntry entry = entries.nextElement();

                    if (entry.getName().equals("deployment.json")) {
                        //System.out.println("crc: " + entry.getCrc());

                        FuncResult<CompositeStruct> pres = CompositeParser.parseJson(zf.getInputStream(entry));

                        if (pres.hasErrors()) {
                            System.out.println("Error reading deployment.json file");
                            break;
                        }

                        deployment = (RecordStruct) pres.getResult();

                        break;
                    }
                }

                zf.close();
            } catch (IOException x) {
                System.out.println("Error reading deployment.json file: " + x);
            }

            if (deployment != null) {
                String fndver = deployment.getFieldAsString("Version");
                String fnddependson = deployment.getFieldAsString("DependsOn");

                if (ver.equals(fnddependson)) {
                    System.out.println("Found update: " + fndver);
                    matchpack = f;
                    break;
                }
            }
        }

        if ((matchpack == null) || (deployment == null)) {
            System.out.println("No updates found!");
            return false;
        }

        String fndver = deployment.getFieldAsString("Version");
        String umsg = deployment.getFieldAsString("UpdateMessage");

        if (StringUtil.isNotEmpty(umsg)) {
            System.out.println("========================================================================");
            System.out.println(umsg);
            System.out.println("========================================================================");
        }

        System.out.println();
        System.out.println("Do you want to install?  (y/n)");
        System.out.println();

        String p = scan.nextLine().toLowerCase();

        if (!p.equals("y"))
            return false;

        System.out.println();

        System.out.println("Intalling: " + fndver);

        Set<String> ignorepaths = new HashSet<>();

        ListStruct iplist = deployment.getFieldAsList("IgnorePaths");

        if (iplist != null) {
            for (Struct df : iplist.getItems())
                ignorepaths.add(df.toString());
        }

        ListStruct dflist = deployment.getFieldAsList("DeleteFiles");

        // deleting
        if (dflist != null) {
            for (Struct df : dflist.getItems()) {
                Path delpath = Paths.get(".", df.toString());

                if (Files.exists(delpath)) {
                    System.out.println("Deleting: " + delpath.toAbsolutePath());

                    try {
                        Files.delete(delpath);
                    } catch (IOException x) {
                        System.out.println("Unable to Delete: " + x);
                    }
                }
            }
        }

        // copying updates

        System.out.println("Checking for updated files: ");

        try {
            @SuppressWarnings("resource")
            ZipFile zf = new ZipFile(matchpack);

            Enumeration<ZipArchiveEntry> entries = zf.getEntries();

            while (entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();

                String entryname = entry.getName().replace('\\', '/');
                boolean xfnd = false;

                for (String exculde : ignorepaths)
                    if (entryname.startsWith(exculde)) {
                        xfnd = true;
                        break;
                    }

                if (xfnd)
                    continue;

                System.out.print(".");

                Path localpath = Paths.get(".", entryname);

                if (entry.isDirectory()) {
                    if (!Files.exists(localpath))
                        Files.createDirectories(localpath);
                } else {
                    boolean hashmatch = false;

                    if (Files.exists(localpath)) {
                        String local = null;
                        String update = null;

                        try (InputStream lin = Files.newInputStream(localpath)) {
                            local = HashUtil.getMd5(lin);
                        }

                        try (InputStream uin = zf.getInputStream(entry)) {
                            update = HashUtil.getMd5(uin);
                        }

                        hashmatch = (StringUtil.isNotEmpty(local) && StringUtil.isNotEmpty(update)
                                && local.equals(update));
                    }

                    if (!hashmatch) {
                        System.out.print("[" + entryname + "]");

                        try (InputStream uin = zf.getInputStream(entry)) {
                            Files.createDirectories(localpath.getParent());

                            Files.copy(uin, localpath, StandardCopyOption.REPLACE_EXISTING);
                        } catch (Exception x) {
                            System.out.println("Error updating: " + entryname + " - " + x);
                            return false;
                        }
                    }
                }
            }

            zf.close();
        } catch (IOException x) {
            System.out.println("Error reading update package: " + x);
        }

        // updating local config
        deployed.setField("Version", fndver);

        OperationResult svres = Updater.saveDeployed(deployed);

        if (svres.hasErrors()) {
            System.out.println("Intalled: " + fndver
                    + " but could not update deployed.json.  Repair the file before continuing.\nError: "
                    + svres.getMessage());
            return false;
        }

        System.out.println("Intalled: " + fndver);

        return true;
    }
}