harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ndbe...@apache.org
Subject svn commit: r440870 - in /incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process: ProcessInputStream.java ProcessOutputStream.java SystemProcess.java
Date Wed, 06 Sep 2006 21:08:17 GMT
Author: ndbeyer
Date: Wed Sep  6 14:08:16 2006
New Revision: 440870

URL: http://svn.apache.org/viewvc?view=rev&rev=440870
Log:
code cleanup; add braces, remove unecessary initialization and compiler warnings

Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessInputStream.java
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessOutputStream.java
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/SystemProcess.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessInputStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessInputStream.java?view=diff&rev=440870&r1=440869&r2=440870
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessInputStream.java
(original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessInputStream.java
Wed Sep  6 14:08:16 2006
@@ -15,157 +15,115 @@
 
 package org.apache.harmony.luni.internal.process;
 
+import java.io.FileDescriptor;
+import java.io.IOException;
 
 class ProcessInputStream extends java.io.InputStream {
 
-	private long handle;
+    private long handle;
 
-	private java.io.FileDescriptor fd;
+    private FileDescriptor fd;
 
-	// Fill in the JNI id caches
-	private static native void oneTimeInitialization();
+    // Fill in the JNI id caches
+    private static native void oneTimeInitialization();
 
-	static {
-		oneTimeInitialization();
-	}
-
-	/**
-	 * Open an InputStream based on the handle.
-	 */
-	protected ProcessInputStream(long handle) {
-		this.fd = new java.io.FileDescriptor();
-		setFDImpl(fd, handle);
-		this.handle = handle;
-	}
-
-	/**
-	 * Answers a int representing then number of bytes that are available before
-	 * this InputStream will block.
-	 * 
-	 * @return the number of bytes available before blocking.
-	 * 
-	 * @throws java.io.IOException
-	 *             If an error occurs in this InputStream.
-	 */
-	public int available() throws java.io.IOException {
-		synchronized (this) {
-			if (handle == -1)
-				return -1;
-			return availableImpl();
-		}
-	}
-
-	/**
-	 * Native to determine the bytes available.
-	 */
-	private native int availableImpl() throws java.io.IOException;
-
-	/*
-	 * There is no way, at the library/vm level, to know when the stream will be
-	 * available for closing. If the user doesn't close it in his code, the
-	 * finalize() will run (eventually ?) and close the dangling OS
-	 * fileDescriptor.
-	 */
-	protected void finalize() throws Throwable {
-		close();
-	}
-
-	/**
-	 * Close the stream.
-	 */
-	public void close() throws java.io.IOException {
-		synchronized (this) {
-			if (handle == -1)
-				return;
-			closeImpl();
-			handle = -1;
-		}
-	}
-
-	/**
-	 * Native to close the stream.
-	 */
-	private native void closeImpl() throws java.io.IOException;
-
-	/**
-	 * Reads a single byte from this InputStream and returns the result as an
-	 * int. The low-order byte is returned or -1 of the end of stream was
-	 * encountered.
-	 * 
-	 * @return the byte read or -1 if end of stream.
-	 * 
-	 * @throws java.io.IOException
-	 *             If the stream is already closed or another IOException
-	 *             occurs.
-	 */
-	public int read() throws java.io.IOException {
-		byte buf[] = new byte[1];
-		synchronized (this) {
-			if (readImpl(buf, 0, 1, handle) == -1)
-				return -1;
-		}
-
-		return buf[0];
-	}
-
-	/**
-	 * Reads bytes from the Stream and stores them in byte array
-	 * <code>buffer</code>. Answer the number of bytes actually read or -1 if
-	 * no bytes were read and end of stream was encountered.
-	 * 
-	 * @param buffer
-	 *            the byte array in which to store the read bytes.
-	 * @return the number of bytes actually read or -1 if end of stream.
-	 * 
-	 * @throws java.io.IOException
-	 *             If the stream is already closed or another IOException
-	 *             occurs.
-	 */
-	public int read(byte[] buffer) throws java.io.IOException {
-		synchronized (this) {
-			return readImpl(buffer, 0, buffer.length, handle);
-		}
-	}
-
-	/**
-	 * Reads at most <code>nbytes</code> bytes from the Stream and stores them
-	 * in byte array <code>buffer</code> starting at <code>offset</code>.
-	 * Answer the number of bytes actually read or -1 if no bytes were read and
-	 * end of stream was encountered.
-	 * 
-	 * @param buffer
-	 *            the byte array in which to store the read bytes.
-	 * @param offset
-	 *            the offset in <code>buffer</code> to store the read bytes.
-	 * @param nbytes
-	 *            the maximum number of bytes to store in <code>buffer</code>.
-	 * @return the number of bytes actually read or -1 if end of stream.
-	 * 
-	 * @throws java.io.IOException
-	 *             If the stream is already closed or another IOException
-	 *             occurs.
-	 */
-	public int read(byte[] buffer, int offset, int nbytes)
-			throws java.io.IOException {
-		synchronized (this) {
-			if (handle == -1)
-				return -1;
-			if ((nbytes < 0 || nbytes > buffer.length)
-					|| (offset < 0 || offset > buffer.length)
-					|| ((nbytes + offset) > buffer.length))
-				throw new ArrayIndexOutOfBoundsException();
-			return readImpl(buffer, offset, nbytes, handle);
-		}
-	}
-
-	/**
-	 * Native to read into the buffer from the stream.
-	 */
-	private native int readImpl(byte[] buf, int offset, int nbytes, long hndl)
-			throws java.io.IOException;
-
-	/**
-	 * Native to set the FileDescriptor handle.
-	 */
-	private native void setFDImpl(java.io.FileDescriptor fd, long handle);
+    static {
+        oneTimeInitialization();
+    }
+
+    /**
+     * Native to determine the bytes available.
+     */
+    private native int availableImpl() throws IOException;
+
+    /**
+     * Native to read into the buffer from the stream.
+     */
+    private native int readImpl(byte[] buf, int offset, int nbytes, long hndl)
+            throws IOException;
+
+    /**
+     * Native to set the FileDescriptor handle.
+     */
+    private native void setFDImpl(FileDescriptor fd, long handle);
+
+    /**
+     * Native to close the stream.
+     */
+    private native void closeImpl() throws IOException;
+
+    /**
+     * Open an InputStream based on the handle.
+     */
+    protected ProcessInputStream(long handle) {
+        this.fd = new java.io.FileDescriptor();
+        setFDImpl(fd, handle);
+        this.handle = handle;
+    }
+
+    @Override
+    public int available() throws IOException {
+        synchronized (this) {
+            if (handle == -1) {
+                return -1;
+            }
+            return availableImpl();
+        }
+    }
+
+    /**
+     * There is no way, at the library/vm level, to know when the stream will be
+     * available for closing. If the user doesn't close it in his code, the
+     * finalize() will run (eventually ?) and close the dangling OS
+     * fileDescriptor.
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        close();
+    }
+
+    @Override
+    public void close() throws IOException {
+        synchronized (this) {
+            if (handle == -1) {
+                return;
+            }
+            closeImpl();
+            handle = -1;
+        }
+    }
+
+    @Override
+    public int read() throws IOException {
+        byte buf[] = new byte[1];
+        synchronized (this) {
+            if (readImpl(buf, 0, 1, handle) == -1) {
+                return -1;
+            }
+        }
+
+        return buf[0];
+    }
+
+    @Override
+    public int read(byte[] buffer) throws IOException {
+        synchronized (this) {
+            return readImpl(buffer, 0, buffer.length, handle);
+        }
+    }
+
+    @Override
+    public int read(byte[] buffer, int offset, int nbytes) throws IOException {
+        synchronized (this) {
+            if (handle == -1) {
+                return -1;
+            }
+            if ((nbytes < 0 || nbytes > buffer.length)
+                    || (offset < 0 || offset > buffer.length)
+                    || ((nbytes + offset) > buffer.length)) {
+                throw new ArrayIndexOutOfBoundsException();
+            }
+            return readImpl(buffer, offset, nbytes, handle);
+        }
+    }
 }

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessOutputStream.java?view=diff&rev=440870&r1=440869&r2=440870
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessOutputStream.java
(original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/ProcessOutputStream.java
Wed Sep  6 14:08:16 2006
@@ -15,124 +15,93 @@
 
 package org.apache.harmony.luni.internal.process;
 
-
-class ProcessOutputStream extends java.io.OutputStream {
-
-	private long handle;
-
-	private java.io.FileDescriptor fd;
-
-	// Fill in the JNI id caches
-	private static native void oneTimeInitialization();
-
-	static {
-		oneTimeInitialization();
-	}
-
-	/**
-	 * Open an OutputStream based on the handle.
-	 */
-	protected ProcessOutputStream(long handle) {
-		this.fd = new java.io.FileDescriptor();
-		setFDImpl(fd, handle);
-		this.handle = handle;
-	}
-
-	/*
-	 * There is no way, at the library/vm level, to know when the stream will be
-	 * available for closing. If the user doesn't close it in its code, the
-	 * finalize() will run (eventually ?) and close the dandling OS
-	 * fileDescriptor.
-	 */
-	protected void finalize() throws Throwable {
-		close();
-	}
-
-	/**
-	 * Close the stream.
-	 */
-	public void close() throws java.io.IOException {
-		synchronized (this) {
-			if (handle == -1)
-				return;
-			closeImpl();
-			handle = -1;
-		}
-	}
-
-	/**
-	 * Native to close the stream.
-	 */
-	private native void closeImpl() throws java.io.IOException;
-
-	/**
-	 * Native to set the FileDescriptor handle.
-	 */
-	private native void setFDImpl(java.io.FileDescriptor fd, long handle);
-
-	/**
-	 * Writes the entire contents of the byte array <code>buf</code> to this
-	 * OutputStream.
-	 * 
-	 * @param buf
-	 *            the buffer to be written
-	 * 
-	 * @throws java.io.IOException
-	 *             If an error occurs attempting to write to this OutputStream.
-	 */
-	public void write(byte[] buf) throws java.io.IOException {
-		synchronized (this) {
-			writeImpl(buf, 0, buf.length, handle);
-		}
-	}
-
-	/**
-	 * Writes <code>nbytes</code> <code>bytes</code> from the byte array
-	 * <code>buf</code> starting at <code>offset</code> to this
-	 * OutputStream.
-	 * 
-	 * @param buf
-	 *            the buffer to be written
-	 * @param offset
-	 *            offset in buffer to get bytes
-	 * @param nbytes
-	 *            number of bytes in buffer to write
-	 * 
-	 * @throws java.io.IOException
-	 *             If an error occurs attempting to write to this OutputStream.
-	 * @throws java.lang.IndexOutOfBoundsException
-	 *             If offset or count are outside of bounds.
-	 */
-	public void write(byte[] buf, int offset, int nbytes)
-			throws java.io.IOException {
-		synchronized (this) {
-			if (handle == -1)
-				return;
-			writeImpl(buf, offset, nbytes, handle);
-		}
-	}
-
-	/**
-	 * Writes the specified byte <code>oneByte</code> to this OutputStream.
-	 * Only the low order byte of <code>oneByte</code> is written.
-	 * 
-	 * @param oneByte
-	 *            the byte to be written
-	 * 
-	 * @throws java.io.IOException
-	 *             If an error occurs attempting to write to this OutputStream.
-	 */
-	public void write(int oneByte) throws java.io.IOException {
-		byte buf[] = new byte[1];
-		buf[0] = (byte) oneByte;
-		synchronized (this) {
-			writeImpl(buf, 0, 1, handle);
-		}
-	}
-
-	/**
-	 * Native to write the buffer to the stream.
-	 */
-	private native void writeImpl(byte[] buf, int offset, int nbytes, long hndl)
-			throws java.io.IOException;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.OutputStream;
+
+class ProcessOutputStream extends OutputStream {
+
+    private long handle;
+
+    private FileDescriptor fd;
+
+    // Fill in the JNI id caches
+    private static native void oneTimeInitialization();
+
+    static {
+        oneTimeInitialization();
+    }
+
+    /**
+     * Native to close the stream.
+     */
+    private native void closeImpl() throws IOException;
+
+    /**
+     * Native to set the FileDescriptor handle.
+     */
+    private native void setFDImpl(FileDescriptor fd, long handle);
+
+    /**
+     * Native to write the buffer to the stream.
+     */
+    private native void writeImpl(byte[] buf, int offset, int nbytes, long hndl)
+            throws IOException;
+
+    /**
+     * Open an OutputStream based on the handle.
+     */
+    protected ProcessOutputStream(long handle) {
+        this.fd = new FileDescriptor();
+        setFDImpl(fd, handle);
+        this.handle = handle;
+    }
+
+    /**
+     * There is no way, at the library/VM level, to know when the stream will be
+     * available for closing. If the user doesn't close it in its code, the
+     * finalize() will run (eventually ?) and close the dangling OS
+     * fileDescriptor.
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        close();
+    }
+
+    @Override
+    public void close() throws IOException {
+        synchronized (this) {
+            if (handle == -1) {
+                return;
+            }
+            closeImpl();
+            handle = -1;
+        }
+    }
+
+    @Override
+    public void write(byte[] buf) throws IOException {
+        synchronized (this) {
+            writeImpl(buf, 0, buf.length, handle);
+        }
+    }
+
+    @Override
+    public void write(byte[] buf, int offset, int nbytes) throws IOException {
+        synchronized (this) {
+            if (handle == -1) {
+                return;
+            }
+            writeImpl(buf, offset, nbytes, handle);
+        }
+    }
+
+    @Override
+    public void write(int oneByte) throws IOException {
+        byte buf[] = new byte[1];
+        buf[0] = (byte) oneByte;
+        synchronized (this) {
+            writeImpl(buf, 0, 1, handle);
+        }
+    }
 }

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/SystemProcess.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/SystemProcess.java?view=diff&rev=440870&r1=440869&r2=440870
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/SystemProcess.java
(original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/process/SystemProcess.java
Wed Sep  6 14:08:16 2006
@@ -15,259 +15,227 @@
 
 package org.apache.harmony.luni.internal.process;
 
-
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import org.apache.harmony.luni.util.Util;
+
 /**
- * This class provides the exec() implementation required for java.lang.Runtime.
+ * This class provides the {@link Runtime#exec(String[], String[], File)}
+ * implementation.
  * 
  * Instances of class Process provide control of and access to platform
  * processes. This is the concrete implementation of class java.lang.Process.
  * 
  * @see java.lang.Runtime
  */
-public class SystemProcess extends java.lang.Process {
-	InputStream err; // STDERR for the process
-
-	InputStream out; // STDOUT for the process
-
-	OutputStream in; // STDIN for the process
+public class SystemProcess extends Process {
 
-	long handle = -1; // Handle to OS process struct
+    // Fill in the JNI id caches
+    private static native void oneTimeInitialization();
 
-	/*
-	 * When exitCodeAvailable == 1, exitCode has a meaning. When exitCode is
-	 * available, it means that the underlying process had finished (for sure).
-	 */
-	boolean exitCodeAvailable = false;
-
-	int exitCode;
-
-	Object lock;
-
-	boolean waiterStarted = false;
-
-	Throwable exception = null;
-
-	// Fill in the JNI id caches
-	private static native void oneTimeInitialization();
-
-	static {
-		oneTimeInitialization();
-	}
-
-	/**
-	 * Prevents this class from being instantiated.
-	 */
-	private SystemProcess() {
-	}
-
-	/**
-	 * Answers a Process hooked to an OS process.
-	 * 
-	 * @param progArray
-	 *            the array containing the program to execute as well as any
-	 *            arguments to the program.
-	 * @param envp
-	 *            the array containing the environment to start the new process
-	 *            in.
-	 * @param directory
-	 *            the directory to start the process in, or null
-	 * 
-	 * @return a java.lang.Process
-	 * 
-	 * @throws IOException
-	 *             when a problem occurs
-	 * @throws NullPointerException
-	 *             when progArray or envp are null, or contain a null element in
-	 *             the array.
-	 */
-	public static Process create(String[] progArray, String[] envp,
-			final File directory) throws IOException {
-		final byte[][] progBytes, envBytes;
-		progBytes = new byte[progArray.length][];
-		for (int i = 0; i < progArray.length; i++)
-			progBytes[i] = org.apache.harmony.luni.util.Util.getBytes(progArray[i]);
-		envBytes = new byte[envp.length][];
-		for (int i = 0; i < envp.length; i++)
-			envBytes[i] = org.apache.harmony.luni.util.Util.getBytes(envp[i]);
-
-		final SystemProcess p = new SystemProcess();
-
-		p.lock = new Object();
-
-		Runnable waitingThread = new Runnable() {
-			public void run() {
-				long[] procVals = null;
-				try {
-					procVals = createImpl(p, progBytes, envBytes,
-							directory == null ? null : org.apache.harmony.luni.util.Util
-									.getBytes(directory.getPath()));
-				} catch (Throwable e) {
-					/* Creation errors need to be passed to the user thread. */
-					synchronized (p.lock) {
-						p.exception = e;
-						p.waiterStarted = true;
-						p.lock.notifyAll();
-					}
-					return;
-				}
-				p.handle = procVals[0];
-				p.in = new ProcessOutputStream(procVals[1]);
-				p.out = new ProcessInputStream(procVals[2]);
-				p.err = new ProcessInputStream(procVals[3]);
-
-				synchronized (p.lock) {
-					p.waiterStarted = true;
-					p.lock.notifyAll();
-				}
-
-				p.exitCode = p.waitForCompletionImpl();
-				synchronized (p.lock) {
-					p.closeImpl();
-					p.handle = -1;
-				}
-				p.exitCodeAvailable = true;
-				synchronized (p.lock) {
-					try {
-						p.in.close();
-					} catch (IOException e) {
-					}
-					p.lock.notifyAll();
-				}
-			}
-		};
-		Thread wait = new Thread(waitingThread);
-		wait.setDaemon(true);
-		wait.start();
-
-		try {
-			synchronized (p.lock) {
-				while (!p.waiterStarted)
-					p.lock.wait();
-				if (p.exception != null) {
-					/* Re-throw exception that originated in the helper thread */
-					p.exception.fillInStackTrace();
-					if (p.exception instanceof IOException)
-						throw (IOException) p.exception;
-					else if (p.exception instanceof Error)
-						throw (Error) p.exception;
-					else
-						throw (RuntimeException) p.exception;
-				}
-			}
-		} catch (InterruptedException e) {
-			throw new InternalError();
-		}
-
-		return p;
-	}
-
-	protected synchronized static native long[] createImpl(Process p,
-			byte[][] progArray, byte[][] envp, byte[] dir)
-			throws java.io.IOException;
-
-	/**
-	 * Stops the process associated with the receiver.
-	 */
-	public void destroy() {
-		synchronized (lock) {
-			if (handle != -1)
-				destroyImpl();
-		}
-	}
-
-	/**
-	 * Internal implementation of the code that stops the process associated
-	 * with the receiver.
-	 */
-	private native void destroyImpl();
-
-	/**
-	 * Internal implementation of the code that closes the handle.
-	 */
-	native void closeImpl();
-
-	/**
-	 * Answers the exit value of the receiving Process. It is available only
-	 * when the OS subprocess is finished.
-	 * 
-	 * @return int The exit value of the process.
-	 */
-	public int exitValue() {
-		synchronized (lock) {
-			if (!exitCodeAvailable)
-				throw new IllegalThreadStateException();
-			return exitCode;
-		}
-	}
-
-	/**
-	 * Answers the receiver's error output stream.
-	 * <p>
-	 * Note: This is an InputStream which allows reading of the other process'
-	 * "stderr".
-	 * 
-	 * @return InputStream The receiver's process' stderr.
-	 */
-	public java.io.InputStream getErrorStream() {
-		return err;
-	}
-
-	/**
-	 * Answers the receiver's standard output stream.
-	 * <p>
-	 * Note: This is an InputStream which allows reading of the other process'
-	 * "stdout".
-	 * 
-	 * @return InputStream The receiver's process' stdout.
-	 */
-	public java.io.InputStream getInputStream() {
-		return out;
-	}
-
-	/**
-	 * Answers the receiver's standard input stream
-	 * <p>
-	 * Note: This is an OutputStream which allows writing to the other process'
-	 * "stdin".
-	 * 
-	 * @return OutputStream The receiver's process' stdout.
-	 */
-	public java.io.OutputStream getOutputStream() {
-		return in;
-	}
-
-	/**
-	 * Causes the calling thread to wait for the process associated with the
-	 * receiver to finish executing.
-	 * 
-	 * @throws InterruptedException
-	 *             If the calling thread is interrupted
-	 * 
-	 * @return int The exit value of the Process being waited on
-	 */
-	public int waitFor() throws InterruptedException {
-		synchronized (lock) {
-			/*
-			 * if the exitCode is available, it means that the underlying OS
-			 * process is already dead, so the exitCode is just returned whitout
-			 * any other OS checks
-			 */
-			while (!exitCodeAvailable)
-				lock.wait();
-			return exitCode;
-		}
-	}
-
-	/**
-	 * Internal implementation of the code that waits for the process to
-	 * complete.
-	 * 
-	 * @return int The exit value of the process.
-	 */
-	native int waitForCompletionImpl();
+    static {
+        oneTimeInitialization();
+    }
+
+    /**
+     * Constructs a process connected to an OS process.
+     * 
+     * @param progArray the array containing the program to execute as well as
+     *        any arguments to the program.
+     * @param envp the array containing the environment to start the new process
+     *        in.
+     * @param directory the directory to start the process in, or null
+     * 
+     * @return The new process.
+     * 
+     * @throws IOException when a problem occurs
+     * @throws NullPointerException when progArray or envp are null, or contain
+     *         a null element in the array.
+     */
+    public static Process create(String[] progArray, String[] envp, final File directory)
+            throws IOException {
+        final byte[][] progBytes, envBytes;
+        progBytes = new byte[progArray.length][];
+        for (int i = 0; i < progArray.length; i++) {
+            progBytes[i] = Util.getBytes(progArray[i]);
+        }
+        envBytes = new byte[envp.length][];
+        for (int i = 0; i < envp.length; i++) {
+            envBytes[i] = Util.getBytes(envp[i]);
+        }
+
+        final SystemProcess p = new SystemProcess();
+
+        p.lock = new Object();
+
+        Runnable waitingThread = new Runnable() {
+            public void run() {
+                long[] procVals = null;
+                try {
+                    procVals = createImpl(p, progBytes, envBytes, directory == null ? null
+                            : Util.getBytes(directory.getPath()));
+                } catch (Throwable e) {
+                    /* Creation errors need to be passed to the user thread. */
+                    synchronized (p.lock) {
+                        p.exception = e;
+                        p.waiterStarted = true;
+                        p.lock.notifyAll();
+                    }
+                    return;
+                }
+                p.handle = procVals[0];
+                p.in = new ProcessOutputStream(procVals[1]);
+                p.out = new ProcessInputStream(procVals[2]);
+                p.err = new ProcessInputStream(procVals[3]);
+
+                synchronized (p.lock) {
+                    p.waiterStarted = true;
+                    p.lock.notifyAll();
+                }
+
+                p.exitCode = p.waitForCompletionImpl();
+                synchronized (p.lock) {
+                    p.closeImpl();
+                    p.handle = -1;
+                }
+                p.exitCodeAvailable = true;
+                synchronized (p.lock) {
+                    try {
+                        p.in.close();
+                    } catch (IOException e) {
+                    }
+                    p.lock.notifyAll();
+                }
+            }
+        };
+        Thread wait = new Thread(waitingThread);
+        wait.setDaemon(true);
+        wait.start();
+
+        try {
+            synchronized (p.lock) {
+                while (!p.waiterStarted) {
+                    p.lock.wait();
+                }
+                if (p.exception != null) {
+                    /* Re-throw exception that originated in the helper thread */
+                    p.exception.fillInStackTrace();
+                    if (p.exception instanceof IOException) {
+                        throw (IOException) p.exception;
+                    } else if (p.exception instanceof Error) {
+                        throw (Error) p.exception;
+                    } else {
+                        throw (RuntimeException) p.exception;
+                    }
+                }
+            }
+        } catch (InterruptedException e) {
+            throw new InternalError();
+        }
+
+        return p;
+    }
+
+    protected synchronized static native long[] createImpl(Process p, byte[][] progArray,
+            byte[][] envp, byte[] dir) throws IOException;
+
+    private InputStream err; // STDERR for the process
+
+    private InputStream out; // STDOUT for the process
+
+    private OutputStream in; // STDIN for the process
+
+    private long handle = -1; // Handle to OS process struct
+
+    /**
+     * When exitCodeAvailable == 1, exitCode has a meaning. When exitCode is
+     * available, it means that the underlying process had finished (for sure).
+     */
+    private boolean exitCodeAvailable;
+
+    private int exitCode;
+
+    private Object lock;
+
+    private boolean waiterStarted;
+
+    private Throwable exception;
+
+    /**
+     * Prevents this class from being instantiated outside of this class.
+     */
+    private SystemProcess() {
+        super();
+    }
+
+    /**
+     * Internal implementation of the code that stops the process associated
+     * with the receiver.
+     */
+    private native void destroyImpl();
+
+    /**
+     * Internal implementation of the code that closes the handle.
+     */
+    native void closeImpl();
+
+    /**
+     * Internal implementation of the code that waits for the process to
+     * complete.
+     * 
+     * @return int The exit value of the process.
+     */
+    native int waitForCompletionImpl();
+
+    @Override
+    public void destroy() {
+        synchronized (lock) {
+            if (handle != -1) {
+                destroyImpl();
+            }
+        }
+    }
+
+    @Override
+    public int exitValue() {
+        synchronized (lock) {
+            if (!exitCodeAvailable) {
+                throw new IllegalThreadStateException();
+            }
+            return exitCode;
+        }
+    }
+
+    @Override
+    public InputStream getErrorStream() {
+        return err;
+    }
+
+    @Override
+    public InputStream getInputStream() {
+        return out;
+    }
+
+    @Override
+    public OutputStream getOutputStream() {
+        return in;
+    }
+
+    @Override
+    public int waitFor() throws InterruptedException {
+        synchronized (lock) {
+            /*
+             * if the exitCode is available, it means that the underlying OS
+             * process is already dead, so the exitCode is just returned without
+             * any other OS checks
+             */
+            while (!exitCodeAvailable) {
+                lock.wait();
+            }
+            return exitCode;
+        }
+    }
 }



Mime
View raw message