net.sf.gluebooster.java.booster.basic.io.DataTransfer Maven / Gradle / Ivy
package net.sf.gluebooster.java.booster.basic.io;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.io.IOUtils;
import net.sf.gluebooster.java.booster.essentials.objects.BoostedObject;
/**
* Transfers the data of the input streams into the corresponding output streams
*/
public class DataTransfer extends BoostedObject implements Runnable
{
/**
* The input streams which content is to be transfered into the corresponding output streams.
*/
private InputStream[] inputs;
/**
* The ouput streams that receive the data of the corresponding input streams.
*/
private OutputStream[] outputs;
/**
* Contains the process that is responsible for the input streams.
* Optional.
*/
private Process process;
/**
* If all input streams are not available this is the time to wait before aborting the transfer.
*/
private int sleepAtMostSeconds = 60;
/**
* Default constructor.
*/
public DataTransfer()
{
}
/**
* Constructor with input and corresponding output streams.
* @param inputs The input streams which content is to be transfered into the corresponding output streams.
* @param outputs The ouput streams that receive the data of the corresponding input streams.
*/
public DataTransfer(InputStream[] inputs, OutputStream[] outputs)
{
this.inputs = inputs;
this.outputs = outputs;
}
/**
* Executes the command and writes the output and error streams.
* @param command the command to be executed. Example: cmd /c dir
* @param defaultOutput the stream where to write the default output
* @param errorOutput the stream where to write the error messages
* @param inSeparateThread should the start be done in a separate process.
* @throws Exception
* @return the exit value of the process if the start was in the same thread, otherwise null
*/
public static Integer execCommand(String command, OutputStream defaultOutput, OutputStream errorOutput, boolean inSeparateThread) throws Exception
{
Process process = Runtime.getRuntime().exec( command);
DataTransfer transfer = new DataTransfer(new InputStream[]{process.getInputStream(), process.getErrorStream()}, new OutputStream[]{defaultOutput, errorOutput});
transfer.process = process;
transfer.start(inSeparateThread);
if (inSeparateThread)
return null;
else
return process.exitValue();
}
/**
* Transfers the data of the input streams into the corresponding output streams
*/
@Override
public void run()
{
/**
* Indicates that data has been transfered or there was currently no data available, but the reading should proceed.
*/
boolean doContinue = true;
/**
* Counts the number of time sleeping while there is no available data.
*/
int sleepingSeconds = 0;
while (doContinue && sleepingSeconds < sleepAtMostSeconds)
{
byte[] bytes = new byte[1000];//buffer for reading
doContinue = false; //only continue when in at least one input stream an action is done
boolean doSleep = false; //sleep only when in all input streams nothing is done
for (int i = 0; i < inputs.length; i++)
{
doSleep = true;//set later to false if one action is done
try
{
int available = inputs[i].available() ;
if (available == 0) // EOF is reached.
{
// nothing more to do
// doSleep keeps its value
}
else
{
//System.out.println("reading at least " + available);
int value = inputs[i].read(bytes);
if (value == -1)
{
getLog().debug("\nEOF reached in stream ", i);
}
else
{
doSleep = false; //do not sleep
sleepingSeconds = 0;//reset
doContinue = true;//another round
outputs[i].write(bytes,0, value);
}
}
}
catch (EOFException ex)
{
getLog().debug("eof");
//nothing to to doContinue is false
}
catch (Exception ex)
{
getLog().warn("exc ",ex);
doContinue = true;//try again
}
}
if (doSleep)
{
if (process != null)
{
try
{
getLog().info("process " + process.exitValue());
//process.exitValue();
doContinue = false;//if the process has ended and no data can be read, then presumably the EOF is reached.
//System.out.println("process " + process.exitValue());
}
catch (IllegalThreadStateException ex)
{
getLog().warn("process still running");
}
}
sleepingSeconds++;
try
{
getLog().trace("sleeping for altogether ", sleepingSeconds);
Thread.sleep(1000);
}
catch (Exception ex)
{
}
}
}
getLog().debug("doContinue ="+ doContinue);
getLog().debug("sleepingSeconds < sleepAtMostSeconds: " + (sleepingSeconds < sleepAtMostSeconds));
}
/**
* Transfers the data of the input streams into the corresponding output streams.
* @param inputs
* @param outputs
* @param inSeparateThread should the start be done in a separate process.
*/
public static void transfer(InputStream[] inputs, OutputStream[] outputs, boolean inSeparateThread)
{
DataTransfer transfer = new DataTransfer(inputs, outputs);
transfer.start(inSeparateThread);
}
/**
* Starts this runnable
* @param inSeparateThread should the start be done in a separate process.
*/
public void start(boolean inSeparateThread)
{
if (inSeparateThread)
{
new Thread(this).start();
}
else
{
run();
}
}
/**
* Getter of the input streams
* @return the inputs set with setInputs
*/
public InputStream[] getInputs() {
return inputs;
}
/**
* Sets the input streams
* @param inputs the new input streams. The length has to be the same as the outputs
*/
public void setInputs(InputStream... inputs) {
this.inputs = inputs;
}
/**
* Getter of the output streams
* @return the ouputs set with setOutputs
*/
public OutputStream[] getOutputs() {
return outputs;
}
/**
* Sets the output streams.
* @param outputs the new output streams. The length has to be the same as the inputs
*/
public void setOutputs(OutputStream... outputs) {
this.outputs = outputs;
}
}