Package tv.ustream.yolo

Source Code of tv.ustream.yolo.Yolo

package tv.ustream.yolo;

import com.google.gson.Gson;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.varia.NullAppender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tv.ustream.yolo.config.ConfigException;
import tv.ustream.yolo.config.ConfigPattern;
import tv.ustream.yolo.handler.FileHandler;
import tv.ustream.yolo.module.ModuleChain;
import tv.ustream.yolo.module.ModuleFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* @author bandesz
*/
public class Yolo
{

    private static final Logger LOG = LoggerFactory.getLogger(Yolo.class);

    private static final PatternLayout CONSOLE_LOG_PATTERN = new PatternLayout("%-6r [%15.15t] %-5p %30.30c - %m%n");

    private static final PatternLayout FILE_LOG_PATTERN = new PatternLayout("%d [%t] %p %c - %m%n");

    private final Options cliOptions = new Options();

    private Map<String, Object> config;

    private static boolean gzip;

    private boolean debug;

    private boolean verbose;

    private String logPath;

    private String configPath;

    private String filePath;

    private Boolean readWholeFile;

    private Boolean reopenFile;

    private long watchConfigInterval;

    private ModuleChain moduleChain = new ModuleChain(new ModuleFactory());

    private FileHandler fileHandler;

    private String hostname;

    public Yolo()
    {
        buildCliOptions();

        setLoggerDefaultOptions();
    }

    private void buildCliOptions()
    {
        cliOptions.addOption("help", false, "print this message");

        cliOptions.addOption("gzip" , false , "read file as gzip compressed");

        cliOptions.addOption("debug", false, "turn on debug mode");

        cliOptions.addOption("verbose", false, "print verbose messages to console");

        Option logOption = new Option("log", true, "log to file");
        logOption.setArgName("path");
        cliOptions.addOption(logOption);

        Option fileOption = new Option("file", true, "path to logfile, wildcards are accepted");
        fileOption.setArgName("path");
        cliOptions.addOption(fileOption);

        Option configOption = new Option("config", true, "path to config file");
        configOption.setArgName("path");
        cliOptions.addOption(configOption);

        cliOptions.addOption("whole", false, "tail file from the beginning");

        cliOptions.addOption("reopen", false, "reopen file between reading the chunks");

        cliOptions.addOption("listModules", false, "list available modules");

        cliOptions.addOption("version", false, "show version");

        Option watchConfigIntervalOption = new Option(
                "watchConfigInterval",
                true,
                "check config file periodically and update without stopping, default: 5 sec"
        );
        watchConfigIntervalOption.setArgName("second");
        cliOptions.addOption(watchConfigIntervalOption);

        Option hostnameOption = new Option("hostname", true, "overwrite hostname");
        hostnameOption.setArgName("short hostname");

        cliOptions.addOption(hostnameOption);
    }

    private void setLoggerDefaultOptions()
    {
        org.apache.log4j.Logger root = org.apache.log4j.Logger.getRootLogger();
        root.addAppender(new NullAppender());
        root.setLevel(Level.INFO);
    }

    private void parseCliOptions(final String[] args) throws Exception
    {
        CommandLine cli;
        try
        {
            cli = new PosixParser().parse(cliOptions, args);
        }
        catch (ParseException exp)
        {
            exitWithError("Error: " + exp.getMessage(), true);
            return;
        }

        if (cli.hasOption("help"))
        {
            printHelp();
            System.exit(0);
        }

        if (cli.hasOption("listModules"))
        {
            ModuleFactory.printAvailableModules();
            System.exit(0);
        }

        if (cli.hasOption("version"))
        {
            printVersion();
            System.exit(0);
        }

        gzip = cli.hasOption("gzip");

        debug = cli.hasOption("debug");

        verbose = cli.hasOption("verbose");

        logPath = cli.getOptionValue("log");

        if (logPath != null && !new File(logPath).isAbsolute())
        {
            exitWithError("log path must be absolute!", false);
            return;
        }

        configPath = cli.getOptionValue("config");

        if (null == configPath || configPath.isEmpty())
        {
            exitWithError("config parameter is missing!", true);
            return;
        }

        if (!new File(configPath).isAbsolute())
        {
            exitWithError("config path must be absolute!", false);
            return;
        }

        filePath = cli.getOptionValue("file");
        if (null == filePath || filePath.isEmpty())
        {
            exitWithError("file parameter is missing!", true);
            return;
        }

        filePath = filePath.replace("\\*", "*").replace("\\?", "?");

        if (!new File(filePath).isAbsolute())
        {
            exitWithError("file path must be absolute!", false);
            return;
        }

        readWholeFile = cli.hasOption("whole");

        reopenFile = cli.hasOption("reopen");
        if (reopenFile && gzip)
        {
            exitWithError("reopen is not supported when gzip reader is enabled", false);
            return;
        }

        watchConfigInterval = TimeUnit.SECONDS.toMillis(
                Integer.parseInt(cli.getOptionValue("watchConfigInterval", "5"))
        );

        hostname = cli.getOptionValue("hostname");
    }

