org.prebake.client.Main.java Source code

Java tutorial

Introduction

Here is the source code for org.prebake.client.Main.java

Source

// Copyright 2010, Mike Samuel
//
// 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.prebake.client;

import org.prebake.channel.Commands;
import org.prebake.channel.FileNames;
import org.prebake.util.CommandLineArgs;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.io.File;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.ParametersAreNonnullByDefault;

/**
 * An executable class that wires the bake command to the file system and
 * network.
 *
 * @author Mike Samuel <mikesamuel@gmail.com>
 */
@ParametersAreNonnullByDefault
public final class Main {

    public static void main(String... argv) {
        long t0 = System.nanoTime();
        final Logger logger = Logger.getLogger(Main.class.getName());
        CommandLineArgs args = new CommandLineArgs(argv);
        if (!CommandLineArgs.setUpLogger(args, logger)) {
            System.out.println(USAGE);
            System.exit(0);
        }

        if (!args.getFlags().isEmpty()) {
            System.err.println(USAGE);
            if (!args.getFlags().isEmpty()) {
                System.err.println("Unused flags : " + Joiner.on(' ').join(args.getFlags()));
            }
            System.exit(-1);
        }

        Bake bake = new Bake(logger) {

            @Override
            protected Connection connect(int port) throws IOException {
                final Socket socket = new Socket(InetAddress.getLoopbackAddress(), port);
                return new Connection() {
                    public InputStream getInputStream() throws IOException {
                        return new FilterInputStream(socket.getInputStream()) {
                            @Override
                            public void close() throws IOException {
                                socket.shutdownInput();
                            }
                        };
                    }

                    public OutputStream getOutputStream() throws IOException {
                        return new FilterOutputStream(socket.getOutputStream()) {
                            @Override
                            public void close() throws IOException {
                                socket.shutdownOutput();
                            }
                        };
                    }

                    public void close() throws IOException {
                        socket.close();
                    }
                };
            }

            @Override
            protected void launch(Path prebakeDir, List<String> argv) throws IOException {
                Map<String, String> env = Maps.newLinkedHashMap();
                boolean doneWithPreJavaFlags = false;
                List<String> cmd = Lists.newArrayListWithCapacity(argv.size() + 1);
                cmd.add("java");
                for (String arg : argv) {
                    if (!doneWithPreJavaFlags && arg.startsWith("-Denv.")) {
                        // See PATH environment variable channeling in CommandLineArgs
                        int eq = arg.indexOf('=');
                        env.put(arg.substring(6, eq).toUpperCase(Locale.ROOT), arg.substring(eq + 1));
                    } else {
                        cmd.add(arg);
                    }
                    if (!arg.startsWith("-")) {
                        doneWithPreJavaFlags = true;
                    }
                }
                File logFile = new File(prebakeDir.resolve(FileNames.LOGS).resolve("main.log").toUri());
                logger.log(Level.INFO, "Execing {0} with env {1} > {2}", new Object[] { cmd, env, logFile });
                ProcessBuilder pb = new ProcessBuilder(cmd.toArray(new String[0]));
                pb.environment().putAll(env);
                pb.redirectOutput(logFile).redirectErrorStream(true).start();
            }

            @Override
            protected void sleep(int millis) throws InterruptedException {
                Thread.sleep(millis);
            }
        };
        Path cwd = FileSystems.getDefault().getPath(System.getProperty("user.dir"));
        int result;
        try {
            Path prebakeDir = bake.findPrebakeDir(cwd);
            Collection<String> argVals = args.getValues();
            Commands commands = bake.decodeArgv(prebakeDir.getParent(),
                    argVals.toArray(new String[argVals.size()]));
            result = bake.issueCommands(prebakeDir, commands, System.out);
        } catch (IOException ex) {
            ex.printStackTrace();
            result = -1;
        }
        logger.log(Level.INFO, "Build took {0}.", prettyTime(System.nanoTime() - t0));
        System.exit(result);
    }

    public static final String USAGE = ("" + "bake [-v | -vv | -q | -qq | --logLevel=<level>]\n" + "\n"
            + "    -qq         extra quiet : errors only\n" + "    -q          quiet : warnings and errors only\n"
            + "    -v          verbose\n" + "    -vv         extra verbose\n"
            + "    --logLevel  see java.util.logging.Level for value names");

    private static final long NANOSECS_PER_SEC = 1000 * 1000 * 1000;

    /** 94,000,000,000 ns => "1 minute, 34 seconds" */
    private static CharSequence prettyTime(long nanos) {
        StringBuilder sb = new StringBuilder();
        long seconds = nanos / NANOSECS_PER_SEC;
        long minutes = seconds / 60;
        seconds -= minutes * 60;
        if (minutes != 0) {
            if (minutes == 1) {
                sb.append("1 minute");
            } else {
                sb.append(minutes).append(" minutes");
            }
        }
        if (seconds != 0 || sb.length() == 0) {
            if (sb.length() != 0) {
                sb.append(", ");
            }
            if (seconds == 1) {
                sb.append("1 second");
            } else {
                sb.append(seconds).append(" seconds");
            }
        }
        return sb;
    }
}