src/demo/share/jpackage/JNLPConverter/src/jnlp/converter/Options.java
author herrick
Tue, 26 Mar 2019 08:54:43 -0400
branchJDK-8200758-branch
changeset 57282 c9c2c08854f5
parent 57106 ea870b9ce89a
child 57315 4f1efc26b577
permissions -rw-r--r--
8221101: Update JNLPConverter to support latest jpackage CLI changes Submitten-by: almatvee Reviewed-by: herrick

/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jnlp.converter;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Options {

    private boolean createImage = false;
    private boolean createInstaller = false;
    private String installerType = null;
    private String jnlp = null;
    private String output = null;
    private String keep = null;
    private boolean help = false;
    private boolean verbose = false;
    private boolean version = false;
    private final List<String> jpackageOptions = new ArrayList<>();
    private boolean isRuntimeImageSet = false;

    private static final String JNLP_OPTION_PREFIX = "--jnlp=";
    private static final String OUTPUT_OPTION_PREFIX = "--output=";
    private static final String KEEP_OPTION_PREFIX = "--keep=";
    private static final String JNLP_OPTION_SHORT_PREFIX = "-j";
    private static final String OUTPUT_OPTION_SHORT_PREFIX = "-o";
    private static final String KEEP_OPTION_SHORT_PREFIX = "-k";

    private static final String [] INSTALLER_TYPES = {"msi", "exe", "dmg", "pkg",
                                                      "rpm", "deb"};

    // --output, -o, --input, -i, --files, -f, --main-jar, --main-class
    private static final String [] BLOCKED_JPACKAGE_OPTIONS = {"--output", "-o", "--input", "-i",
                                                                "--files", "-f", "--main-jar",
                                                                "--main-class"};

    private static final String RUNTIME_IMAGE_OPTION = "--runtime-image";

    private static final String ERR_UNKNOWN_OPTION = "Unknown option: ";
    private static final String ERR_MISSING_VALUE = "Value is required for option ";
    private static final String ERR_MISSING_MODE = "Error: create-image or create-installer mode is required";
    private static final String ERR_MISSING_JNLP = "Error: --jnlp is required";
    private static final String ERR_MISSING_OUTPUT = "Error: --output is required";
    private static final String ERR_OUTPUT_EXISTS = "Error: output folder already exists";
    private static final String ERR_KEEP_EXISTS = "Error: folder for --keep argument already exists";
    private static final String ERR_INVALID_PROTOCOL_JNLP = "Error: Invalid protocol for JNLP file. Only HTTP, HTTPS and FILE protocols are supported.";

    public boolean createImage() {
        return createImage;
    }

    public boolean createInstaller() {
        return createInstaller;
    }

    public String getInstallerType() {
        return installerType;
    }

    public String getJNLP() {
        return jnlp;
    }

    public String getOutput() {
        return output;
    }

    public String keep() {
        return keep;
    }

    public boolean help() {
        return help;
    }

    public boolean verbose() {
        return verbose;
    }

    public boolean version() {
        return version;
    }

    public List<String> getJPackageOptions() {
        return jpackageOptions;
    }

    public boolean isRuntimeImageSet() {
        return isRuntimeImageSet;
    }

    // Helper method to dump all options
    private void display() {
        System.out.println("Options:");
        System.out.println("createImage: " + createImage);
        System.out.println("createInstaller: " + createInstaller);
        System.out.println("installerType: " + installerType);
        System.out.println("jnlp: " + jnlp);
        System.out.println("output: " + output);
        System.out.println("keep: " + keep);
        System.out.println("help: " + help);
        System.out.println("verbose: " + verbose);
        System.out.println("version: " + version);
        for (int i = 0; i < jpackageOptions.size(); i++) {
            System.out.println("jpackageOptions[" + i + "]: " + jpackageOptions.get(i));
        }
    }

    private void validate() {
        if (help || version) {
            return;
        }

        if (!createImage && !createInstaller) {
            optionError(ERR_MISSING_MODE);
        }

        if (jnlp == null) {
            optionError(ERR_MISSING_JNLP);
        } else {
            int index = jnlp.indexOf(":");
            if (index == -1 || index == 0) {
                optionError(ERR_INVALID_PROTOCOL_JNLP);
            } else {
                String protocol = jnlp.substring(0, index);
                if (!protocol.equalsIgnoreCase("http") &&
                    !protocol.equalsIgnoreCase("https") &&
                    !protocol.equalsIgnoreCase("file")) {
                    optionError(ERR_INVALID_PROTOCOL_JNLP);
                }
            }
        }

        if (output == null) {
            optionError(ERR_MISSING_OUTPUT);
        } else {
            File file = new File(output);
            if (file.exists()) {
                optionErrorNoHelp(ERR_OUTPUT_EXISTS);
            }
        }

        if (keep != null) {
            File file = new File(keep);
            if (file.exists()) {
                optionErrorNoHelp(ERR_KEEP_EXISTS);
            }
        }

        jpackageOptions.forEach((option) -> {
            if (isBlockedOption(option)) {
                Log.error(option + " is not allowed via --jpackage-options, since it will conflict with "
                        + "same option generated by JNLPConverter.");
            }
        });
    }

    public boolean isOptionPresent(String option) {
        for (String jpackageOption : jpackageOptions) {
            if (jpackageOption.equalsIgnoreCase(option)) {
                return true;
            }
        }

        return false;
    }

    private boolean isBlockedOption(String option) {
        for (String blockedOption : BLOCKED_JPACKAGE_OPTIONS) {
            if (blockedOption.equalsIgnoreCase(option)) {
                return true;
            }
        }

        return false;
    }

    public static void showHelp() {
//      System.out.println("********* Help should not be longer then 80 characters as per JEP-293 *********");
        System.out.println("Usage: java -jar JNLPConverter.jar <mode> <options>");
        System.out.println("");
        System.out.println("where mode is one of:");
        System.out.println("  create-image");
        System.out.println("          Generates a platform-specific application image.");
        System.out.println("  create-installer");
        System.out.println("          Generates a platform-specific installer for the application.");
        System.out.println("");
        System.out.println("Possible options include:");
        System.out.println("  -j, --jnlp <path>");
        System.out.println("          Full path to JNLP file. Supported protocols are HTTP/HTTPS/FILE.");
        System.out.println("  -o, --output <path>");
        System.out.println("          Name of the directory where generated output files are placed.");
        System.out.println("  -k, --keep <path>");
        System.out.println("          Keep JNLP, JARs and command line arguments for jpackage");
        System.out.println("          in directory provided.");
        System.out.println("      --jpackage-options <options>");
        System.out.println("          Specify additional jpackage options or overwrite provided by JNLPConverter.");
        System.out.println("          All jpackage options can be specified except: --output -o, --input -i,");
        System.out.println("          --files -f, --main-jar -j and --class -c.");
        System.out.println("      --installer-type <type>");
        System.out.println("          The type of the installer to create");
        System.out.println("          Valid values are: {\"exe\", \"msi\", \"rpm\", \"deb\", \"pkg\", \"dmg\"}");
        System.out.println("          If this option is not specified (in create-installer mode) all");
        System.out.println("          supported types of installable packages for the current");
        System.out.println("          platform will be created.");
        System.out.println("  -h, --help, -?");
        System.out.println("          Print this help message");
        System.out.println("  -v, --verbose");
        System.out.println("          Enable verbose output.");
        System.out.println("      --version");
        System.out.println("          Version information.");
        System.out.println("To specify an argument for a long option, you can use --<name>=<value> or");
        System.out.println("--<name> <value>.");
        System.out.println("To specify proxy server use standard Java properties http.proxyHost and http.proxyPort.");
    }

    private static boolean isInstallerType(String type) {
        for (String installerType : INSTALLER_TYPES) {
            if (installerType.equals(type)) {
                return true;
            }
        }

        return false;
    }

    public static Options parseArgs(String[] args) {
        Options options = new Options();

        int index = 0;
        if (args.length >= 1) {
            switch (args[0]) {
                case "create-image":
                    options.createImage = true;
                    index = 1;
                    break;
                case "create-installer":
                    options.createInstaller = true;
                    index = 1;
                    break;
                case "-h":
                case "--help":
                case "-?":
                case "--version":
                    break;
                default:
                    optionError(Options.ERR_MISSING_MODE);
                    break;
            }
        }

        for (int i = index; i < args.length; i++) {
            String arg = args[i];

            if (arg.equals("--jnlp")) {
                if (++i >= args.length) {
                    optionError(Options.ERR_MISSING_VALUE, "--jnlp");
                }
                options.jnlp = args[i];
            }  else if (arg.startsWith(JNLP_OPTION_PREFIX)) {
                options.jnlp = arg.substring(JNLP_OPTION_PREFIX.length());
            } else if (arg.equals("--output")) {
                if (++i >= args.length) {
                    optionError(Options.ERR_MISSING_VALUE, "--output");
                }
                options.output = args[i];
            } else if (arg.startsWith(OUTPUT_OPTION_PREFIX)) {
                options.output = arg.substring(OUTPUT_OPTION_PREFIX.length());
            } else if (arg.equals("--keep")) {
                if (++i >= args.length) {
                    optionError(Options.ERR_MISSING_VALUE, "--keep");
                }
                options.keep = args[i];
            } else if (arg.startsWith(KEEP_OPTION_PREFIX)) {
                options.keep = arg.substring(KEEP_OPTION_PREFIX.length());
            } else if (arg.equals("--help")) {
                options.help = true;
            } else if (arg.equals("--verbose")) {
                options.verbose = true;
            } else if (arg.equals("--version")) {
                options.version = true;
            } else if (arg.equals("-j")) { // short options
                if (++i >= args.length) {
                    optionError(Options.ERR_MISSING_VALUE, "-j");
                }
                options.jnlp = args[i];
            } else if (arg.startsWith(JNLP_OPTION_SHORT_PREFIX)) {
                options.jnlp = arg.substring(JNLP_OPTION_SHORT_PREFIX.length());
            } else if (arg.equals("-o")) {
                if (++i >= args.length) {
                    optionError(Options.ERR_MISSING_VALUE, "-o");
                }
                options.output = args[i];
            } else if (arg.startsWith(OUTPUT_OPTION_SHORT_PREFIX)) {
                options.output = arg.substring(OUTPUT_OPTION_SHORT_PREFIX.length());
            } else if (arg.equals("-k")) {
                if (++i >= args.length) {
                    optionError(Options.ERR_MISSING_VALUE, "-k");
                }
                options.keep = args[i];
            } else if (arg.startsWith(KEEP_OPTION_SHORT_PREFIX)) {
                options.keep = arg.substring(KEEP_OPTION_SHORT_PREFIX.length());
            } else if (arg.equals("-h") || arg.equals("-?")) {
                options.help = true;
            } else if (arg.equals("-v")) {
                options.verbose = true;
            } else if (arg.equals("--jpackage-options")) {
                for (i = (i + 1); i < args.length; i++) {
                    if (!options.isRuntimeImageSet) {
                        if (args[i].equals(RUNTIME_IMAGE_OPTION)) {
                            options.isRuntimeImageSet = true;
                        }
                    }
                    options.jpackageOptions.add(args[i]);
                }
            } else if (arg.equals("--installer-type")) {
                if ((i + 1) < args.length) {
                    if (isInstallerType(args[i + 1])) {
                        options.installerType = args[i + 1];
                        i++;
                    }
                }
            } else {
                optionError(ERR_UNKNOWN_OPTION, arg);
            }
        }

        //options.display(); // For testing only
        options.validate();

        return options;
    }

    private static void optionErrorNoHelp(String msg) {
        System.out.println(msg);
        System.exit(1);
    }

    private static void optionError(String msg) {
        System.out.println(msg);
        System.out.println();
        showHelp();
        System.exit(1);
    }

    private static void optionError(String msg, String option) {
        System.out.println(msg + option);
        System.out.println();
        showHelp();
        System.exit(1);
    }
}