/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
//JDK imports
/**
@author Kedar
@version 1.0
*/
public class ProcessExecutor
{
private String[] mInputLines = null; // strings to set in process's InputStream (like from redirection)
private Process mSubProcess=null; // used to get handle to child process for ProcessManager funtionality
private boolean mVerboseMode = false;
private boolean retainExecutionLogs = false;
private static boolean bDebug=false;
/**
Creates new ProcessExecutor
*/
{
}
/**
Creates new ProcessExecutor
*/
{
}
/**
Creates new ProcessExecutor
*/
{
}
{
}
/**
Creates a new <code> ProcessExecutor </code> that executes the given
command.
@param cmd String that has command name and its command line arguments
@param timeoutSeconds long integer timeout to be applied in seconds. After this time
if the process to execute does not end, it will be destroyed.
*/
{
mCmdStrings = cmd;
char fwdSlashChar = '/';
char backSlashChar = '\\';
// turn on debug, this option was added to help developers
// debug the their code
bDebug=true;
}
{
{
}
else
{
}
}
}
/** This is the setting after the fact that an instance of ProcessExecutor
* is created. This is to be used in case the output and error of the last
* execute call has to be retained for latter analysis.
* @param s boolean representing whether to retain, true means the buffers
* will be retained, false otherwise.
*/
public void setExecutionRetentionFlag(final boolean s) {
this.retainExecutionLogs = s;
}
public boolean getExecutionRetentionFlag() {
return ( this.retainExecutionLogs );
}
/** Returns the last LAST_BYTES bytes in the error stream of last execution as a String, if
* the ProcessExecutor was configured properly. It may return null if the
* retentionFlag is set to false.
*/
return ( this.lastExecutionErrorString );
}
/** Returns the last LAST_BYTES bytes in the output stream of last execution as a String, if
* the ProcessExecutor was configured properly. It may return null if the
* retentionFlag is set to false.
*/
return ( this.lastExecutionOutputString );
}
{
try{
}
catch (IllegalArgumentException iae){
}
catch (IOException ioe){
throw new ExecException(cannotCreateTempFiles());
}
}
return "Could not create temporary files - check "
+ " to see if its writeable and not-full";
}
private void deleteTempFiles(){
if (mOutStream != null) {
try {
mOutStream.flush();
mOutStream.close();
} catch (IOException ioe) {
// Ignore
}
}
if (mErrStream != null) {
try {
mErrStream.flush();
mErrStream.close();
} catch (IOException ioe) {
// Ignore
}
}
}
{
execute(false);
}
/*
Executes the command. Redirects the standard output and error streams
safely to files. This makes the subprocess NOT block or wait on
buffers getting flushed. This is done in a threaded manner.
Note that the subprocess will be killed if it does not end in given
timeout.
@throws ExecException if anything goes wrong in subprocess, or subprocess
terminates abruptly.
*/
{
return execute(bReturnOutputLines, true);
}
/**
* Allows a subclass to control the error message returned when a non-zero exit code is
* returned from a failed execution
* @return
*/
{
/* read the error message from error file */
}
return "abnormal subprocess termination: Detailed Message:" + errorMessage;
}
/*
Executes the command. Redirects the standard output and error streams
safely to files. This makes the subprocess NOT block or wait on
buffers getting flushed. This is done in a threaded manner.
Note that the subprocess will be killed if it does not end in given
timeout.
@throws ExecException if anything goes wrong in subprocess, or subprocess
terminates abruptly.
*/
{
init();
try
{
if (bDebug) {
}
}
if(mInputLines != null)
if(!bReturnOutputLines)
else
// see if process should startup in a limited ammount of time
// processes used by ProcessManager don't return
if (bStartUpTimeLimit) {
boolean timeoutReached = false;
boolean isSubProcessFinished = false;
boolean shouldBeDone = false;
while (! shouldBeDone)
{
try
{
isSubProcessFinished = true;
}
catch(IllegalThreadStateException itse)
{
isSubProcessFinished = false;
//ignore exception
}
}
if (!isSubProcessFinished)
{
mExitValue = -255;
}
else
{
if (debug()) {
}
if (mExitValue != 0)
{
if (mExitValue != 0)
{
throw new ExecException(getExceptionMessage());
}
}
}
}
}
catch(SecurityException se)
{
}
catch(IOException ioe)
{
}
finally {
// retain buffers before deleting them
// only delete files if the time is limited
// for processes that don't return, the temp files will remain
if (bStartUpTimeLimit) {
}
}
if(bReturnOutputLines) {
return getInputStrings(inputStream);
} else {
return null;
}
}
/**
* Get the exit value of the process executed. If this method is called
* before process execution is complete (i.e. before execute() method has
* returned, it will return -1. If sub process is terminated at timeout,
* the method will return -255
*/
public int getProcessExitValue() {
return mExitValue;
}
if(mInputLines==null)
return;
try
{
{
if(bDebug) {
}
}
}
catch (Exception e)
{
throw new ExecException(e.getMessage());
}
finally
{
try
{
}
catch (Throwable t)
{
}
}
}
{
if(inputStream==null)
return null;
try
{
return null;
}
catch (Exception e)
{
throw new ExecException(e.getMessage());
}
finally
{
try
{
}
catch (Throwable t)
{
}
}
}
{
try
{
// Redirect stderr for verbose mode
if(mVerboseMode) {
// send output to stderr
} else {
// send to temp file
}
}
catch (Exception e)
{
throw new ExecException(e.getMessage());
}
return out;
}
{
try
{
// Redirect stderr for verbose mode
if(mVerboseMode) {
// send output to stderr
} else {
// send to temp file
}
}
catch (Exception e)
{
throw new ExecException(e.getMessage());
}
return out;
}
}
{
try
{
}
catch(InterruptedException ie)
{
//ignore exception
}
}
/** Returns the contents of a file as a String. It never returns a null. If
* the file is empty, an empty string is returned.
* @param file the file to read
*/
try {
}
}
catch(Exception e) {
//squelch the exception
}
finally {
try {
}
catch(Exception e) {}
}
}
return ( new RAFileReader(f).readLastBytesAsString() );
}
public void retainBuffers() {
if (this.retainExecutionLogs) {
}
}
private boolean debug() {
return ( f.exists() );
}
final StringBuffer s = new StringBuffer();
if (a != null) {
for (int i = 0 ; i < a.length ; i++) {
s.append(a[i]);
s.append(" ");
}
}
return ( s.toString() );
}
private static class RAFileReader {
}
final int n = getNumberOfBytes(LAST_BYTES);
if (ln == 0)
assert (n <= ln) : ("Asked to read number of bytes more than size of file");
final long s = ln - n;
return ( readWithoutCheck(s) );
}
long ln = 0L;
int lines = 0;
try {
lines++;
//sb.append(Character.LINE_SEPARATOR);
}
}
catch (Exception e) {
//e.printStackTrace(); //ignore
}
finally {
try {
}
catch(Exception e) {}//ignore;
}
//System.out.println("ln-seekPos = " + (ln - seekPos) );
//System.out.println("bytes = " + sb.toString().getBytes().length);
//System.out.println("lines = " + lines);
//assert ((ln - seekPos) == (sb.toString().getBytes().length + lines)) : "Wrong number of bytes read";
}
}
}
// used for ProcessManager to watchdog subProcess
return mSubProcess;
}
{
}
/* This method tests the condition of process throwing an error.
* On Unixlike systems this throws an error in error file. On non-unixlike
* Systems it will throw IOException for CreateProcess, which is desired */
private static void testProcessError() {
try {
}
catch (ExecException ee) {
}
}
}
/**
* inner class to flush runtime.exec process so it doesn't hang
*/
mOutStream = out;
}
public void run() {
// check for null stream
// transfer bytes from input to output stream
try {
int byteCnt=0;
byte[] buffer=new byte[4096];
mOutStream.flush();
}
yield();
}
} catch (IOException e) {
// ignore
} finally {
try {
mOutStream.close();
} catch (IOException ioe) {
// ignore
}
}
}
}