Package com.asakusafw.directio.hive.tools.cli

Source Code of com.asakusafw.directio.hive.tools.cli.GenerateCreateTable

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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 com.asakusafw.directio.hive.tools.cli;

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.apache.commons.cli.BasicParser;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.asakusafw.directio.hive.common.HiveTableInfo;

/**
* Program entry for generate Hive QL {@code CREATE TABLE} statements.
* @since 0.7.0
*/
public final class GenerateCreateTable {

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

    static final Option OPT_LOCATION;
    static final Option OPT_DATABASE;
    static final Option OPT_INCLUDE;
    static final Option OPT_CLASSPATH;
    static final Option OPT_PLUGINPATH;
    static final Option OPT_OUTPUT;
    static final Options OPTIONS;

    static {
        OPT_LOCATION = new Option("l", "location", true, "table output location"); //$NON-NLS-1$ //$NON-NLS-2$
        OPT_LOCATION.setArgName("URI");
        OPT_LOCATION.setRequired(false);

        OPT_DATABASE = new Option("db", "database", true, "table database name"); //$NON-NLS-1$ //$NON-NLS-2$
        OPT_DATABASE.setArgName("dbname");
        OPT_DATABASE.setRequired(false);

        OPT_INCLUDE = new Option("i", "include", true, "include table name regex"); //$NON-NLS-1$ //$NON-NLS-2$
        OPT_INCLUDE.setArgName("regex");
        OPT_INCLUDE.setRequired(false);

        OPT_CLASSPATH = new Option("cp", "classpath", true, "classpath"); //$NON-NLS-1$ //$NON-NLS-2$
        OPT_CLASSPATH.setArgName("/path/to/classes[" + File.pathSeparator + "...]");
        OPT_CLASSPATH.setRequired(true);

        OPT_PLUGINPATH = new Option("pp", "pluginpath", true, "pluginpath"); //$NON-NLS-1$ //$NON-NLS-2$
        OPT_PLUGINPATH.setArgName("/path/to/plugin.jar[" + File.pathSeparator + "...]");
        OPT_PLUGINPATH.setRequired(false);

        OPT_OUTPUT = new Option("o", "output", true, "output file path"); //$NON-NLS-1$ //$NON-NLS-2$
        OPT_OUTPUT.setArgName("/path/to/output-file");
        OPT_OUTPUT.setRequired(true);

        OPTIONS = new Options();
        OPTIONS.addOption(OPT_LOCATION);
        OPTIONS.addOption(OPT_DATABASE);
        OPTIONS.addOption(OPT_INCLUDE);
        OPTIONS.addOption(OPT_CLASSPATH);
        OPTIONS.addOption(OPT_PLUGINPATH);
        OPTIONS.addOption(OPT_OUTPUT);
    }

    private GenerateCreateTable() {
        return;
    }

    /**
     * The program entry.
     * @param args class-paths... output-file
     * @throws IOException if failed by I/O error
     */
    public static void main(String[] args) throws IOException {
        int exit = execute(args);
        if (exit != 0) {
            System.exit(exit);
        }
    }

    static int execute(String... args) {
        GenerateCreateTableTask task = new GenerateCreateTableTask();
        GenerateCreateTableTask.Configuration conf;
        try {
            conf = parseConfiguration(args);
        } catch (Exception e) {
            LOG.error("Failed to initialize application", e);
            HelpFormatter formatter = new HelpFormatter();
            formatter.setWidth(Integer.MAX_VALUE);
            formatter.printHelp(
                    MessageFormat.format(
                            "java -classpath ... {0}", //$NON-NLS-1$
                            GenerateCreateTable.class.getName()),
                    OPTIONS,
                    true);
            return 1;
        }
        try {
            task.perform(conf);
        } catch (Exception e) {
            LOG.error("Failed to reverse-engineer", e);
            return 1;
        } finally {
            closeQuiet(conf.classLoader);
        }
        return 0;
    }

