com.asakusafw.compiler.bootstrap.BatchCompilerDriver.java Source code

Java tutorial

Introduction

Here is the source code for com.asakusafw.compiler.bootstrap.BatchCompilerDriver.java

Source

/**
 * Copyright 2011-2017 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.compiler.bootstrap;

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.List;

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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.asakusafw.compiler.batch.BatchDriver;
import com.asakusafw.compiler.flow.FlowCompilerOptions;
import com.asakusafw.compiler.flow.Location;
import com.asakusafw.compiler.testing.DirectBatchCompiler;
import com.asakusafw.vocabulary.batch.BatchDescription;

/**
 * Program entry for compiling a batch class.
 * @see AllBatchCompilerDriver
 */
public final class BatchCompilerDriver {

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

    private static final Option OPT_OUTPUT;
    private static final Option OPT_PACKAGE;
    private static final Option OPT_HADOOPWORK;
    private static final Option OPT_COMPILERWORK;
    private static final Option OPT_LINK;
    private static final Option OPT_PLUGIN;
    private static final Option OPT_CLASS;

    private static final Options OPTIONS;
    static {
        OPT_OUTPUT = new Option("output", true, //$NON-NLS-1$
                Messages.getString("BatchCompilerDriver.optOutput")); //$NON-NLS-1$
        OPT_OUTPUT.setArgName("/path/to/output"); //$NON-NLS-1$
        OPT_OUTPUT.setValueSeparator(File.pathSeparatorChar);
        OPT_OUTPUT.setRequired(true);

        OPT_PACKAGE = new Option("package", true, //$NON-NLS-1$
                Messages.getString("BatchCompilerDriver.optPackage")); //$NON-NLS-1$
        OPT_PACKAGE.setArgName("pkg.name"); //$NON-NLS-1$
        OPT_PACKAGE.setRequired(true);

        OPT_HADOOPWORK = new Option("hadoopwork", true, //$NON-NLS-1$
                Messages.getString("BatchCompilerDriver.optHadoopwork")); //$NON-NLS-1$
        OPT_HADOOPWORK.setArgName("batch/working"); //$NON-NLS-1$
        OPT_HADOOPWORK.setRequired(true);

        OPT_COMPILERWORK = new Option("compilerwork", true, //$NON-NLS-1$
                Messages.getString("BatchCompilerDriver.optCompilerwork")); //$NON-NLS-1$
        OPT_COMPILERWORK.setArgName("/path/to/temporary"); //$NON-NLS-1$
        OPT_COMPILERWORK.setRequired(false);

        OPT_LINK = new Option("link", true, //$NON-NLS-1$
                Messages.getString("BatchCompilerDriver.optLink")); //$NON-NLS-1$
        OPT_LINK.setArgName("classlib.jar" + File.pathSeparatorChar + "/path/to/classes"); //$NON-NLS-1$ //$NON-NLS-2$

        OPT_PLUGIN = new Option("plugin", true, //$NON-NLS-1$
                Messages.getString("BatchCompilerDriver.optPlugin")); //$NON-NLS-1$
        OPT_PLUGIN.setArgName("plugin-1.jar" + File.pathSeparatorChar + "plugin-2.jar"); //$NON-NLS-1$ //$NON-NLS-2$
        OPT_PLUGIN.setRequired(false);

        OPT_CLASS = new Option("class", true, //$NON-NLS-1$
                Messages.getString("BatchCompilerDriver.optClass")); //$NON-NLS-1$
        OPT_CLASS.setArgName("class-name"); //$NON-NLS-1$
        OPT_CLASS.setRequired(true);

        OPTIONS = new Options();
        OPTIONS.addOption(OPT_OUTPUT);
        OPTIONS.addOption(OPT_PACKAGE);
        OPTIONS.addOption(OPT_HADOOPWORK);
        OPTIONS.addOption(OPT_COMPILERWORK);
        OPTIONS.addOption(OPT_LINK);
        OPTIONS.addOption(OPT_PLUGIN);
        OPTIONS.addOption(OPT_CLASS);
    }

