/*
 * Copyright (c) 2007, 2025, 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;

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.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.lang.reflect.Constructor;
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.Path;
import java.text.MessageFormat;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
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.TimeZone;
import java.util.TreeSet;
import java.util.function.Function;
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.MethodFinder;
import jdk.internal.misc.VM;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.Modules;
import jdk.internal.platform.Container;
import jdk.internal.platform.Metrics;
import jdk.internal.util.OperatingSystem;
import sun.util.calendar.ZoneInfoFile;

/**
 * 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
 */
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 final String ENABLE_NATIVE_ACCESS = "Enable-Native-Access";

    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

    enum Option { DEFAULT, ALL, LOCALE, PROPERTIES, SECURITY,
        SECURITY_ALL, SECURITY_PROPERTIES, SECURITY_PROVIDERS,
        SECURITY_TLS, SYSTEM, VM };

    /*
     * A method called by the launcher to print out the standard settings.
     * -XshowSettings prints details of all supported components in non-verbose
     * mode. -XshowSettings:all prints all settings in verbose mode.
     * Specific settings information may be obtained by using suboptions.
     *
     * Suboption values include "all", "locale", "properties", "security",
     * "system" (Linux only) and "vm". A error message is printed for an
     * unknown suboption value and the VM launch aborts.
     *
     * 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);
        Option component = validateOption(optionFlag);
        switch (component) {
            case ALL -> printAllSettings(initialHeapSize, maxHeapSize, stackSize, true);
            case LOCALE -> printLocale(true);
            case PROPERTIES -> printProperties();
            case SECURITY,
                 SECURITY_ALL,
                 SECURITY_PROPERTIES,
                 SECURITY_PROVIDERS,
                 SECURITY_TLS -> SecuritySettings.printSecuritySettings(component, ostream, true);
            case SYSTEM -> printSystemMetrics();
            case VM -> printVmSettings(initialHeapSize, maxHeapSize, stackSize);
            case DEFAULT -> printAllSettings(initialHeapSize, maxHeapSize, stackSize, false);
        }
    }

    /*
     * Validate that the -XshowSettings value is allowed
     * If a valid option is parsed, return enum corresponding
     * to that option. Abort if a bad option is parsed.
     */
    private static Option validateOption(String optionFlag) {
        if (optionFlag.equals("-XshowSettings")) {
            return Option.DEFAULT;
        }

        if (optionFlag.equals("-XshowSetings:")) {
            abort(null, "java.launcher.bad.option", ":");
        }

        Map<String, Option> validOpts = Arrays.stream(Option.values())
                .filter(o -> !o.equals(Option.DEFAULT)) // non-valid option
                .collect(Collectors.toMap(o -> o.name()
                        .toLowerCase(Locale.ROOT)
                        .replace("_", ":"), Function.identity()));

        String optStr = optionFlag.substring("-XshowSettings:".length());
        Option component = validOpts.get(optStr);
        if (component == null) {
            abort(null, "java.launcher.bad.option", optStr);
        }
        return component;
    }

    /*
     * Print settings for all supported components.
     * verbose value used to determine if verbose information
     * should be printed for components that support printing
     * in verbose or non-verbose mode.
     */
    private static void printAllSettings(long initialHeapSize, long maxHeapSize,
                                         long stackSize, boolean verbose) {
        printVmSettings(initialHeapSize, maxHeapSize, stackSize);
        printProperties();
        printLocale(verbose);
        SecuritySettings.printSecuritySettings(
                    Option.SECURITY_ALL, ostream, verbose);
        if (OperatingSystem.isLinux()) {
            printSystemMetrics();
        }
    }

    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);
        for (String key : p.stringPropertyNames().stream().sorted().toList()) {
            printPropertyValue(key, p.getProperty(key));
        }
        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 bizarre 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(boolean verbose) {
        Locale locale = Locale.getDefault();
        if (verbose) {
            ostream.println(LOCALE_SETTINGS);
        } else {
            ostream.println("Locale settings summary:");
            ostream.println(INDENT + "Use \"-XshowSettings:locale\" " +
                    "option for verbose locale settings options");
        }
        ostream.println(INDENT + "default locale = " +
                locale.getDisplayName());
        ostream.println(INDENT + "default display locale = " +
                Locale.getDefault(Category.DISPLAY).getDisplayName());
        ostream.println(INDENT + "default format locale = " +
                Locale.getDefault(Category.FORMAT).getDisplayName());
        ostream.println(INDENT + "default timezone = " +
                TimeZone.getDefault().getID());
        ostream.println(INDENT + "tzdata version = " +
                ZoneInfoFile.getVersion());
        if (verbose) {
            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);
            }
        }
        ostream.println();
    }

    private static void printSystemMetrics() {
        Metrics c = Container.metrics();

        ostream.println("Operating System Metrics:");

        if (c == null) {
            ostream.println(INDENT + "No metrics available for this platform");
            return;
        }

        final long longRetvalNotSupported = -2;

        ostream.println(INDENT + "Provider: " + c.getProvider());
        if (!c.isContainerized()) {
            ostream.println(INDENT + "System not containerized.");
            return;
        }
        ostream.println(INDENT + "Effective CPU Count: " + c.getEffectiveCpuCount());
        ostream.println(formatCpuVal(c.getCpuPeriod(), INDENT + "CPU Period: ", longRetvalNotSupported));
        ostream.println(formatCpuVal(c.getCpuQuota(), INDENT + "CPU Quota: ", longRetvalNotSupported));
        ostream.println(formatCpuVal(c.getCpuShares(), INDENT + "CPU Shares: ", longRetvalNotSupported));

        int cpus[] = c.getCpuSetCpus();
        if (cpus != null) {
            ostream.println(INDENT + "List of Processors, "
                    + cpus.length + " total: ");

            ostream.print(INDENT);
            for (int i = 0; i < cpus.length; i++) {
                ostream.print(cpus[i] + " ");
            }
            if (cpus.length > 0) {
                ostream.println("");
            }
        } else {
            ostream.println(INDENT + "List of Processors: N/A");
        }

        cpus = c.getEffectiveCpuSetCpus();
        if (cpus != null) {
            ostream.println(INDENT + "List of Effective Processors, "
                    + cpus.length + " total: ");

            ostream.print(INDENT);
            for (int i = 0; i < cpus.length; i++) {
                ostream.print(cpus[i] + " ");
            }
            if (cpus.length > 0) {
                ostream.println("");
            }
        } else {
            ostream.println(INDENT + "List of Effective Processors: N/A");
        }

        int mems[] = c.getCpuSetMems();
        if (mems != null) {
            ostream.println(INDENT + "List of Memory Nodes, "
                    + mems.length + " total: ");

            ostream.print(INDENT);
            for (int i = 0; i < mems.length; i++) {
                ostream.print(mems[i] + " ");
            }
            if (mems.length > 0) {
                ostream.println("");
            }
        } else {
            ostream.println(INDENT + "List of Memory Nodes: N/A");
        }

        mems = c.getEffectiveCpuSetMems();
        if (mems != null) {
            ostream.println(INDENT + "List of Available Memory Nodes, "
                    + mems.length + " total: ");

            ostream.print(INDENT);
            for (int i = 0; i < mems.length; i++) {
                ostream.print(mems[i] + " ");
            }
            if (mems.length > 0) {
                ostream.println("");
            }
        } else {
            ostream.println(INDENT + "List of Available Memory Nodes: N/A");
        }

        long limit = c.getMemoryLimit();
        ostream.println(formatLimitString(limit, INDENT + "Memory Limit: ", longRetvalNotSupported));

        limit = c.getMemorySoftLimit();
        ostream.println(formatLimitString(limit, INDENT + "Memory Soft Limit: ", longRetvalNotSupported));

        limit = c.getMemoryAndSwapLimit();
        ostream.println(formatLimitString(limit, INDENT + "Memory & Swap Limit: ", longRetvalNotSupported));

        limit = c.getPidsMax();
        ostream.println(formatLimitString(limit, INDENT + "Maximum Processes Limit: ",
                                          longRetvalNotSupported, false));
        ostream.println("");
    }

    private static String formatLimitString(long limit, String prefix, long unavailable) {
        return formatLimitString(limit, prefix, unavailable, true);
    }

    private static String formatLimitString(long limit, String prefix, long unavailable, boolean scale) {
        if (limit >= 0) {
            if (scale) {
                return prefix + SizePrefix.scaleValue(limit);
            } else {
                return prefix + limit;
            }
        } else if (limit == unavailable) {
            return prefix + "N/A";
        } else {
            return prefix + "Unlimited";
        }
    }

    private static String formatCpuVal(long cpuVal, String prefix, long unavailable) {
        if (cpuVal >= 0) {
            return prefix + cpuVal + "us";
        } else if (cpuVal == unavailable) {
            return prefix + "N/A";
        } else {
            return prefix + cpuVal;
        }
    }

    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 ));
    }

    /**
     * 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 synonym 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 (OperatingSystem.isMacOS()) {
            ostream.println(getLocalizedMessage("java.launcher.X.macosx.usage",
                        File.pathSeparator));
        }
    }

    /**
     * Prints the short usage text to the desired output stream.
     */
    static void printConciseUsageMessage(boolean printToStderr) {
        initOutput(printToStderr);
        ostream.println(getLocalizedMessage("java.launcher.opt.concise.header",
                File.pathSeparator));
    }

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

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

    private static String getMainClassFromJar(JarFile jarFile) throws IOException {
        String jarname = jarFile.getName();
        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
        String 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);
        }
        String enableNativeAccess = mainAttrs.getValue(ENABLE_NATIVE_ACCESS);
        if (enableNativeAccess != null) {
            if (!enableNativeAccess.equals("ALL-UNNAMED")) {
                abort(null, "java.launcher.jar.error.illegal.ena.value", enableNativeAccess);
            }
            Modules.addEnableNativeAccessToAllUnnamed();
        }

        /*
         * 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();
    }

    /**
     * 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, LM_SOURCE }

    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;
    private static final int LM_SOURCE  = 4;

    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 for a valid 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 = null;
        switch (mode) {
            case LM_MODULE: case LM_SOURCE:
                mainClass = loadModuleMainClass(what);
                break;
            default:
                mainClass = loadMainClass(mode, what);
                break;
        }

        // 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;
        }

        validateMainMethod(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.isEmpty()) {
            // 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.isEmpty()) {
                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 && OperatingSystem.isMacOS()
                    && 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 = null;
        // In LM_JAR mode, keep the underlying file open to retain it in
        // the JarFile/ZipFile cache. This will avoid needing to re-parse
        // the central directory when the file is opened on the class path,
        // triggered by Class.forName below.
        JarFile jarFile = null;
        switch (mode) {
            case LM_CLASS:
                cn = what;
                break;
            case LM_JAR:
                try {
                    jarFile = new JarFile(what);
                    cn = getMainClassFromJar(jarFile);
                } catch (IOException ioe) {
                    abort(ioe, "java.launcher.jar.error1", 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 (OperatingSystem.isMacOS()
                        && 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.error4", cn,
                    le.getClass().getName() + ": " + le.getLocalizedMessage());
        } finally {
            if (jarFile != null) {
                try {
                    jarFile.close();
                } catch (IOException ioe) {
                    abort(ioe, "java.launcher.jar.error5", what);
                }
            }
        }
        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;
    }

    private static boolean isStaticMain = false;
    private static boolean noArgMain = false;

    // Check the existence and signature of main and abort if incorrect.
    private static void validateMainMethod(Class<?> mainClass) {
        Method mainMethod = null;
        try {
            mainMethod = MethodFinder.findMainMethod(mainClass);

            if (mainMethod == null) {
                // invalid main or not FX application, abort with an error
                abort(null, "java.launcher.cls.error2", mainClass.getName(),
                      JAVAFX_APPLICATION_CLASS_NAME);
            }
        } catch (Throwable e) {
            if (mainClass.getModule().isNamed()) {
                abort(e, "java.launcher.module.error3",
                      mainClass.getName(), mainClass.getModule().getName(),
                      e.getClass().getName(), e.getLocalizedMessage());
            } else {
                abort(e, "java.launcher.cls.error5", mainClass.getName(),
                      e.getClass().getName(), e.getLocalizedMessage());
            }
        }

        int mods = mainMethod.getModifiers();
        isStaticMain = Modifier.isStatic(mods);
        noArgMain = mainMethod.getParameterCount() == 0;

        if (!isStaticMain) {
            String className = mainMethod.getDeclaringClass().getName();
            if (Modifier.isAbstract(mainClass.getModifiers())) {
                abort(null, "java.launcher.cls.error8", className);
            }
            if (mainClass.isMemberClass() && !Modifier.isStatic(mainClass.getModifiers())) {
                abort(null, "java.launcher.cls.error7", className);
            }
            try {
                Constructor<?> constructor = mainClass.getDeclaredConstructor();
                if (Modifier.isPrivate(constructor.getModifiers())) {
                    abort(null, "java.launcher.cls.error6", className);
                }
            } catch (Throwable ex) {
                abort(null, "java.launcher.cls.error6", className);
            }
        }
    }

    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.isEmpty()) {
                abort(null, "java.launcher.cls.error3");
            }

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

            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.error3", 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(Locale.ROOT));
    }

    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"));
    }

}
