com.opengamma.component.tool.AbstractTool.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.component.tool.AbstractTool.java

Source

/**
 * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.component.tool;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
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.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.component.ComponentManager;
import com.opengamma.financial.tool.ToolContext;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.StartupUtils;

/**
 * Abstract class for command line tools.
 * <p>
 * The command line tools generally require access to key parts of the infrastructure.
 * These are provided via {@link ToolContext} which is setup and closed by this class
 * using {@link ComponentManager}. Normally the file is named {@code toolcontext.ini}.
 *
 * @param <T> the tool context type
 */
public abstract class AbstractTool<T extends ToolContext> {

    /**
     * Logger.
     */
    private static final Logger s_logger = LoggerFactory.getLogger(AbstractTool.class);

    /**
     * Help command line option.
     */
    private static final String HELP_OPTION = "h";
    /**
     * Configuration command line option.
     */
    protected static final String CONFIG_RESOURCE_OPTION = "c";
    /**
     * Logging command line option.
     */
    private static final String LOGBACK_RESOURCE_OPTION = "l";

    static {
        StartupUtils.init();
    }

    /**
     * The command line.
     */
    private volatile CommandLine _commandLine;
    /**
     * The tool contexts.
     */
    private volatile T[] _toolContexts;

    /**
     * Initializes the tool statically.
     *
     * @param logbackResource the logback resource location, not null
     * @return true if successful
     */
    public static final boolean init(final String logbackResource) {
        return ToolUtils.initLogback(logbackResource);
    }

    /**
     * Creates an instance.
     */
    protected AbstractTool() {
    }

    //-------------------------------------------------------------------------
    /**
     * Initializes and runs the tool from standard command-line arguments.
     * <p>
     * The base class defined three options:<br />
     * c/config - the config file, mandatory<br />
     * l/logback - the logback configuration, default tool-logback.xml<br />
     * h/help - prints the help tool<br />
     *
     * @param args the command-line arguments, not null
     * @param toolContextClass the type of tool context to create, should match the generic type argument
     * @return true if successful, false otherwise
     */
    public boolean initAndRun(final String[] args, final Class<? extends T> toolContextClass) {
        return initAndRun(args, null, null, toolContextClass);
    }

    /**
     * Initializes and runs the tool from standard command-line arguments.
     * <p>
     * The base class defined three options:<br />
     * c/config - the config file, mandatory unless default specified<br />
     * l/logback - the logback configuration, default tool-logback.xml<br />
     * h/help - prints the help tool<br />
     *
     * @param args the command-line arguments, not null
     * @param defaultConfigResource the default configuration resource location, null if mandatory on command line
     * @param defaultLogbackResource the default logback resource, null to use tool-logback.xml as the default
     * @param toolContextClass the type of tool context to create, should match the generic type argument
     * @return true if successful, false otherwise
     */
    public boolean initAndRun(final String[] args, final String defaultConfigResource,
            final String defaultLogbackResource, final Class<? extends T> toolContextClass) {
        ArgumentChecker.notNull(args, "args");

        final Options options = createOptions(defaultConfigResource == null);
        final CommandLineParser parser = new PosixParser();
        CommandLine line;
        try {
            line = parser.parse(options, args);
        } catch (final ParseException e) {
            usage(options);
            return false;
        }
        _commandLine = line;
        if (line.hasOption(HELP_OPTION)) {
            usage(options);
            return true;
        }
        String logbackResource = line.getOptionValue(LOGBACK_RESOURCE_OPTION);
        logbackResource = StringUtils.defaultIfEmpty(logbackResource, ToolUtils.getDefaultLogbackConfiguration());
        String[] configResources = line.getOptionValues(CONFIG_RESOURCE_OPTION);
        if (configResources == null || configResources.length == 0) {
            configResources = new String[] { defaultConfigResource };
        }
        return init(logbackResource) && run(configResources, toolContextClass);
    }

    /**
     * Runs the tool.
     * <p>
     * This starts the tool context and calls {@link #run(ToolContext)}. This will catch exceptions and print a stack trace.
     *
     * @param configResource the config resource location, not null
     * @param toolContextClass the type of tool context to create, should match the generic type argument
     * @return true if successful
     */
    public final boolean run(final String configResource, final Class<? extends T> toolContextClass) {
        return run(new String[] { configResource }, toolContextClass);
    }

