org.jruyi.launcher.Main.java Source code

Java tutorial

Introduction

Here is the source code for org.jruyi.launcher.Main.java

Source

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jruyi.launcher;

import static org.jruyi.system.Constants.JRUYI_HOME_DIR;
import static org.jruyi.system.Constants.JRUYI_INST_CONF_URL;
import static org.jruyi.system.Constants.JRUYI_INST_NAME;
import static org.jruyi.system.Constants.JRUYI_VENDOR;
import static org.jruyi.system.Constants.JRUYI_VERSION;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarFile;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
import org.osgi.framework.Constants;

public final class Main {

    private static final String RUYI_PROPERTY = "property";
    private static final String LOG4J_CONF = "log4j.configurationFile";
    private Object m_ruyi;

    static final class MainHolder {

        static final Main INST = new Main();
    }

    Main() {
    }

    public static void main(String[] args) {

        try {
            MainHolder.INST.init(args);

            if (args.length > 0 && !processCommandLines(args))
                return;

            if (System.getProperty(JRUYI_INST_NAME) == null)
                System.setProperty(JRUYI_INST_NAME, "default");

            Runtime.getRuntime().addShutdownHook(new ShutdownHook());

        } catch (Throwable t) {
            t.printStackTrace();
            return;
        }

        MainHolder.INST.start();
    }

    public static void start(String[] args) {
        try {
            MainHolder.INST.init(args);
        } catch (Throwable t) {
            t.printStackTrace();
            return;
        }

        MainHolder.INST.start();
    }

    public static void stop(String[] args) {
        MainHolder.INST.stop();
    }

    public void init(String[] args) throws Exception {
        ClassLoader classLoader = Main.class.getClassLoader();
        if (!(classLoader instanceof URLClassLoader))
            classLoader = new URLClassLoader(new URL[0], classLoader);

        final Method addUrl = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        boolean accessible = addUrl.isAccessible();
        if (!accessible)
            addUrl.setAccessible(true);

        final ArrayList<String> pkgList = new ArrayList<>();
        final File[] jars = getLibJars();
        for (final File jar : jars) {
            final String exportPackages;
            try (JarFile jf = new JarFile(jar)) {
                exportPackages = jf.getManifest().getMainAttributes().getValue("Export-Package");
            }
            if (exportPackages != null)
                pkgList.add(exportPackages);
            addUrl.invoke(classLoader, jar.getCanonicalFile().toURI().toURL());
        }

        if (!accessible)
            addUrl.setAccessible(false);

        final int n = pkgList.size();
        if (n < 1)
            return;

        final StringBuilder builder = new StringBuilder(pkgList.get(0));
        for (int i = 1; i < n; ++i)
            builder.append(',').append(pkgList.get(i));

        final HashMap<String, String> props = new HashMap<>(3);
        props.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, builder.toString());

        final Class<?> clazz = classLoader.loadClass("org.jruyi.system.main.Ruyi");
        final Object ruyi = clazz.getMethod("getInstance").invoke(null);
        clazz.getMethod("setProperties", Map.class).invoke(ruyi, props);
        final String instConfUrl = (String) clazz.getMethod(RUYI_PROPERTY, String.class).invoke(ruyi,
                JRUYI_INST_CONF_URL);

        System.setProperty(ShutdownCallbackRegistry.SHUTDOWN_CALLBACK_REGISTRY, Log4jCallback.class.getName());
        final String confFile = System.getProperty(LOG4J_CONF);
        if (confFile == null || confFile.trim().isEmpty())
            System.setProperty(LOG4J_CONF, instConfUrl + "log4j2.xml");

        m_ruyi = ruyi;
    }

    public void start() {
        try {
            m_ruyi.getClass().getMethod("startAndWait").invoke(m_ruyi);
        } catch (Throwable t) {
            t.printStackTrace();
            MainHolder.INST.stop();
        }
    }

    public void stop() {
        try {
            m_ruyi.getClass().getMethod("stop").invoke(m_ruyi);
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            Log4jCallback.shutdown();
        }
    }

    public void destroy() {
    }

    private static File[] getLibJars() throws Exception {
        // Home Dir
        File homeDir;
        String temp = System.getProperty(JRUYI_HOME_DIR);
        if (temp == null) {
            String classpath = System.getProperty("java.class.path");
            int index = classpath.toLowerCase().indexOf("jruyi-launcher");
            int start = classpath.lastIndexOf(File.pathSeparator, index) + 1;
            if (index >= start) {
                temp = classpath.substring(start, index);
                homeDir = new File(temp).getCanonicalFile().getParentFile();
            } else
                // use current dir
                homeDir = new File(System.getProperty("user.dir"));
        } else
            homeDir = new File(temp);

        homeDir = homeDir.getCanonicalFile();

        System.setProperty(JRUYI_HOME_DIR, homeDir.getCanonicalPath());

        return new File(homeDir, "lib").listFiles(new JarFileFilter());
    }

    private static boolean processCommandLines(String[] args) throws Exception {
        Options options = new Options();
        options.addOption("?", "help", false, null);
        options.addOption("v", "version", false, null);
        Option o = new Option("D", true, null);
        o.setArgs(Option.UNLIMITED_VALUES);
        options.addOption(o);
        options.addOption("r", "run", true, null);

        CommandLine line = new PosixParser().parse(options, args);

        Option[] opts = line.getOptions();
        for (Option option : opts) {
            String opt = option.getOpt();
            if (opt.equals("?")) {
                printHelp();
                return false;
            } else if (opt.equals("v")) {
                MainHolder.INST.printVersion();
                return false;
            } else if (opt.equals("D")) {
                handleSystemProps(option.getValues());
            } else if (opt.equals("r")) {
                System.setProperty(JRUYI_INST_NAME, option.getValue().trim());
            } else
                throw new Exception("Unknown option: " + option);
        }

        return true;
    }

    private static void printHelp() {
        String programName = System.getProperty("program.name");
        System.out.println();
        System.out.println("Usage: " + programName + " [options]");
        System.out.println();
        System.out.println("options:");
        System.out.println("    -?, --help              print this help message");
        System.out.println("    -v, --version           print version information");
        System.out.println("    -D<name>[=<value>]      add a system property");
        System.out.println("    -r, --run=<instance>    run the specified instance");
        System.out.println();
    }

    private static void handleSystemProps(String[] args) {
        for (String arg : args) {
            final String name;
            final String value;
            final int i = arg.indexOf('=');
            if (i < 0) {
                name = arg;
                value = "true";
            } else {
                name = arg.substring(0, i);
                value = arg.substring(i + 1, arg.length());
            }
            System.setProperty(name, value);
        }
    }

    private void printVersion() throws Exception {
        final Object ruyi = m_ruyi;
        Method property = ruyi.getClass().getMethod(RUYI_PROPERTY, String.class);

        System.out.print("JRuyi version: ");
        System.out.println(property.invoke(ruyi, JRUYI_VERSION));

        System.out.print("JRuyi vendor: ");
        System.out.println(property.invoke(ruyi, JRUYI_VENDOR));

        System.out.println();
    }
}