KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > hudson > Proc


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 JavaDoc;
8 import java.io.IOException JavaDoc;
9 import java.io.InputStream JavaDoc;
10 import java.io.OutputStream JavaDoc;
11 import java.util.Map JavaDoc;
12 import java.util.concurrent.ExecutionException JavaDoc;
13 import java.util.concurrent.Future JavaDoc;
14 import java.util.logging.Level JavaDoc;
15 import java.util.logging.Logger JavaDoc;
16
17 /**
18  * External process wrapper.
19  *
20  * <p>
21  * Used for launching, monitoring, waiting for a process.
22  *
23  * @author Kohsuke Kawaguchi
24  */

25 public abstract class Proc {
26     private Proc() {}
27
28     /**
29      * Terminates the process.
30      *
31      * @throws IOException
32      * if there's an error killing a process
33      * and a stack trace could help the trouble-shooting.
34      */

35     public abstract void kill() throws IOException JavaDoc;
36
37     /**
38      * Waits for the completion of the process.
39      *
40      * <p>
41      * If the thread is interrupted while waiting for the completion
42      * of the process, this method terminates the process and
43      * exits with a non-zero exit code.
44      *
45      * @throws IOException
46      * if there's an error launching/joining a process
47      * and a stack trace could help the trouble-shooting.
48      */

49     public abstract int join() throws IOException JavaDoc;
50
51     /**
52      * Locally launched process.
53      */

54     public static final class LocalProc extends Proc {
55         private final Process JavaDoc proc;
56         private final Thread JavaDoc t1,t2;
57
58         public LocalProc(String JavaDoc cmd, Map JavaDoc<String JavaDoc,String JavaDoc> env, OutputStream JavaDoc out, File JavaDoc workDir) throws IOException JavaDoc {
59             this(cmd,Util.mapToEnv(env),out,workDir);
60         }
61
62         public LocalProc(String JavaDoc[] cmd, Map JavaDoc<String JavaDoc,String JavaDoc> env,InputStream JavaDoc in, OutputStream JavaDoc out) throws IOException JavaDoc {
63             this(cmd,Util.mapToEnv(env),in,out);
64         }
65
66         public LocalProc(String JavaDoc cmd,String JavaDoc[] env,OutputStream JavaDoc out, File JavaDoc workDir) throws IOException JavaDoc {
67             this( Util.tokenize(cmd), env, out, workDir );
68         }
69
70         public LocalProc(String JavaDoc[] cmd,String JavaDoc[] env,OutputStream JavaDoc out, File JavaDoc workDir) throws IOException JavaDoc {
71             this(cmd,env,null,out,workDir);
72         }
73
74         public LocalProc(String JavaDoc[] cmd,String JavaDoc[] env,InputStream JavaDoc in,OutputStream JavaDoc out) throws IOException JavaDoc {
75             this(cmd,env,in,out,null);
76         }
77
78         public LocalProc(String JavaDoc[] cmd,String JavaDoc[] env,InputStream JavaDoc in,OutputStream JavaDoc out, File JavaDoc workDir) throws IOException JavaDoc {
79             this( calcName(cmd), Runtime.getRuntime().exec(cmd,env,workDir), in, out );
80         }
81
82         private LocalProc( String JavaDoc name, Process JavaDoc proc, InputStream JavaDoc in, OutputStream JavaDoc out ) throws IOException JavaDoc {
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         /**
96          * Waits for the completion of the process.
97          */

98         @Override JavaDoc
99         public int join() {
100             try {
101                 t1.join();
102                 t2.join();
103                 return proc.waitFor();
104             } catch (InterruptedException JavaDoc e) {
105                 // aborting. kill the process
106
proc.destroy();
107                 return -1;
108             }
109         }
110
111         @Override JavaDoc
112         public void kill() {
113             proc.destroy();
114             join();
115         }
116
117         private static class ByteCopier extends Thread JavaDoc {
118             private final InputStream JavaDoc in;
119             private final OutputStream JavaDoc out;
120
121             public ByteCopier(String JavaDoc threadName, InputStream JavaDoc in, OutputStream JavaDoc 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 JavaDoc e) {
137                     // TODO: what to do?
138
}
139             }
140         }
141
142         private static String JavaDoc calcName(String JavaDoc[] cmd) {
143             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
144             for (String JavaDoc token : cmd) {
145                 if(buf.length()>0) buf.append(' ');
146                 buf.append(token);
147             }
148             return buf.toString();
149         }
150     }
151
152     /**
153      * Retemoly launched process via {@link Channel}.
154      */

155     public static final class RemoteProc extends Proc {
156         private final Future JavaDoc<Integer JavaDoc> process;
157
158         public RemoteProc(Future JavaDoc<Integer JavaDoc> process) {
159             this.process = process;
160         }
161
162         @Override JavaDoc
163         public void kill() throws IOException JavaDoc {
164             process.cancel(true);
165             join();
166         }
167
168         @Override JavaDoc
169         public int join() throws IOException JavaDoc {
170             try {
171                 return process.get();
172             } catch (InterruptedException JavaDoc e) {
173                 // aborting. kill the process
174
process.cancel(true);
175                 return -1;
176             } catch (ExecutionException JavaDoc e) {
177                 if(e.getCause() instanceof IOException JavaDoc)
178                     throw (IOException JavaDoc)e.getCause();
179                 throw new IOException2("Failed to join the process",e);
180             }
181         }
182     }
183 }
184
Popular Tags