org.hrva.capture.Capture.java Source code

Java tutorial

Introduction

Here is the source code for org.hrva.capture.Capture.java

Source

/*
 * The HRT Project.
 * This work is licensed under the 
 * Creative Commons Attribution-NonCommercial 3.0 Unported License. 
 * To view a copy of this license, 
 * visit http://creativecommons.org/licenses/by-nc/3.0/ 
 * or send a letter to 
 * Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
 */
package org.hrva.capture;

import com.fourspaces.couchdb.Document;
import java.io.*;
import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;

/**
 * Combination "Wrapper" which tails a log, reformats and then pushes.
 *
 * <p>This cycles on a one-minute interval. </p>
 *
 * <p>This is both a main program with a command-line interface, as well as
 * object that can be used to push. </p>
 *
 * <p>Typical use case</p>
 * <code><pre>
 *      File prop_file = new File("hrtail.properties");
 *      Properties config= new Properties();
 *      config.load(new FileInputStream(prop_file));
 *
 *      Capture instance = new Capture(config);
 *      instance.capture( "/path/to/some.log", 60.0 );
 * </pre></code>
 *
 * <p>At the command line, it might look like this.</p>
 * <code><pre>
 * java -cp LogCapture/dist/LogCapture.jar org.hrva.capture.Capture /path/to/some.log
 * </pre></code>
 *
 * <p>This will cycle indefinitely, capturing, reformatting and pushing extracts
 * from the log file. </p>
 *
 * <p>This uses the <tt>hrtail.properties</tt> file.</p> <dl>
 * <dt><tt>capture.extract_filename</tt><dd>The file to which to write log
 * extracts</dd> <dt><tt>capture.csv_filename</tt><dd>The file to which to write
 * reformatted extracts</dd> </dl>
 *
 * @author slott
 */
public class Capture {

    /**
     * Properties for this application.
     */
    Properties global;
    /**
     * Immediate Push option.
     */
    @Option(name = "-1", usage = "One Ping Only, Please.")
    boolean one_time = false;
    /**
     * Verbose debugging.
     */
    @Option(name = "-v", usage = "Vebose logging")
    boolean verbose = false;
    /**
     * Cycle time.
     */
    @Option(name = "-c", usage = "Cyclic Processing Interval, default 60 seconds")
    double cycle_time = 60.0;
    /**
     * Command-line Arguments.
     */
    @Argument
    List<String> arguments = new ArrayList<String>();
    /**
     * The Scheduling timer.
     */
    Timer timer = new Timer();
    /**
     * The scheduled operation.
     */
    Tail_Format_Push worker;
    /**
     * Logger.
     */
    final Log logger = LogFactory.getLog(Capture.class);

    /**
     * Command-line program to tail a log and then push file to the HRT couch
     * DB.
     *
     * <p>All this does is read properties and invoke run_main</p>
     *
     * @param args arguments
     */
    public static void main(String[] args) {
        Log log = LogFactory.getLog(Reformat.class);
        File prop_file = new File("hrtail.properties");
        Properties config = new Properties();
        try {
            config.load(new FileInputStream(prop_file));
        } catch (IOException ex) {
            log.warn("Can't find " + prop_file.getName(), ex);
            try {
                log.debug(prop_file.getCanonicalPath());
            } catch (IOException ex1) {
            }
        }
        Capture capture = new Capture(config);
        try {
            capture.run_main(args);
        } catch (CmdLineException ex1) {
            log.fatal("Invalid Options", ex1);
        } catch (MalformedURLException ex2) {
            log.fatal("Invalid CouchDB URL", ex2);
        } catch (IOException ex3) {
            log.fatal(ex3);
        }
    }

    /**
     * Build the LogTail instance.
     *
     * @param global The hrtail.properties file
     */
    public Capture(Properties global) {
        super();
        this.global = global;
        worker = new Tail_Format_Push();
    }

    /**
     * Does the three-stop process of tail, reformat and couch push.
     *
     * <p>Accepts the following options</p> <dl> <dt><tt>-1</tt></dt><dd>Don't
     * cycle; process once only.</dd> <dt><tt>-v</tt></dt><dd>Verbose
     * logging.</dd> </dl> <p>This gets properties from the
     * <tt>hrtail.properties</tt> file.</p>
     *
     *
     * @param args the command line arguments
     * @throws CmdLineException
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void run_main(String[] args) throws CmdLineException, FileNotFoundException, IOException {
        CmdLineParser parser = new CmdLineParser(this);
        parser.parseArgument(args);

        if (arguments.size() != 1) {
            throw new CmdLineException("Only one log file can be captured");
        }
        for (String source : arguments) {
            if (one_time) {
                capture(source, 0.0);
            } else {
                capture(source, cycle_time);
            }
        }
    }

    /**
     * Captures an extract of a log file, reformats it and uploads it. <p>If
     * seconds is zero, this is run once.</p> <p>If seconds is non-zero, this is
     * the delay for repeat scheduling. Since a push takes almost 1 second, the
     * intervals need to be fairly long. </p>
     *
     * @param source Log File to capture, reformat and push.
     * @param seconds Scheduling interval in seconds. 0.0 means one-time-only.
     */
    public void capture(String source, double seconds) {
        worker.setSource_filename(source);
        worker.setExtract_filename(global.getProperty("capture.extract_filename", "hrtrtf.txt"));
        worker.setCsv_filename(global.getProperty("capture.csv_filename", "hrtrtf.csv"));
        if (seconds == 0.0) {
            timer.schedule(worker, 2 * 1000);
        } else {
            long interval = (long) seconds * 1000;
            long current = Calendar.getInstance().get(Calendar.SECOND);
            timer.scheduleAtFixedRate(worker, (60 - current) * 1000, interval);
        }
    }

    /**
     * TimerTask used to handle cycling log capture process.
     */
    class Tail_Format_Push extends TimerTask {

        Timer timer;
        String source_filename;
        String extract_filename;
        String csv_filename;

        public void setCsv_filename(String csv_filename) {
            this.csv_filename = csv_filename;
        }

        public void setExtract_filename(String extract_filename) {
            this.extract_filename = extract_filename;
        }

        public void setSource_filename(String source_filename) {
            this.source_filename = source_filename;
        }

        LogTail tail = new LogTail(global);
        Reformat reformat = new Reformat(global);
        CouchPush push = new CouchPush(global);

        Tail_Format_Push() {
            super();
        }

        /**
         * Run the timer task. <p> This performs the standard three-step
         * capture. </p> <ol> <li>LogTail</li> <li>Reformat</li>
         * <li>CouchPush</li> </ol>
         */
        @Override
        public void run() {
            try {
                String created = tail.tail(source_filename, extract_filename);

                if (created == null) {
                    return;
                }

                Reader extract = new FileReader(new File(created));
                File csv_file = new File(csv_filename);
                Writer wtr = new FileWriter(csv_file, false);
                reformat.include_header = true;
                try {
                    Object[] details = { extract_filename, csv_filename };
                    logger.info(MessageFormat.format("Reformatting {0} to {1}", details));

                    reformat.reformat(extract, wtr);
                } finally {
                    wtr.close();
                }

                logger.debug("About to push " + csv_filename);
                push.open();
                Document doc = push.push_feed(csv_file);
                if (doc == null) {
                    logger.error("Couch Push Failed.");
                    cancel();
                    return;
                }

            } catch (Exception ex) {
                logger.fatal("Worker Failed", ex);
                cancel();
                throw new Error(ex);
            }
        }
    }
}