    static GenerateCreateTableTask.Configuration parseConfiguration(String... args) throws ParseException {
        LOG.debug("Analyzing arguments: {}", Arrays.toString(args));

        CommandLineParser parser = new BasicParser();
        CommandLine cmd = parser.parse(OPTIONS, args);
        String classpath = getOption(cmd, OPT_CLASSPATH);
        String pluginpath = getOption(cmd, OPT_PLUGINPATH);
        String output = getOption(cmd, OPT_OUTPUT);
        String include = getOption(cmd, OPT_INCLUDE);
        String location = getOption(cmd, OPT_LOCATION);
        String database = getOption(cmd, OPT_DATABASE);

        List<File> sources = parseFileList(classpath);
        List<File> plugins = parseFileList(pluginpath);
        List<File> classpathAdditions = new ArrayList<File>();
        classpathAdditions.addAll(sources);
        classpathAdditions.addAll(plugins);

        Pattern acceptTableNames = null;
        if (include != null) {
            try {
                acceptTableNames = Pattern.compile(include);
            } catch (PatternSyntaxException e) {
                throw new IllegalArgumentException(MessageFormat.format(
                        "Invalid regex (--{0}): {1}",
                        OPT_INCLUDE.getLongOpt(),
                        include));
            }
        }

        Stringnizer locationProvider = null;
        if (location != null) {
            final String prefix = location.endsWith("/") ? location : location + '/';
            locationProvider = new Stringnizer() {
                @Override
                public String toString(HiveTableInfo table) {
                    return prefix + table.getTableName();
                }
            };
        }

        if (database != null) {
            database = database.trim();
            if (database.isEmpty()) {
                database = null;
            }
        }
        File outputFile = new File(output);
        URLClassLoader classLoader = buildPluginLoader(
                GenerateCreateTable.class.getClassLoader(),
                classpathAdditions);
        return new GenerateCreateTableTask.Configuration(
                classLoader,
                sources,
                acceptTableNames,
                locationProvider,
                database,
                outputFile);
    }

    private static String getOption(CommandLine cmd, Option option) {
        String value = cmd.getOptionValue(option.getOpt());
        LOG.debug("Option: {}={}", option.getLongOpt(), value);
        return value;
    }

    /**
     * Parses a string of file list separated by the platform dependent path separator.
     * @param fileListOrNull target string, or {@code null}
     * @return the represented file list, or an empty list if not specified
     */
    private static List<File> parseFileList(String fileListOrNull) {
        if (fileListOrNull == null || fileListOrNull.isEmpty()) {
            return Collections.emptyList();
        }
        List<File> results = new ArrayList<File>();
        int start = 0;
        while (true) {
            int index = fileListOrNull.indexOf(File.pathSeparatorChar, start);
            if (index < 0) {
                break;
            }
            if (start != index) {
                results.add(new File(fileListOrNull.substring(start, index).trim()));
            }
            start = index + 1;
        }
        results.add(new File(fileListOrNull.substring(start).trim()));
        return results;
    }

    /**
     * Creates a class loader for loading plug-ins.
     * @param parent parent class loader, or {@code null} to use the system class loader
     * @param files plug-in class paths (*.jar file or class path directory)
     * @return the created class loader
     * @throws IllegalArgumentException if some parameters were {@code null}
     */
    private static URLClassLoader buildPluginLoader(final ClassLoader parent, List<File> files) {
        if (files == null) {
            throw new IllegalArgumentException("files must not be null"); //$NON-NLS-1$
        }
        final List<URL> locations = new ArrayList<URL>();
        for (File file : files) {
            try {
                if (file.exists() == false) {
                    throw new FileNotFoundException(MessageFormat.format(
                            "Plug-in file/directory is not found \"{0}\"",
                            file.getAbsolutePath()));
                }
                URL url = file.toURI().toURL();
                locations.add(url);
            } catch (IOException e) {
                LOG.warn(MessageFormat.format(
                        "Failed to detect plug-in file/directory: {0}",
                        file.getAbsolutePath()), e);
            }
        }
        return AccessController.doPrivileged(new PrivilegedAction<URLClassLoader>() {
            @Override
            public URLClassLoader run() {
                return new URLClassLoader(
                        locations.toArray(new URL[locations.size()]),
                        parent);
            }
        });
    }

    private static void closeQuiet(Object object) {
        if (object instanceof Closeable) {
            try {
                ((Closeable) object).close();
            } catch (IOException e) {
                LOG.warn(MessageFormat.format(
                        "Failed to close object: {0}",
                        object), e);
            }
        }
    }
}
TOP

Related Classes of com.asakusafw.directio.hive.tools.cli.GenerateCreateTable

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.