    private void setupLogging()
    {
        org.apache.log4j.Logger root = org.apache.log4j.Logger.getRootLogger();

        if (debug)
        {
            root.setLevel(Level.DEBUG);
        }

        if (verbose)
        {
            root.addAppender(new ConsoleAppender(CONSOLE_LOG_PATTERN));
        }

        if (logPath != null)
        {
            try
            {
                root.addAppender(new FileAppender(FILE_LOG_PATTERN, logPath));
            }
            catch (IOException e)
            {
                exitWithError(e.getMessage(), false);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void readConfig(final boolean update) throws ConfigException
    {
        try
        {
            config = (Map<String, Object>) new Gson().fromJson(new FileReader(configPath), Map.class);
        }
        catch (Exception e)
        {
            exitWithError("Failed to open configuration file: " + e.getMessage(), false);
            return;
        }

        moduleChain.updateConfig(config, !update);
    }

    private void observeConfigChanges() throws Exception
    {
        if (watchConfigInterval < 0)
        {
            return;
        }

        FileAlterationListenerAdaptor listener = new FileAlterationListenerAdaptor()
        {
            @Override
            public void onFileChange(File file)
            {
                LOG.info("Config file changed: {}", configPath);
                try
                {
                    readConfig(true);
                }
                catch (ConfigException e)
                {
                    exitWithError("Failed to refresh config: " + e.getMessage(), false);
                    return;
                }
            }
        };

        String filename = configPath.substring(configPath.lastIndexOf('/') + 1);
        String directory = configPath.substring(0, configPath.lastIndexOf('/'));

        FileAlterationObserver observer = new FileAlterationObserver(
                new File(directory),
                FileFilterUtils.nameFileFilter(filename)
        );
        observer.addListener(listener);

        FileAlterationMonitor monitor = new FileAlterationMonitor(watchConfigInterval);
        monitor.addObserver(observer);

        monitor.start();
    }

    private void setGlobalParameters() throws Exception
    {
        if (hostname != null)
        {
            ConfigPattern.addGlobalParameter("HOSTNAME", hostname);
        }
        else
        {
            ConfigPattern.addGlobalParameter("HOSTNAME", getHostname());
        }
    }

    private String getHostname() throws IOException
    {
        Process process = Runtime.getRuntime().exec("hostname -s");
        return new BufferedReader(new InputStreamReader(process.getInputStream())).readLine();
    }

    private void startFileHandler()
    {
        fileHandler = new FileHandler(moduleChain, filePath, 1000, readWholeFile, reopenFile, gzip);
        fileHandler.start();
    }

    public void start(String[] args)
    {
        try
        {
            parseCliOptions(args);

            setupLogging();

            setGlobalParameters();

            readConfig(false);

            observeConfigChanges();

            startFileHandler();

            addShutdownHook();
        }
        catch (ConfigException e)
        {
            System.out.println(e.getMessage());
        }
        catch (Exception e)
        {
            LOG.error("Exception occured", e);
        }
    }

    public void addShutdownHook()
    {
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            @Override
            public void run()
            {
                LOG.info("Shutting down..");
                Yolo.this.stop();
            }
        });
    }

    public void stop()
    {
        if (null != fileHandler)
        {
            fileHandler.stop();
        }
        moduleChain.stop();
    }

    private void printHelp()
    {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("yolo", cliOptions);
    }

    private void printVersion() throws IOException
    {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("VERSION");
        System.out.println(IOUtils.toString(is, "UTF-8"));
    }

    private void exitWithError(String message, Boolean printHelp)
    {
        System.out.println(message);

        LOG.error(message);

        if (printHelp)
        {
            printHelp();
        }
        System.exit(1);
    }

    public static void main(String[] args)
    {
        Yolo yolo = new Yolo();
        yolo.start(args);
    }

}
TOP

Related Classes of tv.ustream.yolo.Yolo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.