org.finra.herd.tools.common.databridge.DataBridgeApp.java Source code

Java tutorial

Introduction

Here is the source code for org.finra.herd.tools.common.databridge.DataBridgeApp.java

Source

/*
* Copyright 2015 herd contributors
*
* 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.finra.herd.tools.common.databridge;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.finra.herd.core.ApplicationContextHolder;
import org.finra.herd.core.ArgumentParser;
import org.finra.herd.core.config.CoreSpringModuleConfig;
import org.finra.herd.model.api.xml.BuildInformation;
import org.finra.herd.tools.common.ToolsCommonConstants;
import org.finra.herd.tools.common.config.DataBridgeAopSpringModuleConfig;
import org.finra.herd.tools.common.config.DataBridgeEnvSpringModuleConfig;
import org.finra.herd.tools.common.config.DataBridgeSpringModuleConfig;

/**
 * A base class for the uploader and downloader applications. This class is abstract since it is not an actual application that has a main method, but rather
 * provides common base functionality that should be used by an extending class.
 */
public abstract class DataBridgeApp {
    public static final String BUILD_INFO_STRING_FORMAT = "buildDate: %s\nbuildNumber: %s\nbuildOS: %s\nbuildUser: %s";

    private static final Logger LOGGER = LoggerFactory.getLogger(DataBridgeApp.class);

    protected Option s3AccessKeyOpt;

    protected Option s3SecretKeyOpt;

    protected Option s3EndpointOpt;

    protected Option localPathOpt;

    protected Option manifestPathOpt;

    protected Option regServerHostOpt;

    protected Option regServerPortOpt;

    protected Option dmRegServerHostOpt;

    protected Option dmRegServerPortOpt;

    protected Option sslOpt;

    protected Option usernameOpt;

    protected Option passwordOpt;

    protected Option trustSelfSignedCertificateOpt;

    protected Option disableHostnameVerificationOpt;

    protected Option helpOpt;

    protected Option versionOpt;

    protected Option httpProxyHostOpt;

    protected Option httpProxyPortOpt;

    protected Option maxThreadsOpt;

    protected Option socketTimeoutOpt;

    // Boolean value for useSsl command line option that is of type "Boolean".
    protected Boolean useSsl;

    // Boolean value for trustSelfSignedCertificate command line option that is of type "Boolean".
    protected Boolean trustSelfSignedCertificate;

    // Boolean value for disableHostnameVerification command line option that is of type "Boolean".
    protected Boolean disableHostnameVerification;

    // Integer value for regServerPort command line option that is of type "Integer".
    protected Integer regServerPort;

    // Integer value for httpProxyPort command line option that is of type "Integer".
    protected Integer httpProxyPort;

    // Integer value for maxThreads command line option that is of type "Integer".
    protected Integer maxThreads;

    // The registration server hostname.
    protected String regServerHost;

    /**
     * The list of possible return values for the application.
     */
    public enum ReturnValue {
        SUCCESS(0), FAILURE(1);

        private int returnCode;

        private ReturnValue(int returnCode) {
            this.returnCode = returnCode;
        }

        public int getReturnCode() {
            return returnCode;
        }
    }

    /**
     * Gets the application argument parser.
     *
     * @return the argument parser.
     */
    public abstract ArgumentParser getArgumentParser();

    /**
     * Runs the application. This is the main entry into the application class itself and is typically called from a main method.
     *
     * @param args the command line arguments.
     *
     * @return the application return value.
     * @throws Exception if any problems were encountered.
     */
    public abstract ReturnValue go(String[] args) throws Exception;

