1 package org.codehaus.mojo.fitnesse.plexus;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import java.io.InputStream;
28
29 import org.codehaus.plexus.util.cli.StreamConsumer;
30 import org.codehaus.plexus.util.cli.StreamFeeder;
31 import org.codehaus.plexus.util.cli.StreamPumper;
32
33
34
35
36
37 public abstract class FCommandLineUtils
38 {
39 public static class StringStreamConsumer
40 implements StreamConsumer
41 {
42 private StringBuffer string = new StringBuffer();
43
44 private String ls = System.getProperty( "line.separator" );
45
46 public void consumeLine( String line )
47 {
48 string.append( line + ls );
49 }
50
51 public String getOutput()
52 {
53 return string.toString();
54 }
55 }
56
57 public static int executeCommandLine( FCommandline cl, StreamConsumer systemOut, StreamConsumer systemErr )
58 throws FCommandLineException
59 {
60 return executeCommandLine( cl, null, systemOut, systemErr );
61 }
62
63 public static int executeCommandLine( FCommandline cl, InputStream systemIn, StreamConsumer systemOut,
64 StreamConsumer systemErr )
65 throws FCommandLineException
66 {
67 if ( cl == null )
68 {
69 throw new IllegalArgumentException( "cl cannot be null." );
70 }
71
72 Process p = null;
73
74 p = cl.execute();
75 Thread tKiller = new KillerThread( p );
76 Runtime.getRuntime().addShutdownHook( tKiller );
77 StreamFeeder inputFeeder = null;
78
79 if ( systemIn != null )
80 {
81 inputFeeder = new StreamFeeder( systemIn, p.getOutputStream() );
82 }
83
84 StreamPumper outputPumper = new StreamPumper( p.getInputStream(), systemOut );
85
86 StreamPumper errorPumper = new StreamPumper( p.getErrorStream(), systemErr );
87
88 if ( inputFeeder != null )
89 {
90 inputFeeder.start();
91 }
92
93 outputPumper.start();
94
95 errorPumper.start();
96
97 try
98 {
99 int returnValue = p.waitFor();
100 if ( inputFeeder != null )
101 {
102 synchronized ( inputFeeder )
103 {
104 if ( !inputFeeder.isDone() )
105 {
106 inputFeeder.wait();
107 }
108 }
109 }
110
111 if ( outputPumper != null )
112 {
113 synchronized ( outputPumper )
114 {
115 if ( !outputPumper.isDone() )
116 {
117 outputPumper.wait();
118 }
119 }
120 }
121
122 if ( errorPumper != null )
123 {
124 synchronized ( errorPumper )
125 {
126 if ( !errorPumper.isDone() )
127 {
128 errorPumper.wait();
129 }
130 }
131 }
132 Runtime.getRuntime().removeShutdownHook( tKiller );
133
134 return returnValue;
135 }
136 catch ( InterruptedException ex )
137 {
138 throw new FCommandLineException( "Error while executing external command.", ex );
139 }
140 finally
141 {
142 if ( inputFeeder != null )
143 {
144 inputFeeder.close();
145 }
146
147 outputPumper.close();
148
149 errorPumper.close();
150 }
151 }
152
153 public static class KillerThread
154 extends Thread
155 {
156 public KillerThread( Process pProcess )
157 {
158 mProcessToKill = pProcess;
159 }
160
161 Process mProcessToKill;
162
163 public void run()
164 {
165 super.run();
166 if ( mProcessToKill != null )
167 {
168 System.err.println( "Sub process has been closed by destroy()" );
169 System.err.flush();
170 mProcessToKill.destroy();
171 }
172 else
173 {
174 System.err.println( "Should kill Sub process but was null" );
175 System.err.flush();
176 }
177 }
178
179 }
180 }