Launcher.java 4.8 KB
Newer Older
K
kohsuke 已提交
1 2
package hudson;

K
kohsuke 已提交
3
import hudson.model.Hudson;
K
kohsuke 已提交
4
import hudson.model.TaskListener;
K
kohsuke 已提交
5 6
import hudson.remoting.VirtualChannel;
import hudson.Proc.LocalProc;
K
kohsuke 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * Starts a process.
 *
 * <p>
 * This hides the difference between running programs locally vs remotely.
 *
 *
 * <h2>'env' parameter</h2>
 * <p>
 * To allow important environment variables to be copied over to the remote machine,
K
kohsuke 已提交
25
 * the 'env' parameter shouldn't contain default inherited environment variables
K
kohsuke 已提交
26 27 28 29 30 31 32 33
 * (which often contains machine-specific information, like PATH, TIMEZONE, etc.)
 *
 * <p>
 * {@link Launcher} is responsible for inheriting environment variables.
 *
 *
 * @author Kohsuke Kawaguchi
 */
K
kohsuke 已提交
34
public abstract class Launcher {
K
kohsuke 已提交
35 36 37

    protected final TaskListener listener;

K
kohsuke 已提交
38 39 40
    protected final VirtualChannel channel;

    public Launcher(TaskListener listener, VirtualChannel channel) {
K
kohsuke 已提交
41
        this.listener = listener;
K
kohsuke 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54
        this.channel = channel;
    }

    /**
     * Gets the channel that can be used to run a program remotely.
     *
     * @return
     *      null if the target node is not configured to support this.
     *      this is a transitional measure.
     *      Note that a launcher for the master is always non-null.
     */
    public VirtualChannel getChannel() {
        return channel;
K
kohsuke 已提交
55 56
    }

J
jglick 已提交
57
    public final Proc launch(String cmd, Map<String,String> env, OutputStream out, FilePath workDir) throws IOException {
K
kohsuke 已提交
58 59 60
        return launch(cmd,Util.mapToEnv(env),out,workDir);
    }

J
jglick 已提交
61
    public final Proc launch(String[] cmd, Map<String,String> env, OutputStream out, FilePath workDir) throws IOException {
K
kohsuke 已提交
62 63 64
        return launch(cmd,Util.mapToEnv(env),out,workDir);
    }

J
jglick 已提交
65
    public final Proc launch(String[] cmd, Map<String,String> env, InputStream in, OutputStream out) throws IOException {
K
kohsuke 已提交
66 67 68 69 70 71 72
        return launch(cmd,Util.mapToEnv(env),in,out);
    }

    public final Proc launch(String cmd,String[] env,OutputStream out, FilePath workDir) throws IOException {
        return launch(Util.tokenize(cmd),env,out,workDir);
    }

K
kohsuke 已提交
73 74
    public final Proc launch(String[] cmd,String[] env,OutputStream out, FilePath workDir) throws IOException {
        return launch(cmd,env,null,out,workDir);
K
kohsuke 已提交
75 76
    }

K
kohsuke 已提交
77 78
    public final Proc launch(String[] cmd,String[] env,InputStream in,OutputStream out) throws IOException {
        return launch(cmd,env,in,out,null);
K
kohsuke 已提交
79 80
    }

K
kohsuke 已提交
81 82 83 84 85 86 87 88 89 90 91
    /**
     * @param in
     *      null if there's no input.
     * @param workDir
     *      null if the working directory could be anything.
     * @param out
     *      stdout and stderr of the process will be sent to this stream.
     *      the stream won't be closed.
     */
    public abstract Proc launch(String[] cmd,String[] env,InputStream in,OutputStream out, FilePath workDir) throws IOException;

K
kohsuke 已提交
92 93 94 95 96 97 98 99
    /**
     * Returns true if this {@link Launcher} is going to launch on Unix.
     */
    public boolean isUnix() {
        return File.pathSeparatorChar==':';
    }

    /**
K
kohsuke 已提交
100
     * Prints out the command line to the listener so that users know what we are doing.
K
kohsuke 已提交
101
     */
K
kohsuke 已提交
102
    protected final void printCommandLine(String[] cmd, FilePath workDir) {
K
kohsuke 已提交
103 104 105 106 107 108 109 110 111 112 113 114
        StringBuffer buf = new StringBuffer();
        if (workDir != null) {
            buf.append('[');
            buf.append(workDir.getRemote().replaceFirst("^.+[/\\\\]", ""));
            buf.append("] ");
        }
        buf.append('$');
        for (String c : cmd) {
            buf.append(' ').append(c);
        }
        listener.getLogger().println(buf.toString());
    }
K
kohsuke 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

    public static class LocalLauncher extends Launcher {
        public LocalLauncher(TaskListener listener) {
            this(listener,Hudson.MasterComputer.localChannel);
        }

        public LocalLauncher(TaskListener listener, VirtualChannel channel) {
            super(listener, channel);
        }

        public Proc launch(String[] cmd,String[] env,InputStream in,OutputStream out, FilePath workDir) throws IOException {
            printCommandLine(cmd, workDir);
            return new LocalProc(cmd,Util.mapToEnv(inherit(env)),in,out, workDir==null ? null : new File(workDir.getRemote()));
        }

        /**
         * Expands the list of environment variables by inheriting current env variables.
         */
        private Map<String,String> inherit(String[] env) {
            Map<String,String> m = new HashMap<String,String>(EnvVars.masterEnvVars);
            for (String e : env) {
                int index = e.indexOf('=');
                String key = e.substring(0,index);
                String value = e.substring(index+1);
                if(value.length()==0)
                    m.remove(key);
                else
                    m.put(key,value);
            }
            return m;
        }
    }
K
kohsuke 已提交
147
}