    /**
     * Runs the tool.
     * <p>
     * This starts the tool contexts and calls {@link #run(ToolContexts)}. This will catch exceptions and print a stack trace.
     *
     * @param configResources the config resource locations for multiple tool contexts, not null
     * @param toolContextClass the type of tool context to create, should match the generic type argument
     * @return true if successful
     */
    @SuppressWarnings("unchecked")
    public final boolean run(final String[] configResources, final Class<? extends T> toolContextClass) {
        ToolContext[] toolContexts = null;
        try {
            ArgumentChecker.notEmpty(configResources, "configResources");
            s_logger.info("Starting " + getClass().getSimpleName());
            toolContexts = new ToolContext[configResources.length];
            for (int i = 0; i < configResources.length; i++) {
                s_logger.info("Populating tool context " + (i + 1) + " of " + configResources.length + "...");
                toolContexts[i] = ToolContextUtils.getToolContext(configResources[i], toolContextClass);
            }
            s_logger.info("Running " + getClass().getSimpleName());
            run((T[]) toolContexts);
            s_logger.info("Finished " + getClass().getSimpleName());
            return true;
        } catch (final Exception ex) {
            s_logger.error("Caught exception", ex);
            ex.printStackTrace();
            return false;
        } finally {
            if (toolContexts != null) {
                for (final ToolContext toolContext : toolContexts) {
                    if (toolContext != null) {
                        try {
                            toolContext.close();
                        } catch (final Exception e) {
                            s_logger.error("Caught exception", e);
                        }
                    }
                }
            }
        }
    }

    /**
     * Runs the tool, calling {@code doRun}.
     * <p>
     * This will catch not handle exceptions, but will convert checked exceptions to unchecked.
     *
     * @param toolContext the tool context, not null
     * @throws RuntimeException if an error occurs
     */
    @SuppressWarnings("unchecked")
    public final void run(final T toolContext) {
        run((T[]) new ToolContext[] { toolContext });
    }

    /**
     * Runs the tool, calling {@code doRun}.
     * <p>
     * This will catch not handle exceptions, but will convert checked exceptions to unchecked.
     *
     * @param toolContexts the tool contexts, not null or empty
     * @throws RuntimeException if an error occurs
     */
    public final void run(final T[] toolContexts) {
        _toolContexts = toolContexts;
        try {
            doRun();
        } catch (final RuntimeException ex) {
            throw ex;
        } catch (final Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            _toolContexts = null;
        }
    }

    //-------------------------------------------------------------------------
    /**
     * Override in subclasses to implement the tool.
     *
     * @throws Exception if an error occurs
     */
    protected abstract void doRun() throws Exception;

    //-------------------------------------------------------------------------
    /**
     * Gets the (first) tool context.
     *
     * @return the context, not null during {@code doRun}
     */
    protected T getToolContext() {
        return getToolContext(0);
    }

    //-------------------------------------------------------------------------
    /**
     * Gets the i-th tool context.
     *
     * @param i the index of the tool context to retrieve
     * @return the i-th context, not null during {@code doRun}
     */
    protected T getToolContext(final int i) {
        ArgumentChecker.notNegative(i, "ToolContext index");
        if (getToolContexts().length > i) {
            return getToolContexts()[i];
        } else {
            throw new OpenGammaRuntimeException("ToolContext " + i + " does not exist");
        }
    }

    //-------------------------------------------------------------------------
    /**
     * Gets all tool contexts.
     *
     * @return the array of contexts, not null or empty during {@code doRun}
     */
    protected T[] getToolContexts() {
        return _toolContexts;
    }

    /**
     * Gets the parsed command line.
     *
     * @return the parsed command line, not null after parsing
     */
    protected CommandLine getCommandLine() {
        return _commandLine;
    }

    //-------------------------------------------------------------------------
    /**
     * Creates the command line options.
     * <p>
     * Subclasses may override this and add their own parameters. The base class defined the options h/help, c/config, l/logback.
     *
     * @param mandatoryConfigResource whether the config resource is mandatory
     * @return the set of command line options, not null
     */
    protected Options createOptions(final boolean mandatoryConfigResource) {
        final Options options = new Options();
        options.addOption(createHelpOption());
        options.addOption(createConfigOption(mandatoryConfigResource));
        options.addOption(createLogbackOption());
        return options;
    }

    private static Option createHelpOption() {
        return new Option(HELP_OPTION, "help", false, "prints this message");
    }

    private static Option createConfigOption(final boolean mandatoryConfigResource) {
        final Option option = new Option(CONFIG_RESOURCE_OPTION, "config", true,
                "the toolcontext configuration resource");
        option.setArgName("resource");
        option.setRequired(mandatoryConfigResource);
        return option;
    }

    private static Option createLogbackOption() {
        final Option option = new Option(LOGBACK_RESOURCE_OPTION, "logback", true,
                "the logback configuration resource");
        option.setArgName("resource");
        option.setRequired(false);
        return option;
    }

    protected Class<?> getEntryPointClass() {
        return getClass();
    }

    protected void usage(final Options options) {
        final HelpFormatter formatter = new HelpFormatter();
        formatter.setWidth(120);
        formatter.printHelp("java " + getEntryPointClass().getName(), options, true);
    }

}