blob: e8ca77ee1e9209625036e3a3e6b44924842a8c20 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* A ProcessOutputReader will read both stdout and stderr from a {@link java.lang.Process} process.
* The constructor does not return until all output from the process has been read and the process
* has exited.
*
*
*/
public class ProcessOutputReader {
private int exitCode;
private String output;
/**
* Creates a process output reader for the given process.
*
* @param p the process whose output should be read.
*/
public ProcessOutputReader(final Process p) {
final List lines = Collections.synchronizedList(new ArrayList());
class ProcessStreamReader extends Thread {
private BufferedReader reader;
public int linecount = 0;
public ProcessStreamReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream));
}
@Override
public void run() {
try {
String line;
while ((line = reader.readLine()) != null) {
linecount++;
lines.add(line);
}
reader.close();
} catch (Exception e) {
}
}
};
ProcessStreamReader stdout = new ProcessStreamReader(p.getInputStream());
ProcessStreamReader stderr = new ProcessStreamReader(p.getErrorStream());
stdout.start();
stderr.start();
try {
stderr.join();
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
}
try {
stdout.join();
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
}
this.exitCode = 0;
int retryCount = 9;
while (retryCount > 0) {
retryCount--;
try {
exitCode = p.exitValue();
break;
} catch (IllegalThreadStateException e) {
// due to bugs in Process we may not be able to get
// a process's exit value.
// We can't use Process.waitFor() because it can hang forever
if (retryCount == 0) {
if (stderr.linecount > 0) {
// The process wrote to stderr so manufacture
// an error exist code
lines.add(
"Failed to get exit status and it wrote to stderr so setting exit status to 1.");
exitCode = 1;
}
} else {
// We need to wait around to give a chance for
// the child to be reaped.See bug 19682
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
// TODO a cancellation check here?
}
}
}
}
java.io.StringWriter sw = new java.io.StringWriter();
PrintWriter pw = new PrintWriter(sw);
Iterator it = lines.iterator();
while (it.hasNext()) {
pw.println((String) it.next());
}
pw.close();
try {
sw.close();
} catch (java.io.IOException ignore) {
}
StringBuffer buf = sw.getBuffer();
if (buf != null && buf.length() > 0) {
this.output = sw.toString();
} else {
this.output = "";
}
}
/**
* Gets the process's exit status code. A code equal to 0 indicates all is well.
*/
public int getExitCode() {
return exitCode;
}
/**
* Gets everything the process wrote to both stdout and stderr.
*/
public String getOutput() {
return output;
}
}