27
27
import jdk .test .lib .Platform ;
28
28
import jdk .test .lib .Utils ;
29
29
30
+ import java .io .ByteArrayOutputStream ;
30
31
import java .io .File ;
31
32
import java .io .IOException ;
32
33
import java .io .InputStream ;
@@ -71,14 +72,17 @@ protected void processLine(String line) {
71
72
ps .println ("[" + prefix + "] " + line );
72
73
}
73
74
}
74
-
75
75
private ProcessTools () {
76
76
}
77
77
78
78
/**
79
79
* <p>Starts a process from its builder.</p>
80
80
* <span>The default redirects of STDOUT and STDERR are started</span>
81
- *
81
+ * <p>
82
+ * Same as
83
+ * {@linkplain #startProcess(String, ProcessBuilder, Consumer, Predicate, long, TimeUnit) startProcess}
84
+ * {@code (name, processBuilder, null, null, -1, TimeUnit.NANOSECONDS)}
85
+ * </p>
82
86
* @param name The process name
83
87
* @param processBuilder The process builder
84
88
* @return Returns the initialized process
@@ -93,11 +97,15 @@ public static Process startProcess(String name,
93
97
/**
94
98
* <p>Starts a process from its builder.</p>
95
99
* <span>The default redirects of STDOUT and STDERR are started</span>
96
- * <p>It is possible to monitor the in-streams via the provided {@code consumer}
100
+ * <p>
101
+ * Same as
102
+ * {@linkplain #startProcess(String, ProcessBuilder, Consumer, Predicate, long, TimeUnit) startProcess}
103
+ * {@code (name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS)}
104
+ * </p>
97
105
*
98
106
* @param name The process name
99
- * @param consumer {@linkplain Consumer} instance to process the in-streams
100
107
* @param processBuilder The process builder
108
+ * @param consumer {@linkplain Consumer} instance to process the in-streams
101
109
* @return Returns the initialized process
102
110
* @throws IOException
103
111
*/
@@ -118,8 +126,9 @@ public static Process startProcess(String name,
118
126
* <p>Starts a process from its builder.</p>
119
127
* <span>The default redirects of STDOUT and STDERR are started</span>
120
128
* <p>
121
- * It is possible to wait for the process to get to a warmed-up state
122
- * via {@linkplain Predicate} condition on the STDOUT/STDERR
129
+ * Same as
130
+ * {@linkplain #startProcess(String, ProcessBuilder, Consumer, Predicate, long, TimeUnit) startProcess}
131
+ * {@code (name, processBuilder, null, linePredicate, timeout, unit)}
123
132
* </p>
124
133
*
125
134
* @param name The process name
@@ -144,6 +153,58 @@ public static Process startProcess(String name,
144
153
return startProcess (name , processBuilder , null , linePredicate , timeout , unit );
145
154
}
146
155
156
+
157
+ /*
158
+ BufferOutputStream and BufferInputStream allow to re-use p.getInputStream() amd p.getOutputStream() of
159
+ processes started with ProcessTools.startProcess(...).
160
+ Implementation cashes ALL process output and allow to read it through InputStream.
161
+ */
162
+ private static class BufferOutputStream extends ByteArrayOutputStream {
163
+ private int current = 0 ;
164
+ final private Process p ;
165
+
166
+ public BufferOutputStream (Process p ) {
167
+ this .p = p ;
168
+ }
169
+
170
+ synchronized int readNext () {
171
+ if (current > count ) {
172
+ throw new RuntimeException ("Shouldn't ever happen. start: "
173
+ + current + " count: " + count + " buffer: " + this );
174
+ }
175
+ while (current == count ) {
176
+ if (!p .isAlive ()) {
177
+ return -1 ;
178
+ }
179
+ try {
180
+ wait (1 );
181
+ } catch (InterruptedException ie ) {
182
+ return -1 ;
183
+ }
184
+ }
185
+ return this .buf [current ++];
186
+ }
187
+ }
188
+
189
+ private static class BufferInputStream extends InputStream {
190
+
191
+ private final BufferOutputStream buffer ;
192
+
193
+ public BufferInputStream (Process p ) {
194
+ buffer = new BufferOutputStream (p );
195
+ }
196
+
197
+ OutputStream getOutputStream () {
198
+ return buffer ;
199
+ }
200
+
201
+ @ Override
202
+ public int read () throws IOException {
203
+ return buffer .readNext ();
204
+ }
205
+ }
206
+
207
+
147
208
/**
148
209
* <p>Starts a process from its builder.</p>
149
210
* <span>The default redirects of STDOUT and STDERR are started</span>
@@ -181,6 +242,12 @@ public static Process startProcess(String name,
181
242
182
243
stdout .addPump (new LineForwarder (name , System .out ));
183
244
stderr .addPump (new LineForwarder (name , System .err ));
245
+ BufferInputStream stdOut = new BufferInputStream (p );
246
+ BufferInputStream stdErr = new BufferInputStream (p );
247
+
248
+ stdout .addOutputStream (stdOut .getOutputStream ());
249
+ stderr .addOutputStream (stdErr .getOutputStream ());
250
+
184
251
if (lineConsumer != null ) {
185
252
StreamPumper .LinePump pump = new StreamPumper .LinePump () {
186
253
@ Override
@@ -250,7 +317,7 @@ protected void processLine(String line) {
250
317
throw e ;
251
318
}
252
319
253
- return new ProcessImpl (p , stdoutTask , stderrTask );
320
+ return new ProcessImpl (p , stdoutTask , stderrTask , stdOut , stdErr );
254
321
}
255
322
256
323
/**
@@ -701,14 +768,19 @@ private static Process privilegedStart(ProcessBuilder pb) throws IOException {
701
768
702
769
private static class ProcessImpl extends Process {
703
770
771
+ private final InputStream stdOut ;
772
+ private final InputStream stdErr ;
704
773
private final Process p ;
705
774
private final Future <Void > stdoutTask ;
706
775
private final Future <Void > stderrTask ;
707
776
708
- public ProcessImpl (Process p , Future <Void > stdoutTask , Future <Void > stderrTask ) {
777
+ public ProcessImpl (Process p , Future <Void > stdoutTask , Future <Void > stderrTask ,
778
+ InputStream stdOut , InputStream etdErr ) {
709
779
this .p = p ;
710
780
this .stdoutTask = stdoutTask ;
711
781
this .stderrTask = stderrTask ;
782
+ this .stdOut = stdOut ;
783
+ this .stdErr = etdErr ;
712
784
}
713
785
714
786
@ Override
@@ -718,12 +790,12 @@ public OutputStream getOutputStream() {
718
790
719
791
@ Override
720
792
public InputStream getInputStream () {
721
- return p . getInputStream () ;
793
+ return stdOut ;
722
794
}
723
795
724
796
@ Override
725
797
public InputStream getErrorStream () {
726
- return p . getErrorStream () ;
798
+ return stdErr ;
727
799
}
728
800
729
801
@ Override
0 commit comments