com.github.dirkraft.jash.AbstractBundler.java Source code

Java tutorial

Introduction

Here is the source code for com.github.dirkraft.jash.AbstractBundler.java

Source

/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Jason Dunkelberger (dirkraft)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.github.dirkraft.jash;

import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.FileOptionHandler;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractBundler implements JashCommand {

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Command options

    @Argument(metaVar = "command name")
    public String commandName;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Daemon options

    @Option(name = "-h", aliases = "--daemon-host")
    public String daemonHost = "localhost";

    @Option(name = "-p", aliases = "--daemon-port")
    public int daemonPort = 47474;

    // TODO use a respectable parser, e.g. 1h30m (1 hour 30 minutes); 90s (90 seconds), 1d (1 day)
    @Option(name = "-i", aliases = "--daemon-idle")
    public String daemonIdle = "1h";

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Build options

    @Option(name = "-o", aliases = "--output-dir", handler = FileOptionHandler.class)
    // This is a bit silly to have an extra dir, but in the case the user downloaded the jasher cli (rather
    // than use the gradle plugin), output to similar build directory path.
    public File outputDir = new File("build/jasher/");

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // internal build state

    protected File _renderedScriptFile;

    public List<String> validateAndInit() throws Exception {
        List<String> errors = new ArrayList<>();
        if (outputDir.isFile()) {
            errors.add(outputDir.getAbsolutePath() + " exists and is a file. Cannot output here. "
                    + "Should either be a directory or not exist (which would be automatically created).");
        }
        return errors;
    }

    @Override
    public void run(Object cli) throws Exception {
        String renderedScript = namespaceScript(renderScript());
        JashIO.outf("Rendered jash.bash script %n");
        writeScript(renderedScript);
        JashIO.outf("Wrote rendered jash.bash script to %s%n", _renderedScriptFile.getAbsolutePath());
    }

    @Override
    public String complete(Object cli) throws Exception {
        return "";
    }

    String renderScript() {
        String script = readClasspathResource("jash.bash");
        script = script.replaceFirst("_JASH_COMMAND_NAME=.*", "_JASH_COMMAND_NAME=" + commandName);

        final String resolvedBindAddr;
        try {
            URI uri = new URI(daemonHost);
            String scheme = uri.getScheme();
            if (Strings.isNullOrEmpty(scheme)) {
                scheme = "http";
            }
            String host = uri.getHost();
            if (Strings.isNullOrEmpty(host)) {
                host = "localhost";
            }
            int port = uri.getPort();
            if (port == -1) {
                port = this.daemonPort;
            }

            resolvedBindAddr = new URI(scheme, null, host, port, null, null, null).toString();

        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }

        script = script.replaceFirst("_JASH_SERVER=.*", "_JASH_SERVER=" + resolvedBindAddr);

        return script;
    }

    void writeScript(String script) {
        boolean ignored = outputDir.mkdirs();
        Path outputDirPath = outputDir.toPath();
        if (!Files.isDirectory(outputDirPath) || !Files.isWritable(outputDirPath)) {
            throw new RuntimeException("Unable to prepare and write to " + outputDir.getAbsolutePath());
        }

        Path scriptPath = outputDirPath.resolve(commandName + ".bash");
        try {
            File scriptFile = scriptPath.toFile();
            com.google.common.io.Files.write(script, scriptFile, Charsets.UTF_8);
            boolean setExecutable = scriptFile.setExecutable(true);
            if (!setExecutable) {
                JashIO.errf("Warning: Failed to set execute bit on %s%n", scriptFile.getAbsolutePath());
            }

            this._renderedScriptFile = scriptFile;

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    String namespaceScript(String commonBash) {
        String underscored = '_' + commandName.replace('-', '_');
        // The leading _ indicates things that need namespacing.
        return commonBash.replace("_JASH", underscored.toUpperCase()).replace("_jash", underscored.toLowerCase());
    }

    static String readClasspathResource(String classpathRes) {
        try {
            return CharStreams.toString(
                    new InputStreamReader(Resources.getResource(classpathRes).openStream(), Charsets.UTF_8));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String toString() {
        return "commandName='" + commandName + '\'' + ", daemonHost='" + daemonHost + '\'' + ", daemonPort="
                + daemonPort + ", daemonIdle='" + daemonIdle + '\'' + ", outputDir=" + outputDir;
    }
}