All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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;
   }

   
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy