/*
 * Copyright (c) 2007, 2017, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 sun.launcher;

/*
 *
 *  <p><b>This is NOT part of any API supported by Sun Microsystems.
 *  If you write code that depends on this, you do so at your own
 *  risk.  This code and its internal interfaces are subject to change
 *  or deletion without notice.</b>
 *
 */

/**
 * A utility package for the java(1), javaw(1) launchers.
 * The following are helper methods that the native launcher uses
 * to perform checks etc. using JNI, see src/share/bin/java.c
 */
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.module.Configuration;
import java.lang.module.FindException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.Normalizer;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Locale.Category;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jdk.internal.misc.VM;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.Modules;

public final class LauncherHelper {

    // No instantiation
    private LauncherHelper() {}

    // used to identify JavaFX applications
    private static final String JAVAFX_APPLICATION_MARKER =
            "JavaFX-Application-Class";
    private static final String JAVAFX_APPLICATION_CLASS_NAME =
            "javafx.application.Application";
    private static final String JAVAFX_FXHELPER_CLASS_NAME_SUFFIX =
            "sun.launcher.LauncherHelper$FXHelper";
    private static final String LAUNCHER_AGENT_CLASS = "Launcher-Agent-Class";
    private static final String MAIN_CLASS = "Main-Class";
    private static final String ADD_EXPORTS = "Add-Exports";
    private static final String ADD_OPENS = "Add-Opens";

    private static StringBuilder outBuf = new StringBuilder();

    private static final String INDENT = "    ";
    private static final String VM_SETTINGS     = "VM settings:";
    private static final String PROP_SETTINGS   = "Property settings:";
    private static final String LOCALE_SETTINGS = "Locale settings:";

    // sync with java.c and jdk.internal.misc.VM
    private static final String diagprop = "sun.java.launcher.diag";
    static final boolean trace = VM.getSavedProperty(diagprop) != null;

    private static final String defaultBundleName =
            "sun.launcher.resources.launcher";
    private static class ResourceBundleHolder {
        private static final ResourceBundle RB =
                ResourceBundle.getBundle(defaultBundleName);
    }
    private static PrintStream ostream;
    private static Class<?> appClass; // application class, for GUI/reporting purposes

    /*
     * A method called by the launcher to print out the standard settings,
     * by default -XshowSettings is equivalent to -XshowSettings:all,
     * Specific information may be gotten by using suboptions with possible
     * values vm, properties and locale.
     *
     * printToStderr: choose between stdout and stderr
     *
     * optionFlag: specifies which options to print default is all other
     *    possible values are vm, properties, locale.
     *
     * initialHeapSize: in bytes, as set by the launcher, a zero-value indicates
     *    this code should determine this value, using a suitable method or
     *    the line could be omitted.
     *
     * maxHeapSize: in bytes, as set by the launcher, a zero-value indicates
     *    this code should determine this value, using a suitable method.
     *
     * stackSize: in bytes, as set by the launcher, a zero-value indicates
     *    this code determine this value, using a suitable method or omit the
     *    line entirely.
     */
    static void showSettings(boolean printToStderr, String optionFlag,
            long initialHeapSize, long maxHeapSize, long stackSize) {

        initOutput(printToStderr);
        String opts[] = optionFlag.split(":");
        String optStr = (opts.length > 1 && opts[1] != null)
                ? opts[1].trim()
                : "all";
        switch (optStr) {
            case "vm":
                printVmSettings(initialHeapSize, maxHeapSize, stackSize);
                break;
            case "properties":
                printProperties();
                break;
            case "locale":
                printLocale();
                break;
            default:
                printVmSettings(initialHeapSize, maxHeapSize, stackSize);
                printProperties();
                printLocale();
                break;
        }
    }

    /*
     * prints the main vm settings subopt/section
     */
    private static void printVmSettings(
            long initialHeapSize, long maxHeapSize,
            long stackSize) {

        ostream.println(VM_SETTINGS);
        if (stackSize != 0L) {
            ostream.println(INDENT + "Stack Size: " +
                    SizePrefix.scaleValue(stackSize));
        }
        if (initialHeapSize != 0L) {
             ostream.println(INDENT + "Min. Heap Size: " +
                    SizePrefix.scaleValue(initialHeapSize));
        }
        if (maxHeapSize != 0L) {
            ostream.println(INDENT + "Max. Heap Size: " +
                    SizePrefix.scaleValue(maxHeapSize));
        } else {
            ostream.println(INDENT + "Max. Heap Size (Estimated): "
                    + SizePrefix.scaleValue(Runtime.getRuntime().maxMemory()));
        }
        ostream.println(INDENT + "Using VM: "
                + System.getProperty("java.vm.name"));
        ostream.println();
    }

    /*
     * prints the properties subopt/section
     */
    private static void printProperties() {
        Properties p = System.getProperties();
        ostream.println(PROP_SETTINGS);
        List<String> sortedPropertyKeys = new ArrayList<>();
        sortedPropertyKeys.addAll(p.stringPropertyNames());
        Collections.sort(sortedPropertyKeys);
        for (String x : sortedPropertyKeys) {
            printPropertyValue(x, p.getProperty(x));
        }
        ostream.println();
    }

    private static boolean isPath(String key) {
        return key.endsWith(".dirs") || key.endsWith(".path");
    }

    private static void printPropertyValue(String key, String value) {
        ostream.print(INDENT + key + " = ");
        if (key.equals("line.separator")) {
            for (byte b : value.getBytes()) {
                switch (b) {
                    case 0xd:
                        ostream.print("\\r ");
                        break;
                    case 0xa:
                        ostream.print("\\n ");
                        break;
                    default:
                        // print any bizzare line separators in hex, but really
                        // shouldn't happen.
                        ostream.printf("0x%02X", b & 0xff);
                        break;
                }
            }
            ostream.println();
            return;
        }
        if (!isPath(key)) {
            ostream.println(value);
            return;
        }
        String[] values = value.split(System.getProperty("path.separator"));
        boolean first = true;
        for (String s : values) {
            if (first) { // first line treated specially
                ostream.println(s);
                first = false;
            } else { // following lines prefix with indents
                ostream.println(INDENT + INDENT + s);
            }
        }
    }

    /*
     * prints the locale subopt/section
     */
    private static void printLocale() {
        Locale locale = Locale.getDefault();
        ostream.println(LOCALE_SETTINGS);
        ostream.println(INDENT + "default locale = " +
                locale.getDisplayLanguage());
        ostream.println(INDENT + "default display locale = " +
                Locale.getDefault(Category.DISPLAY).getDisplayName());
        ostream.println(INDENT + "default format locale = " +
                Locale.getDefault(Category.FORMAT).getDisplayName());
        printLocales();
        ostream.println();
    }

    private static void printLocales() {
        Locale[] tlocales = Locale.getAvailableLocales();
        final int len = tlocales == null ? 0 : tlocales.length;
        if (len < 1 ) {
            return;
        }
        // Locale does not implement Comparable so we convert it to String
        // and sort it for pretty printing.
        Set<String> sortedSet = new TreeSet<>();
        for (Locale l : tlocales) {
            sortedSet.add(l.toString());
        }

        ostream.print(INDENT + "available locales = ");
        Iterator<String> iter = sortedSet.iterator();
        final int last = len - 1;
        for (int i = 0 ; iter.hasNext() ; i++) {
            String s = iter.next();
            ostream.print(s);
            if (i != last) {
                ostream.print(", ");
            }
            // print columns of 8
            if ((i + 1) % 8 == 0) {
                ostream.println();
                ostream.print(INDENT + INDENT);
            }
        }
    }

    private enum SizePrefix {

        KILO(1024, "K"),
        MEGA(1024 * 1024, "M"),
        GIGA(1024 * 1024 * 1024, "G"),
        TERA(1024L * 1024L * 1024L * 1024L, "T");
        long size;
        String abbrev;

        SizePrefix(long size, String abbrev) {
            this.size = size;
            this.abbrev = abbrev;
        }

        private static String scale(long v, SizePrefix prefix) {
            return BigDecimal.valueOf(v).divide(BigDecimal.valueOf(prefix.size),
                    2, RoundingMode.HALF_EVEN).toPlainString() + prefix.abbrev;
        }
        /*
         * scale the incoming values to a human readable form, represented as
         * K, M, G and T, see java.c parse_size for the scaled values and
         * suffixes. The lowest possible scaled value is Kilo.
         */
        static String scaleValue(long v) {
            if (v < MEGA.size) {
                return scale(v, KILO);
            } else if (v < GIGA.size) {
                return scale(v, MEGA);
            } else if (v < TERA.size) {
                return scale(v, GIGA);
            } else {
                return scale(v, TERA);
            }
        }
    }

    /**
     * A private helper method to get a localized message and also
     * apply any arguments that we might pass.
     */
    private static String getLocalizedMessage(String key, Object... args) {
        String msg = ResourceBundleHolder.RB.getString(key);
        return (args != null) ? MessageFormat.format(msg, args) : msg;
    }

    /**
     * The java -help message is split into 3 parts, an invariant, followed
     * by a set of platform dependent variant messages, finally an invariant
     * set of lines.
     * This method initializes the help message for the first time, and also
     * assembles the invariant header part of the message.
     */
    static void initHelpMessage(String progname) {
        outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.header",
                (progname == null) ? "java" : progname ));
        outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.datamodel",
                32));
        outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.datamodel",
                64));
    }

    /**
     * Appends the vm selection messages to the header, already created.
     * initHelpSystem must already be called.
     */
    static void appendVmSelectMessage(String vm1, String vm2) {
        outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.vmselect",
                vm1, vm2));
    }

    /**
     * Appends the vm synoym message to the header, already created.
     * initHelpSystem must be called before using this method.
     */
    static void appendVmSynonymMessage(String vm1, String vm2) {
        outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.hotspot",
                vm1, vm2));
    }

    /**
     * Appends the last invariant part to the previously created messages,
     * and finishes up the printing to the desired output stream.
     * initHelpSystem must be called before using this method.
     */
    static void printHelpMessage(boolean printToStderr) {
        initOutput(printToStderr);
        outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.footer",
                File.pathSeparator));
        ostream.println(outBuf.toString());
    }

    /**
     * Prints the Xusage text to the desired output stream.
     */
    static void printXUsageMessage(boolean printToStderr) {
        initOutput(printToStderr);
        ostream.println(getLocalizedMessage("java.launcher.X.usage",
                File.pathSeparator));
        if (System.getProperty("os.name").contains("OS X")) {
            ostream.println(getLocalizedMessage("java.launcher.X.macosx.usage",
                        File.pathSeparator));
        }
    }

    static void initOutput(boolean printToStderr) {
        ostream =  (printToStderr) ? System.err : System.out;
    }

    static void initOutput(PrintStream ps) {
        ostream = ps;
    }

    static String getMainClassFromJar(String jarname) {
        String mainValue;
        try (JarFile jarFile = new JarFile(jarname)) {
            Manifest manifest = jarFile.getManifest();
            if (manifest == null) {
                abort(null, "java.launcher.jar.error2", jarname);
            }
            Attributes mainAttrs = manifest.getMainAttributes();
            if (mainAttrs == null) {
                abort(null, "java.launcher.jar.error3", jarname);
            }

            // Main-Class
            mainValue = mainAttrs.getValue(MAIN_CLASS);
            if (mainValue == null) {
                abort(null, "java.launcher.jar.error3", jarname);
            }

            // Launcher-Agent-Class (only check for this when Main-Class present)
            String agentClass = mainAttrs.getValue(LAUNCHER_AGENT_CLASS);
            if (agentClass != null) {
                ModuleLayer.boot().findModule("java.instrument").ifPresent(m -> {
                    try {
                        String cn = "sun.instrument.InstrumentationImpl";
                        Class<?> clazz = Class.forName(cn, false, null);
                        Method loadAgent = clazz.getMethod("loadAgent", String.class);
                        loadAgent.invoke(null, jarname);
                    } catch (Throwable e) {
                        if (e instanceof InvocationTargetException) e = e.getCause();
                        abort(e, "java.launcher.jar.error4", jarname);
                    }
                });
            }

            // Add-Exports and Add-Opens
            String exports = mainAttrs.getValue(ADD_EXPORTS);
            if (exports != null) {
                addExportsOrOpens(exports, false);
            }
            String opens = mainAttrs.getValue(ADD_OPENS);
            if (opens != null) {
                addExportsOrOpens(opens, true);
            }

            /*
             * Hand off to FXHelper if it detects a JavaFX application
             * This must be done after ensuring a Main-Class entry
             * exists to enforce compliance with the jar specification
             */
            if (mainAttrs.containsKey(
                    new Attributes.Name(JAVAFX_APPLICATION_MARKER))) {
                FXHelper.setFXLaunchParameters(jarname, LM_JAR);
                return FXHelper.class.getName();
            }

            return mainValue.trim();
        } catch (IOException ioe) {
            abort(ioe, "java.launcher.jar.error1", jarname);
        }
        return null;
    }

    /**
     * Process the Add-Exports or Add-Opens value. The value is
     * {@code <module>/<package> ( <module>/<package>)*}.
     */
    static void addExportsOrOpens(String value, boolean open) {
        for (String moduleAndPackage : value.split(" ")) {
            String[] s = moduleAndPackage.trim().split("/");
            if (s.length == 2) {
                String mn = s[0];
                String pn = s[1];
                ModuleLayer.boot()
                    .findModule(mn)
                    .filter(m -> m.getDescriptor().packages().contains(pn))
                    .ifPresent(m -> {
                        if (open) {
                            Modules.addOpensToAllUnnamed(m, pn);
                        } else {
                            Modules.addExportsToAllUnnamed(m, pn);
                        }
                    });
            }
        }
    }

    // From src/share/bin/java.c:
    //   enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE }

    private static final int LM_UNKNOWN = 0;
    private static final int LM_CLASS   = 1;
    private static final int LM_JAR     = 2;
    private static final int LM_MODULE  = 3;

    static void abort(Throwable t, String msgKey, Object... args) {
        if (msgKey != null) {
            ostream.println(getLocalizedMessage(msgKey, args));
        }
        if (trace) {
            if (t != null) {
                t.printStackTrace();
            } else {
                Thread.dumpStack();
            }
        }
        System.exit(1);
    }

    /**
     * This method:
     * 1. Loads the main class from the module or class path
     * 2. Checks the public static void main method.
     * 3. If the main class extends FX Application then call on FXHelper to
     * perform the launch.
     *
     * @param printToStderr if set, all output will be routed to stderr
     * @param mode LaunchMode as determined by the arguments passed on the
     *             command line
     * @param what the module name[/class], JAR file, or the main class
     *             depending on the mode
     *
     * @return the application's main class
     */
    public static Class<?> checkAndLoadMain(boolean printToStderr,
                                            int mode,
                                            String what) {
        initOutput(printToStderr);

        Class<?> mainClass = (mode == LM_MODULE) ? loadModuleMainClass(what)
                                                 : loadMainClass(mode, what);

        // record the real main class for UI purposes
        // neither method above can return null, they will abort()
        appClass = mainClass;

        /*
         * Check if FXHelper can launch it using the FX launcher. In an FX app,
         * the main class may or may not have a main method, so do this before
         * validating the main class.
         */
        if (JAVAFX_FXHELPER_CLASS_NAME_SUFFIX.equals(mainClass.getName()) ||
            doesExtendFXApplication(mainClass)) {
            // Will abort() if there are problems with FX runtime
            FXHelper.setFXLaunchParameters(what, mode);
            mainClass = FXHelper.class;
        }

        validateMainClass(mainClass);
        return mainClass;
    }

    /**
     * Returns the main class for a module. The query is either a module name
     * or module-name/main-class. For the former then the module's main class
     * is obtained from the module descriptor (MainClass attribute).
     */
    private static Class<?> loadModuleMainClass(String what) {
        int i = what.indexOf('/');
        String mainModule;
        String mainClass;
        if (i == -1) {
            mainModule = what;
            mainClass = null;
        } else {
            mainModule = what.substring(0, i);
            mainClass = what.substring(i+1);
        }

        // main module is in the boot layer
        ModuleLayer layer = ModuleLayer.boot();
        Optional<Module> om = layer.findModule(mainModule);
        if (!om.isPresent()) {
            // should not happen
            throw new InternalError("Module " + mainModule + " not in boot Layer");
        }
        Module m = om.get();

        // get main class
        if (mainClass == null) {
            Optional<String> omc = m.getDescriptor().mainClass();
            if (!omc.isPresent()) {
                abort(null, "java.launcher.module.error1", mainModule);
            }
            mainClass = omc.get();
        }

        // load the class from the module
        Class<?> c = null;
        try {
            c = Class.forName(m, mainClass);
            if (c == null && System.getProperty("os.name", "").contains("OS X")
                    && Normalizer.isNormalized(mainClass, Normalizer.Form.NFD)) {

                String cn = Normalizer.normalize(mainClass, Normalizer.Form.NFC);
                c = Class.forName(m, cn);
            }
        } catch (LinkageError le) {
            abort(null, "java.launcher.module.error3", mainClass, m.getName(),
                    le.getClass().getName() + ": " + le.getLocalizedMessage());
        }
        if (c == null) {
            abort(null, "java.launcher.module.error2", mainClass, mainModule);
        }

        System.setProperty("jdk.module.main.class", c.getName());
        return c;
    }

    /**
     * Loads the main class from the class path (LM_CLASS or LM_JAR).
     */
    private static Class<?> loadMainClass(int mode, String what) {
        // get the class name
        String cn;
        switch (mode) {
            case LM_CLASS:
                cn = what;
                break;
            case LM_JAR:
                cn = getMainClassFromJar(what);
                break;
            default:
                // should never happen
                throw new InternalError("" + mode + ": Unknown launch mode");
        }

        // load the main class
        cn = cn.replace('/', '.');
        Class<?> mainClass = null;
        ClassLoader scl = ClassLoader.getSystemClassLoader();
        try {
            try {
                mainClass = Class.forName(cn, false, scl);
            } catch (NoClassDefFoundError | ClassNotFoundException cnfe) {
                if (System.getProperty("os.name", "").contains("OS X")
                        && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) {
                    try {
                        // On Mac OS X since all names with diacritical marks are
                        // given as decomposed it is possible that main class name
                        // comes incorrectly from the command line and we have
                        // to re-compose it
                        String ncn = Normalizer.normalize(cn, Normalizer.Form.NFC);
                        mainClass = Class.forName(ncn, false, scl);
                    } catch (NoClassDefFoundError | ClassNotFoundException cnfe1) {
                        abort(cnfe1, "java.launcher.cls.error1", cn,
                                cnfe1.getClass().getCanonicalName(), cnfe1.getMessage());
                    }
                } else {
                    abort(cnfe, "java.launcher.cls.error1", cn,
                            cnfe.getClass().getCanonicalName(), cnfe.getMessage());
                }
            }
        } catch (LinkageError le) {
            abort(le, "java.launcher.cls.error6", cn,
                    le.getClass().getName() + ": " + le.getLocalizedMessage());
        }
        return mainClass;
    }

    /*
     * Accessor method called by the launcher after getting the main class via
     * checkAndLoadMain(). The "application class" is the class that is finally
     * executed to start the application and in this case is used to report
     * the correct application name, typically for UI purposes.
     */
    public static Class<?> getApplicationClass() {
        return appClass;
    }

    /*
     * Check if the given class is a JavaFX Application class. This is done
     * in a way that does not cause the Application class to load or throw
     * ClassNotFoundException if the JavaFX runtime is not available.
     */
    private static boolean doesExtendFXApplication(Class<?> mainClass) {
        for (Class<?> sc = mainClass.getSuperclass(); sc != null;
                sc = sc.getSuperclass()) {
            if (sc.getName().equals(JAVAFX_APPLICATION_CLASS_NAME)) {
                return true;
            }
        }
        return false;
    }

    // Check the existence and signature of main and abort if incorrect
    static void validateMainClass(Class<?> mainClass) {
        Method mainMethod = null;
        try {
            mainMethod = mainClass.getMethod("main", String[].class);
        } catch (NoSuchMethodException nsme) {
            // invalid main or not FX application, abort with an error
            abort(null, "java.launcher.cls.error4", mainClass.getName(),
                  JAVAFX_APPLICATION_CLASS_NAME);
        } catch (Throwable e) {
            if (mainClass.getModule().isNamed()) {
                abort(e, "java.launcher.module.error5",
                      mainClass.getName(), mainClass.getModule(),
                      e.getClass().getName(), e.getLocalizedMessage());
            } else {
                abort(e, "java.launcher.cls.error7", mainClass.getName(),
                      e.getClass().getName(), e.getLocalizedMessage());
            }
        }

        /*
         * getMethod (above) will choose the correct method, based
         * on its name and parameter type, however, we still have to
         * ensure that the method is static and returns a void.
         */
        int mod = mainMethod.getModifiers();
        if (!Modifier.isStatic(mod)) {
            abort(null, "java.launcher.cls.error2", "static",
                  mainMethod.getDeclaringClass().getName());
        }
        if (mainMethod.getReturnType() != java.lang.Void.TYPE) {
            abort(null, "java.launcher.cls.error3",
                  mainMethod.getDeclaringClass().getName());
        }
    }

    private static final String encprop = "sun.jnu.encoding";
    private static String encoding = null;
    private static boolean isCharsetSupported = false;

    /*
     * converts a c or a byte array to a platform specific string,
     * previously implemented as a native method in the launcher.
     */
    static String makePlatformString(boolean printToStderr, byte[] inArray) {
        initOutput(printToStderr);
        if (encoding == null) {
            encoding = System.getProperty(encprop);
            isCharsetSupported = Charset.isSupported(encoding);
        }
        try {
            String out = isCharsetSupported
                    ? new String(inArray, encoding)
                    : new String(inArray);
            return out;
        } catch (UnsupportedEncodingException uee) {
            abort(uee, null);
        }
        return null; // keep the compiler happy
    }

    static String[] expandArgs(String[] argArray) {
        List<StdArg> aList = new ArrayList<>();
        for (String x : argArray) {
            aList.add(new StdArg(x));
        }
        return expandArgs(aList);
    }

    static String[] expandArgs(List<StdArg> argList) {
        ArrayList<String> out = new ArrayList<>();
        if (trace) {
            System.err.println("Incoming arguments:");
        }
        for (StdArg a : argList) {
            if (trace) {
                System.err.println(a);
            }
            if (a.needsExpansion) {
                File x = new File(a.arg);
                File parent = x.getParentFile();
                String glob = x.getName();
                if (parent == null) {
                    parent = new File(".");
                }
                try (DirectoryStream<Path> dstream =
                        Files.newDirectoryStream(parent.toPath(), glob)) {
                    int entries = 0;
                    for (Path p : dstream) {
                        out.add(p.normalize().toString());
                        entries++;
                    }
                    if (entries == 0) {
                        out.add(a.arg);
                    }
                } catch (Exception e) {
                    out.add(a.arg);
                    if (trace) {
                        System.err.println("Warning: passing argument as-is " + a);
                        System.err.print(e);
                    }
                }
            } else {
                out.add(a.arg);
            }
        }
        String[] oarray = new String[out.size()];
        out.toArray(oarray);

        if (trace) {
            System.err.println("Expanded arguments:");
            for (String x : oarray) {
                System.err.println(x);
            }
        }
        return oarray;
    }

    /* duplicate of the native StdArg struct */
    private static class StdArg {
        final String arg;
        final boolean needsExpansion;
        StdArg(String arg, boolean expand) {
            this.arg = arg;
            this.needsExpansion = expand;
        }
        // protocol: first char indicates whether expansion is required
        // 'T' = true ; needs expansion
        // 'F' = false; needs no expansion
        StdArg(String in) {
            this.arg = in.substring(1);
            needsExpansion = in.charAt(0) == 'T';
        }
        public String toString() {
            return "StdArg{" + "arg=" + arg + ", needsExpansion=" + needsExpansion + '}';
        }
    }

    static final class FXHelper {

        private static final String JAVAFX_GRAPHICS_MODULE_NAME =
                "javafx.graphics";

        private static final String JAVAFX_LAUNCHER_CLASS_NAME =
                "com.sun.javafx.application.LauncherImpl";

        /*
         * The launch method used to invoke the JavaFX launcher. These must
         * match the strings used in the launchApplication method.
         *
         * Command line                 JavaFX-App-Class  Launch mode  FX Launch mode
         * java -cp fxapp.jar FXClass   N/A               LM_CLASS     "LM_CLASS"
         * java -cp somedir FXClass     N/A               LM_CLASS     "LM_CLASS"
         * java -jar fxapp.jar          Present           LM_JAR       "LM_JAR"
         * java -jar fxapp.jar          Not Present       LM_JAR       "LM_JAR"
         * java -m module/class [1]     N/A               LM_MODULE    "LM_MODULE"
         * java -m module               N/A               LM_MODULE    "LM_MODULE"
         *
         * [1] - JavaFX-Application-Class is ignored when modular args are used, even
         * if present in a modular jar
         */
        private static final String JAVAFX_LAUNCH_MODE_CLASS = "LM_CLASS";
        private static final String JAVAFX_LAUNCH_MODE_JAR = "LM_JAR";
        private static final String JAVAFX_LAUNCH_MODE_MODULE = "LM_MODULE";

        /*
         * FX application launcher and launch method, so we can launch
         * applications with no main method.
         */
        private static String fxLaunchName = null;
        private static String fxLaunchMode = null;

        private static Class<?> fxLauncherClass    = null;
        private static Method   fxLauncherMethod   = null;

        /*
         * Set the launch params according to what was passed to LauncherHelper
         * so we can use the same launch mode for FX. Abort if there is any
         * issue with loading the FX runtime or with the launcher method.
         */
        private static void setFXLaunchParameters(String what, int mode) {

            // find the module with the FX launcher
            Optional<Module> om = ModuleLayer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME);
            if (!om.isPresent()) {
                abort(null, "java.launcher.cls.error5");
            }

            // load the FX launcher class
            fxLauncherClass = Class.forName(om.get(), JAVAFX_LAUNCHER_CLASS_NAME);
            if (fxLauncherClass == null) {
                abort(null, "java.launcher.cls.error5");
            }

            try {
                /*
                 * signature must be:
                 * public static void launchApplication(String launchName,
                 *     String launchMode, String[] args);
                 */
                fxLauncherMethod = fxLauncherClass.getMethod("launchApplication",
                        String.class, String.class, String[].class);

                // verify launcher signature as we do when validating the main method
                int mod = fxLauncherMethod.getModifiers();
                if (!Modifier.isStatic(mod)) {
                    abort(null, "java.launcher.javafx.error1");
                }
                if (fxLauncherMethod.getReturnType() != java.lang.Void.TYPE) {
                    abort(null, "java.launcher.javafx.error1");
                }
            } catch (NoSuchMethodException ex) {
                abort(ex, "java.launcher.cls.error5", ex);
            }

            fxLaunchName = what;
            switch (mode) {
                case LM_CLASS:
                    fxLaunchMode = JAVAFX_LAUNCH_MODE_CLASS;
                    break;
                case LM_JAR:
                    fxLaunchMode = JAVAFX_LAUNCH_MODE_JAR;
                    break;
                case LM_MODULE:
                    fxLaunchMode = JAVAFX_LAUNCH_MODE_MODULE;
                    break;
                default:
                    // should not have gotten this far...
                    throw new InternalError(mode + ": Unknown launch mode");
            }
        }

        public static void main(String... args) throws Exception {
            if (fxLauncherMethod == null
                    || fxLaunchMode == null
                    || fxLaunchName == null) {
                throw new RuntimeException("Invalid JavaFX launch parameters");
            }
            // launch appClass via fxLauncherMethod
            fxLauncherMethod.invoke(null,
                    new Object[] {fxLaunchName, fxLaunchMode, args});
        }
    }

    /**
     * Called by the launcher to list the observable modules.
     */
    static void listModules() {
        initOutput(System.out);

        ModuleBootstrap.limitedFinder().findAll().stream()
            .sorted(new JrtFirstComparator())
            .forEach(LauncherHelper::showModule);
    }

    /**
     * Called by the launcher to show the resolved modules
     */
    static void showResolvedModules() {
        initOutput(System.out);

        ModuleLayer bootLayer = ModuleLayer.boot();
        Configuration cf = bootLayer.configuration();

        cf.modules().stream()
            .map(ResolvedModule::reference)
            .sorted(new JrtFirstComparator())
            .forEach(LauncherHelper::showModule);
    }

    /**
     * Called by the launcher to describe a module
     */
    static void describeModule(String moduleName) {
        initOutput(System.out);

        ModuleFinder finder = ModuleBootstrap.limitedFinder();
        ModuleReference mref = finder.find(moduleName).orElse(null);
        if (mref == null) {
            abort(null, "java.launcher.module.error4", moduleName);
        }
        ModuleDescriptor md = mref.descriptor();

        // one-line summary
        showModule(mref);

        // unqualified exports (sorted by package)
        md.exports().stream()
            .filter(e -> !e.isQualified())
            .sorted(Comparator.comparing(Exports::source))
            .map(e -> Stream.concat(Stream.of(e.source()),
                                    toStringStream(e.modifiers()))
                    .collect(Collectors.joining(" ")))
            .forEach(sourceAndMods -> ostream.format("exports %s%n", sourceAndMods));

        // dependences
        for (Requires r : md.requires()) {
            String nameAndMods = Stream.concat(Stream.of(r.name()),
                                               toStringStream(r.modifiers()))
                    .collect(Collectors.joining(" "));
            ostream.format("requires %s", nameAndMods);
            finder.find(r.name())
                .map(ModuleReference::descriptor)
                .filter(ModuleDescriptor::isAutomatic)
                .ifPresent(any -> ostream.print(" automatic"));
            ostream.println();
        }

        // service use and provides
        for (String s : md.uses()) {
            ostream.format("uses %s%n", s);
        }
        for (Provides ps : md.provides()) {
            String names = ps.providers().stream().collect(Collectors.joining(" "));
            ostream.format("provides %s with %s%n", ps.service(), names);

        }

        // qualified exports
        for (Exports e : md.exports()) {
            if (e.isQualified()) {
                String who = e.targets().stream().collect(Collectors.joining(" "));
                ostream.format("qualified exports %s to %s%n", e.source(), who);
            }
        }

        // open packages
        for (Opens opens: md.opens()) {
            if (opens.isQualified())
                ostream.print("qualified ");
            String sourceAndMods = Stream.concat(Stream.of(opens.source()),
                                                 toStringStream(opens.modifiers()))
                    .collect(Collectors.joining(" "));
            ostream.format("opens %s", sourceAndMods);
            if (opens.isQualified()) {
                String who = opens.targets().stream().collect(Collectors.joining(" "));
                ostream.format(" to %s", who);
            }
            ostream.println();
        }

        // non-exported/non-open packages
        Set<String> concealed = new TreeSet<>(md.packages());
        md.exports().stream().map(Exports::source).forEach(concealed::remove);
        md.opens().stream().map(Opens::source).forEach(concealed::remove);
        concealed.forEach(p -> ostream.format("contains %s%n", p));
    }

    /**
     * Prints a single line with the module name, version and modifiers
     */
    private static void showModule(ModuleReference mref) {
        ModuleDescriptor md = mref.descriptor();
        ostream.print(md.toNameAndVersion());
        mref.location()
                .filter(uri -> !isJrt(uri))
                .ifPresent(uri -> ostream.format(" %s", uri));
        if (md.isOpen())
            ostream.print(" open");
        if (md.isAutomatic())
            ostream.print(" automatic");
        ostream.println();
    }

    /**
     * A ModuleReference comparator that considers modules in the run-time
     * image to be less than modules than not in the run-time image.
     */
    private static class JrtFirstComparator implements Comparator<ModuleReference> {
        private final Comparator<ModuleReference> real;

        JrtFirstComparator() {
            this.real = Comparator.comparing(ModuleReference::descriptor);
        }

        @Override
        public int compare(ModuleReference a, ModuleReference b) {
            if (isJrt(a)) {
                return isJrt(b) ? real.compare(a, b) : -1;
            } else {
                return isJrt(b) ? 1 : real.compare(a, b);
            }
        }
    }

    private static <T> Stream<String> toStringStream(Set<T> s) {
        return s.stream().map(e -> e.toString().toLowerCase());
    }

    private static boolean isJrt(ModuleReference mref) {
        return isJrt(mref.location().orElse(null));
    }

    private static boolean isJrt(URI uri) {
        return (uri != null && uri.getScheme().equalsIgnoreCase("jrt"));
    }

    /**
     * Called by the launcher to validate the modules on the upgrade and
     * application module paths.
     *
     * @return {@code true} if no errors are found
     */
    private static boolean validateModules() {
        initOutput(System.out);

        ModuleValidator validator = new ModuleValidator();

        // upgrade module path
        String value = System.getProperty("jdk.module.upgrade.path");
        if (value != null) {
            Stream.of(value.split(File.pathSeparator))
                    .map(Paths::get)
                    .forEach(validator::scan);
        }

        // system modules
        ModuleFinder.ofSystem().findAll().stream()
                .sorted(Comparator.comparing(ModuleReference::descriptor))
                .forEach(validator::process);

        // application module path
        value = System.getProperty("jdk.module.path");
        if (value != null) {
            Stream.of(value.split(File.pathSeparator))
                    .map(Paths::get)
                    .forEach(validator::scan);
        }

        return !validator.foundErrors();
    }

    /**
     * A simple validator to check for errors and conflicts between modules.
     */
    static class ModuleValidator {
        private static final String MODULE_INFO = "module-info.class";

        private Map<String, ModuleReference> nameToModule = new HashMap<>();
        private Map<String, ModuleReference> packageToModule = new HashMap<>();
        private boolean errorFound;

        /**
         * Returns true if at least one error was found
         */
        boolean foundErrors() {
            return errorFound;
        }

        /**
         * Prints the module location and name.
         */
        private void printModule(ModuleReference mref) {
            mref.location()
                .filter(uri -> !isJrt(uri))
                .ifPresent(uri -> ostream.print(uri + " "));
            ModuleDescriptor descriptor = mref.descriptor();
            ostream.print(descriptor.name());
            if (descriptor.isAutomatic())
                ostream.print(" automatic");
            ostream.println();
        }

        /**
         * Prints the module location and name, checks if the module is
         * shadowed by a previously seen module, and finally checks for
         * package conflicts with previously seen modules.
         */
        void process(ModuleReference mref) {
            printModule(mref);

            String name = mref.descriptor().name();
            ModuleReference previous = nameToModule.putIfAbsent(name, mref);
            if (previous != null) {
                ostream.print(INDENT + "shadowed by ");
                printModule(previous);
            } else {
                // check for package conflicts when not shadowed
                for (String pkg :  mref.descriptor().packages()) {
                    previous = packageToModule.putIfAbsent(pkg, mref);
                    if (previous != null) {
                        String mn = previous.descriptor().name();
                        ostream.println(INDENT + "contains " + pkg
                                        + " conflicts with module " + mn);
                        errorFound = true;
                    }
                }
            }
        }

        /**
         * Scan an element on a module path. The element is a directory
         * of modules, an exploded module, or a JAR file.
         */
        void scan(Path entry) {
            BasicFileAttributes attrs;
            try {
                attrs = Files.readAttributes(entry, BasicFileAttributes.class);
            } catch (NoSuchFileException ignore) {
                return;
            } catch (IOException ioe) {
                ostream.println(entry + " " + ioe);
                errorFound = true;
                return;
            }

            String fn = entry.getFileName().toString();
            if (attrs.isRegularFile() && fn.endsWith(".jar")) {
                // JAR file, explicit or automatic module
                scanModule(entry).ifPresent(this::process);
            } else if (attrs.isDirectory()) {
                Path mi = entry.resolve(MODULE_INFO);
                if (Files.exists(mi)) {
                    // exploded module
                    scanModule(entry).ifPresent(this::process);
                } else {
                    // directory of modules
                    scanDirectory(entry);
                }
            }
        }

        /**
         * Scan the JAR files and exploded modules in a directory.
         */
        private void scanDirectory(Path dir) {
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
                Map<String, Path> moduleToEntry = new HashMap<>();

                for (Path entry : stream) {
                    BasicFileAttributes attrs;
                    try {
                        attrs = Files.readAttributes(entry, BasicFileAttributes.class);
                    } catch (IOException ioe) {
                        ostream.println(entry + " " + ioe);
                        errorFound = true;
                        continue;
                    }

                    ModuleReference mref = null;

                    String fn = entry.getFileName().toString();
                    if (attrs.isRegularFile() && fn.endsWith(".jar")) {
                        mref = scanModule(entry).orElse(null);
                    } else if (attrs.isDirectory()) {
                        Path mi = entry.resolve(MODULE_INFO);
                        if (Files.exists(mi)) {
                            mref = scanModule(entry).orElse(null);
                        }
                    }

                    if (mref != null) {
                        String name = mref.descriptor().name();
                        Path previous = moduleToEntry.putIfAbsent(name, entry);
                        if (previous != null) {
                            // same name as other module in the directory
                            printModule(mref);
                            ostream.println(INDENT + "contains same module as "
                                            + previous.getFileName());
                            errorFound = true;
                        } else {
                            process(mref);
                        }
                    }
                }
            } catch (IOException ioe) {
                ostream.println(dir + " " + ioe);
                errorFound = true;
            }
        }

        /**
         * Scan a JAR file or exploded module.
         */
        private Optional<ModuleReference> scanModule(Path entry) {
            ModuleFinder finder = ModuleFinder.of(entry);
            try {
                return finder.findAll().stream().findFirst();
            } catch (FindException e) {
                ostream.println(entry);
                ostream.println(INDENT + e.getMessage());
                Throwable cause = e.getCause();
                if (cause != null) {
                    ostream.println(INDENT + cause);
                }
                errorFound = true;
                return Optional.empty();
            }
        }
    }
}
