1 package hudson; 2 3 import hudson.remoting.Channel; 4 import hudson.util.StreamCopyThread; 5 import hudson.util.IOException2; 6 7 import java.io.File ; 8 import java.io.IOException ; 9 import java.io.InputStream ; 10 import java.io.OutputStream ; 11 import java.util.Map ; 12 import java.util.concurrent.ExecutionException ; 13 import java.util.concurrent.Future ; 14 import java.util.logging.Level ; 15 import java.util.logging.Logger ; 16 17 25 public abstract class Proc { 26 private Proc() {} 27 28 35 public abstract void kill() throws IOException ; 36 37 49 public abstract int join() throws IOException ; 50 51 54 public static final class LocalProc extends Proc { 55 private final Process proc; 56 private final Thread t1,t2; 57 58 public LocalProc(String cmd, Map <String ,String > env, OutputStream out, File workDir) throws IOException { 59 this(cmd,Util.mapToEnv(env),out,workDir); 60 } 61 62 public LocalProc(String [] cmd, Map <String ,String > env,InputStream in, OutputStream out) throws IOException { 63 this(cmd,Util.mapToEnv(env),in,out); 64 } 65 66 public LocalProc(String cmd,String [] env,OutputStream out, File workDir) throws IOException { 67 this( Util.tokenize(cmd), env, out, workDir ); 68 } 69 70 public LocalProc(String [] cmd,String [] env,OutputStream out, File workDir) throws IOException { 71 this(cmd,env,null,out,workDir); 72 } 73 74 public LocalProc(String [] cmd,String [] env,InputStream in,OutputStream out) throws IOException { 75 this(cmd,env,in,out,null); 76 } 77 78 public LocalProc(String [] cmd,String [] env,InputStream in,OutputStream out, File workDir) throws IOException { 79 this( calcName(cmd), Runtime.getRuntime().exec(cmd,env,workDir), in, out ); 80 } 81 82 private LocalProc( String name, Process proc, InputStream in, OutputStream out ) throws IOException { 83 Logger.getLogger(Proc.class.getName()).log(Level.FINE, "Running: {0}", name); 84 this.proc = proc; 85 t1 = new StreamCopyThread(name+": stdout copier", proc.getInputStream(), out); 86 t1.start(); 87 t2 = new StreamCopyThread(name+": stderr copier", proc.getErrorStream(), out); 88 t2.start(); 89 if(in!=null) 90 new ByteCopier(name+": stdin copier",in,proc.getOutputStream()).start(); 91 else 92 proc.getOutputStream().close(); 93 } 94 95 98 @Override 99 public int join() { 100 try { 101 t1.join(); 102 t2.join(); 103 return proc.waitFor(); 104 } catch (InterruptedException e) { 105 proc.destroy(); 107 return -1; 108 } 109 } 110 111 @Override 112 public void kill() { 113 proc.destroy(); 114 join(); 115 } 116 117 private static class ByteCopier extends Thread { 118 private final InputStream in; 119 private final OutputStream out; 120 121 public ByteCopier(String threadName, InputStream in, OutputStream out) { 122 super(threadName); 123 this.in = in; 124 this.out = out; 125 } 126 127 public void run() { 128 try { 129 while(true) { 130 int ch = in.read(); 131 if(ch==-1) break; 132 out.write(ch); 133 } 134 in.close(); 135 out.close(); 136 } catch (IOException e) { 137 } 139 } 140 } 141 142 private static String calcName(String [] cmd) { 143 StringBuffer buf = new StringBuffer (); 144 for (String token : cmd) { 145 if(buf.length()>0) buf.append(' '); 146 buf.append(token); 147 } 148 return buf.toString(); 149 } 150 } 151 152 155 public static final class RemoteProc extends Proc { 156 private final Future <Integer > process; 157 158 public RemoteProc(Future <Integer > process) { 159 this.process = process; 160 } 161 162 @Override 163 public void kill() throws IOException { 164 process.cancel(true); 165 join(); 166 } 167 168 @Override 169 public int join() throws IOException { 170 try { 171 return process.get(); 172 } catch (InterruptedException e) { 173 process.cancel(true); 175 return -1; 176 } catch (ExecutionException e) { 177 if(e.getCause() instanceof IOException ) 178 throw (IOException )e.getCause(); 179 throw new IOException2("Failed to join the process",e); 180 } 181 } 182 } 183 } 184 | Popular Tags |