    /**
     * The program entry.
     * @param args command line arguments
     */
    public static void main(String... args) {
        try {
            if (start(args) == false) {
                System.exit(1);
            }
        } catch (Exception e) {
            HelpFormatter formatter = new HelpFormatter();
            formatter.setWidth(Integer.MAX_VALUE);
            formatter.printHelp(MessageFormat.format("java -classpath ... {0}", //$NON-NLS-1$
                    BatchCompilerDriver.class.getName()), OPTIONS, true);
            e.printStackTrace(System.out);
            System.exit(1);
        }
    }

    private static boolean start(String[] args) throws Exception {
        CommandLineParser parser = new BasicParser();
        CommandLine cmd = parser.parse(OPTIONS, args);
        String output = cmd.getOptionValue(OPT_OUTPUT.getOpt());
        String className = cmd.getOptionValue(OPT_CLASS.getOpt());
        String packageName = cmd.getOptionValue(OPT_PACKAGE.getOpt());
        String hadoopWork = cmd.getOptionValue(OPT_HADOOPWORK.getOpt());
        String compilerWork = cmd.getOptionValue(OPT_COMPILERWORK.getOpt());
        String link = cmd.getOptionValue(OPT_LINK.getOpt());
        String plugin = cmd.getOptionValue(OPT_PLUGIN.getOpt());

        File outputDirectory = new File(output);
        Location hadoopWorkLocation = Location.fromPath(hadoopWork, '/');
        File compilerWorkDirectory = new File(compilerWork);
        List<File> linkingResources = new ArrayList<>();
        if (link != null) {
            for (String s : link.split(File.pathSeparator)) {
                linkingResources.add(new File(s));
            }
        }
        List<URL> pluginLocations = new ArrayList<>();
        if (plugin != null) {
            for (String s : plugin.split(File.pathSeparator)) {
                if (s.trim().isEmpty()) {
                    continue;
                }
                try {
                    File file = new File(s);
                    if (file.exists() == false) {
                        throw new FileNotFoundException(file.getAbsolutePath());
                    }
                    URL url = file.toURI().toURL();
                    pluginLocations.add(url);
                } catch (IOException e) {
                    LOG.warn(MessageFormat.format(Messages.getString("BatchCompilerDriver.warnFailedToLoadPlugin"), //$NON-NLS-1$
                            s), e);
                }
            }
        }

        Class<? extends BatchDescription> batchDescription = Class.forName(className)
                .asSubclass(BatchDescription.class);
        boolean succeeded = compile(outputDirectory, batchDescription, packageName, hadoopWorkLocation,
                compilerWorkDirectory, linkingResources, pluginLocations);

        if (succeeded) {
            LOG.info(MessageFormat.format(Messages.getString("BatchCompilerDriver.infoComplete"), //$NON-NLS-1$
                    batchDescription.getName()));
        }
        return succeeded;
    }

    static boolean compile(File outputDirectory, Class<? extends BatchDescription> batchDescription,
            String packageName, Location hadoopWorkLocation, File compilerWorkDirectory,
            List<File> linkingResources, List<URL> pluginLibraries) {
        assert outputDirectory != null;
        assert batchDescription != null;
        assert packageName != null;
        assert hadoopWorkLocation != null;
        assert compilerWorkDirectory != null;
        assert linkingResources != null;
        try {
            BatchDriver analyzed = BatchDriver.analyze(batchDescription);
            if (analyzed.hasError()) {
                for (String diagnostic : analyzed.getDiagnostics()) {
                    LOG.error(diagnostic);
                }
                return false;
            }

            String batchId = analyzed.getBatchClass().getConfig().name();
            ClassLoader serviceLoader = AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> {
                URLClassLoader loader = new URLClassLoader(pluginLibraries.toArray(new URL[pluginLibraries.size()]),
                        BatchCompilerDriver.class.getClassLoader());
                return loader;
            });
            DirectBatchCompiler.compile(analyzed.getDescription(), packageName, hadoopWorkLocation,
                    new File(outputDirectory, batchId), new File(compilerWorkDirectory, batchId), linkingResources,
                    serviceLoader, FlowCompilerOptions.load(System.getProperties()));
            return true;
        } catch (Exception e) {
            LOG.error(MessageFormat.format(Messages.getString("BatchCompilerDriver.errorFailedToCompile"), //$NON-NLS-1$
                    batchDescription.getName()), e);
            return false;
        }
    }

    private BatchCompilerDriver() {
        return;
    }
}