com.l2jfree.L2AutoInitialization.java Source code

Java tutorial

Introduction

Here is the source code for com.l2jfree.L2AutoInitialization.java

Source

/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program 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 for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jfree;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.PrintStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.Jdk14Logger;

import com.l2jfree.config.ConfigProperty;
import com.l2jfree.config.L2Properties;
import com.l2jfree.io.RedirectingOutputStream.BufferedRedirectingOutputStream;
import com.l2jfree.lang.L2Math;
import com.l2jfree.util.HandlerRegistry;

/**
 * @author evill33t
 */
public abstract class L2AutoInitialization {
    public static final int LOGIN_PROTOCOL_L2J = 258;

    /** Current network protocol version */
    // protocol 1 does not support connection filtering
    public static final int LOGIN_PROTOCOL_CURRENT = 2;

    public static final String LOG_FILE = "./config/logging.properties";
    public static final String TELNET_FILE = "./config/telnet.properties";

    public static Level EXTENDED_LOG_LEVEL = Level.OFF;

    protected static final Log _log;
    protected static final Logger _logger;

    public static final PrintStream out = System.out;
    public static final PrintStream err = System.err;

    static {
        Locale.setDefault(Locale.ENGLISH);
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.err.print("Exception in thread \"" + t.getName() + "\" ");

                e.printStackTrace(System.err);

                // restart automatically
                if (e instanceof Error && !(e instanceof StackOverflowError))
                    Runtime.getRuntime().halt(2);
            }
        });

        if (System.getProperty("user.name").equals("root") && System.getProperty("user.home").equals("/root")) {
            System.out.print("L2Jfree servers should not run under root-account ... exited.");
            System.exit(-1);
        }

        final Map<String, List<String>> libs = new HashMap<String, List<String>>();

        final Set<File> files = new HashSet<File>();

        for (String classPath : System.getProperty("java.class.path").split(File.pathSeparator)) {
            final File classPathFile = new File(classPath);

            if (classPathFile.isDirectory()) {
                for (File f : classPathFile.listFiles())
                    files.add(f);
            } else
                files.add(classPathFile);
        }

        boolean shouldExit = false;

        for (File f : files) {
            if (!f.getName().endsWith("jar"))
                continue;

            final StringBuilder sb = new StringBuilder();

            final StringTokenizer st = new StringTokenizer(f.getName(), "-");

            tokenizer: while (st.hasMoreTokens()) {
                final String token = st.nextToken();

                boolean numberOnly = true;

                for (int i = 0; i < token.length(); i++) {
                    char c = token.charAt(i);

                    if (numberOnly && c == '.')
                        break tokenizer;

                    numberOnly &= Character.isDigit(c);
                }

                if (sb.length() != 0)
                    sb.append("-");

                sb.append(token);
            }

            List<String> list = libs.get(sb.toString());

            if (list == null)
                libs.put(sb.toString(), list = new ArrayList<String>());
            else
                shouldExit = true;

            list.add(f.getName());
        }

        if (shouldExit) {
            System.out.println("Server should not run with classpath conflicts! "
                    + "(rename/remove possible conflicting classpath entries)");

            for (Map.Entry<String, List<String>> entry : libs.entrySet())
                if (entry.getValue().size() > 1)
                    for (String name : entry.getValue())
                        System.out.println("\t'" + name + "'");

            System.exit(-1);
        }

        System.setProperty("line.separator", "\r\n");
        System.setProperty("file.encoding", "UTF-8");
        System.setProperty("org.apache.commons.logging.LogFactory",
                "org.apache.commons.logging.impl.LogFactoryImpl");
        System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.Jdk14Logger");
        System.setProperty("java.util.logging.manager", "com.l2jfree.util.logging.L2LogManager");

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(LOG_FILE);

            LogManager.getLogManager().readConfiguration(fis);
        } catch (Exception e) {
            try {
                // if failed to load 'logging.properties', then load default logging parameters
                LogManager.getLogManager().readConfiguration();
            } catch (Exception e1) {
                throw new Error(e1);
            }
        } finally {
            IOUtils.closeQuietly(fis);
        }

        _log = LogFactory.getLog(L2AutoInitialization.class);
        _log.info("logging initialized");
        _logger = ((Jdk14Logger) _log).getLogger();

        System.setOut(new PrintStream(new BufferedRedirectingOutputStream() {
            @Override
            protected void handleLine(String line) {
                final StackTraceElement caller = getCaller();

                if (caller == null)
                    _logger.logp(Level.INFO, "", "", line);
                else
                    _logger.logp(Level.INFO, caller.getClassName(), caller.getMethodName(), line);
            }
        }));

        System.setErr(new PrintStream(new BufferedRedirectingOutputStream() {
            @Override
            protected void handleLine(String line) {
                final StackTraceElement caller = getCaller();

                if (caller == null)
                    _logger.logp(Level.WARNING, "", "", line);
                else
                    _logger.logp(Level.WARNING, caller.getClassName(), caller.getMethodName(), line);
            }
        }));
    }

    private static StackTraceElement getCaller() {
        StackTraceElement[] stack = new Throwable().getStackTrace();

        for (int i = stack.length - 1; i >= 0; i--) {
            if (stack[i].getClassName().startsWith("java.io.")
                    || stack[i].getMethodName().equals("printStackTrace"))
                return stack[L2Math.limit(0, i + 1, stack.length - 1)];

            if (stack[i].getMethodName().equals("dispatchUncaughtException"))
                break;
        }

        return null;
    }

    protected L2AutoInitialization() {
    }

    private static final HandlerRegistry<String, ConfigLoader> _loaders = new HandlerRegistry<String, ConfigLoader>(
            true) {
        @Override
        public String standardizeKey(String key) {
            return key.trim().toLowerCase();
        }
    };

    protected static void registerConfig(ConfigLoader loader) {
        _loaders.register(loader.getName(), loader);
    }

    public static void loadConfigs() throws Exception {
        for (ConfigLoader loader : _loaders.getHandlers().values())
            loader.load();
    }

    public static String loadConfig(String name) throws Exception {
        final ConfigLoader loader = _loaders.get(name);

        if (loader == null)
            throw new Exception();

        try {
            loader.load();
            return "'" + loader.getName() + "' reloaded!";
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    public static String getLoaderNames() {
        return StringUtils.join(_loaders.getHandlers().keySet().iterator(), "|");
    }

    protected static abstract class ConfigLoader {
        protected abstract String getName();

        protected abstract void load() throws Exception;

        @Override
        public final int hashCode() {
            return getClass().hashCode();
        }

        @Override
        public final boolean equals(Object obj) {
            return getClass().equals(obj.getClass());
        }
    }

    protected static abstract class ConfigFileLoader extends ConfigLoader {
        protected abstract String getFileName();

        @Override
        protected final void load() throws Exception {
            _log.info("loading '" + getFileName() + "'");

            try {
                loadReader(new BufferedReader(new FileReader(getFileName())));
            } catch (Exception e) {
                _log.fatal("Failed to load '" + getFileName() + "'!", e);

                throw new Exception("Failed to load '" + getFileName() + "'!");
            }
        }

        protected abstract void loadReader(BufferedReader reader) throws Exception;
    }

    protected static abstract class ConfigPropertiesLoader extends ConfigFileLoader {
        @Override
        protected final String getFileName() {
            return "./config/" + getName().trim() + ".properties";
        }

        protected Class<?>[] getAnnotatedClasses() {
            return new Class<?>[] { getClass().getEnclosingClass() };
        }

        @Override
        protected final void loadReader(BufferedReader reader) throws Exception {
            final L2Properties properties = new L2Properties(reader);

            for (Class<?> cl : getAnnotatedClasses()) {
                for (Field field : cl.getFields()) {
                    final ConfigProperty configProperty = field.getAnnotation(ConfigProperty.class);

                    if (configProperty == null || !configProperty.loader().equals(getName()))
                        continue;

                    if (!Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
                        _log.warn("Invalid modifiers for " + field);
                        continue;
                    }

                    field.set(null, properties.getProperty(field.getType(), configProperty));
                }
            }

            loadImpl(properties);
        }

        protected abstract void loadImpl(L2Properties properties);
    }

    public static boolean isIDEMode() {
        return Files.exists(Paths.get("pom.xml"));
    }
}