    /**
     * Parses the command line arguments using the specified argument parser. Common data bridge options will be initialized and added to the argument parser in
     * this method, but any application specific arguments should be added to the argument parser prior to calling this method. Ensure the argParser was set in
     * this class prior to calling this method.
     *
     * @param args the command line arguments.
     * @param applicationContext the Spring application context.
     *
     * @return the return value if the application should exit or null if the application can continue.
     */
    // Using System.out to inform user of usage or version information is okay.
    @SuppressWarnings("PMD.SystemPrintln")
    @SuppressFBWarnings(value = "VA_FORMAT_STRING_USES_NEWLINE", justification = "We will use the standard carriage return character.")
    protected ReturnValue parseCommandLineArguments(String[] args, ApplicationContext applicationContext) {
        // Get the application argument parser.
        ArgumentParser argParser = getArgumentParser();

        try {
            s3AccessKeyOpt = argParser.addArgument("a", "s3AccessKey", true, "S3 access key.", false);
            s3SecretKeyOpt = argParser.addArgument("p", "s3SecretKey", true, "S3 secret key.", false);
            s3EndpointOpt = argParser.addArgument("e", "s3Endpoint", true, "S3 endpoint.", false);
            localPathOpt = argParser.addArgument("l", "localPath", true,
                    "The path to files on your local file system.", true);
            manifestPathOpt = argParser.addArgument("m", "manifestPath", true, "Local path to the manifest file.",
                    true);
            regServerHostOpt = argParser.addArgument("H", "regServerHost", true, "Registration Service hostname.",
                    false);
            regServerPortOpt = argParser.addArgument("P", "regServerPort", true, "Registration Service port.",
                    false);
            dmRegServerHostOpt = argParser.addArgument("Y", "dmRegServerHost", true,
                    "Registration Service hostname (deprecated - use regServerHost).", false);
            dmRegServerPortOpt = argParser.addArgument("Z", "dmRegServerPort", true,
                    "Registration Service port (deprecated - use regServerPort.", false);
            sslOpt = argParser.addArgument("s", "ssl", true, "Enable or disable SSL (HTTPS).", false);
            usernameOpt = argParser.addArgument("u", "username", true,
                    "The username for HTTPS client authentication.", false);
            passwordOpt = argParser.addArgument("w", "password", true,
                    "The password used for HTTPS client authentication.", false);
            trustSelfSignedCertificateOpt = argParser.addArgument("C", "trustSelfSignedCertificate", true,
                    "If set to true, makes HTTPS client trust self-signed certificate.", false);
            disableHostnameVerificationOpt = argParser.addArgument("d", "disableHostnameVerification", true,
                    "If set to true, turns off hostname verification.", false);
            helpOpt = argParser.addArgument("h", "help", false, "Display usage information and exit.", false);
            versionOpt = argParser.addArgument("v", "version", false, "Display version information and exit.",
                    false);
            httpProxyHostOpt = argParser.addArgument("n", "httpProxyHost", true, "HTTP proxy host.", false);
            httpProxyPortOpt = argParser.addArgument("o", "httpProxyPort", true, "HTTP proxy port.", false);
            maxThreadsOpt = argParser.addArgument("t", "maxThreads", true, "Maximum number of threads.", false);
            socketTimeoutOpt = argParser.addArgument("c", "socketTimeout", true,
                    "The socket timeout in milliseconds. 0 indicates no timeout. Default 50000.", false);

            // Parse command line arguments without failing on any missing required arguments by passing "false" as the second argument.
            argParser.parseArguments(args, false);

            // If help option was specified, then display usage information and return success.
            if (argParser.getBooleanValue(helpOpt)) {
                System.out.println(argParser.getUsageInformation());
                return ReturnValue.SUCCESS;
            }

            // If version option was specified, then display version information and return success.
            if (argParser.getBooleanValue(versionOpt)) {
                BuildInformation buildInformation = applicationContext.getBean(BuildInformation.class);
                System.out.println(String.format(BUILD_INFO_STRING_FORMAT, buildInformation.getBuildDate(),
                        buildInformation.getBuildNumber(), buildInformation.getBuildOs(),
                        buildInformation.getBuildUser()));
                return ReturnValue.SUCCESS;
            }

            // Parse command line arguments for the second time, enforcing the required arguments by passing "true" as the second argument.
            argParser.parseArguments(args, true);

            // Extract boolean option values passing "false" as a default value.
            useSsl = argParser.getStringValueAsBoolean(sslOpt, false);
            trustSelfSignedCertificate = argParser.getStringValueAsBoolean(trustSelfSignedCertificateOpt, false);
            disableHostnameVerification = argParser.getStringValueAsBoolean(disableHostnameVerificationOpt, false);

            // Username and password are required when useSsl is enabled.
            if (useSsl && (StringUtils.isBlank(argParser.getStringValue(usernameOpt))
                    || StringUtils.isBlank(argParser.getStringValue(passwordOpt)))) {
                throw new ParseException("Username and password are required when SSL is enabled.");
            }

            // Ensure that both the S3 secret and access keys were specified or both not specified.
            if (StringUtils.isNotBlank(argParser.getStringValue(s3SecretKeyOpt))
                    && StringUtils.isBlank(argParser.getStringValue(s3AccessKeyOpt))) {
                throw new ParseException("S3 access key must be specified when S3 secret key is present.");
            }
            if (StringUtils.isNotBlank(argParser.getStringValue(s3AccessKeyOpt))
                    && StringUtils.isBlank(argParser.getStringValue(s3SecretKeyOpt))) {
                throw new ParseException("S3 secret key must be specified when S3 access key is present.");
            }

            // Get the registration server host
            regServerHost = argParser.getStringValue(regServerHostOpt);
            if (StringUtils.isBlank(regServerHost)) {
                regServerHost = argParser.getStringValue(dmRegServerHostOpt);
                if (StringUtils.isBlank(regServerHost)) {
                    throw new ParseException("A registration host must be specified.");
                }
            } else {
                if (StringUtils.isNotBlank(argParser.getStringValue(dmRegServerHostOpt))) {
                    throw new ParseException(
                            "The regServerHost and the dmRegServerHost options can't both be specified.");
                }
            }

            // Get the registration server port
            regServerPort = argParser.getIntegerValue(regServerPortOpt);
            if (regServerPort == null) {
                regServerPort = argParser.getIntegerValue(dmRegServerPortOpt);
                if (regServerPort == null) {
                    throw new ParseException("A registration port must be specified.");
                }
            } else {
                if (argParser.getIntegerValue(dmRegServerPortOpt) != null) {
                    throw new ParseException(
                            "The regServerPort and the dmRegServerPort options can't both be specified.");
                }
            }

            // Extract all Integer option values here to catch any NumberFormatException exceptions.
            httpProxyPort = argParser.getIntegerValue(httpProxyPortOpt);
            maxThreads = argParser.getIntegerValue(maxThreadsOpt, ToolsCommonConstants.DEFAULT_THREADS);
        } catch (ParseException ex) {
            // Log a friendly error and return a failure which will cause the application to exit.
            LOGGER.error("Error parsing command line arguments: " + ex.getMessage() + "\n"
                    + argParser.getUsageInformation());
            return ReturnValue.FAILURE;
        }

        // The command line arguments were all parsed successfully so return null to continue processing.
        return null;
    }

    /**
     * Creates and returns the Spring application context.
     *
     * @return the application context
     */
    protected ApplicationContext createApplicationContext() {
        // Create the Spring application context and register the JavaConfig classes we need.
        // We will use core (in case it's needed), the service aspect that times the duration of the service method calls, and our specific beans defined in
        // the data bridge configuration. We're not including full service and DAO configurations because they come with database/data source dependencies
        // that we don't need and don't want (i.e. we don't want the database to be running as a pre-requisite for running the uploader).
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        ApplicationContextHolder.setApplicationContext(applicationContext);
        applicationContext.register(CoreSpringModuleConfig.class, DataBridgeSpringModuleConfig.class,
                DataBridgeAopSpringModuleConfig.class, DataBridgeEnvSpringModuleConfig.class);
        applicationContext.refresh();
        return applicationContext;
    }
}