Author: sgoeschl Date: Tue Jan 1 14:50:59 2008 New Revision: 607936 URL: http://svn.apache.org/viewvc?rev=607936&view=rev Log: SANDBOX-107 - Make ProcessDestroyer optional and pluggable
Modified: commons/sandbox/exec/trunk/src/changes/changes.xml commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/Executor.java commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ProcessDestroyer.java commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ShutdownHookProcessDestroyer.java commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java Modified: commons/sandbox/exec/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/changes/changes.xml?rev=607936&r1=607935&r2=607936&view=diff ============================================================================== --- commons/sandbox/exec/trunk/src/changes/changes.xml (original) +++ commons/sandbox/exec/trunk/src/changes/changes.xml Tue Jan 1 14:50:59 2008 @@ -6,6 +6,9 @@ </properties> <body> <release version="1.0-SNAPSHOT" date="as in SVN" description="Sandbox release"> + <action dev="sgoeschl" type="add" issue="SANDBOX-107" due-to="Niklas Gustavsson"> + Made ProcessDestroyer optional and pluggable when using Executor. + </action> <action dev="sgoeschl" type="add"> CommandLine can now expand the given command line by a user-suppied map. This allows to execute something like "${JAVA_HOME}/bin/java -jar ${myapp}" Modified: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java?rev=607936&r1=607935&r2=607936&view=diff ============================================================================== --- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java (original) +++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java Tue Jan 1 14:50:59 2008 @@ -40,9 +40,12 @@ /** the exit values considerd to be successful */ private int[] exitValues; - // TODO replace with generic launcher + /** launches the command in a new process */ private CommandLauncher launcher; + /** optional cleanup of started processes */ + private ProcessDestroyer processDestroyer; + /** * Default Constrctor */ @@ -81,6 +84,20 @@ } /** + * @see org.apache.commons.exec.Executor#getProcessDestroyer() + */ + public ProcessDestroyer getProcessDestroyer() { + return this.processDestroyer; + } + + /** + * @see org.apache.commons.exec.Executor#setProcessDestroyer(ProcessDestroyer) + */ + public void setProcessDestroyer(ProcessDestroyer processDestroyer) { + this.processDestroyer = processDestroyer; + } + + /** * @see org.apache.commons.exec.Executor#getWorkingDirectory() */ public File getWorkingDirectory() { @@ -131,13 +148,14 @@ */ public void execute(final CommandLine command, final Map environment, final ExecuteResultHandler handler) throws ExecuteException, IOException { + if (workingDirectory != null && !workingDirectory.exists()) { throw new IOException(workingDirectory + " doesn't exist."); } new Thread() { - /* (non-Javadoc) + /** * @see java.lang.Thread#run() */ public void run() { @@ -152,11 +170,6 @@ handler.onProcessFailed(e); } catch(Exception e) { handler.onProcessFailed(new ExecuteException("Execution failed", exitValue, e)); - } finally { - // remove the process to the list of those to destroy if the VM - // exits - // - // processDestroyer.remove(process); } } }.start(); @@ -271,12 +284,14 @@ process.destroy(); throw e; } + streams.start(); try { // add the process to the list of those to destroy if the VM exits - // - // processDestroyer.add(process); + if(this.getProcessDestroyer() != null) { + this.getProcessDestroyer().add(process); + } if (watchdog != null) { watchdog.start(process); @@ -301,7 +316,6 @@ // TODO: include cause throw new IOException(e.getMessage()); } - } if(!this.isSuccess(exitValue)) { @@ -310,10 +324,10 @@ return exitValue; } finally { - // remove the process to the list of those to destroy if the VM - // exits - // - // processDestroyer.remove(process); + // remove the process to the list of those to destroy if the VM exits + if(this.getProcessDestroyer() != null) { + this.getProcessDestroyer().remove(process); + } } } Modified: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/Executor.java URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/Executor.java?rev=607936&r1=607935&r2=607936&view=diff ============================================================================== --- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/Executor.java (original) +++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/Executor.java Tue Jan 1 14:50:59 2008 @@ -58,6 +58,13 @@ ExecuteWatchdog getWatchdog(); void setWatchdog(ExecuteWatchdog watchDog); + /** + * Optinal cleanup of started processes if the main process + * is going to terminate. + */ + ProcessDestroyer getProcessDestroyer(); + void setProcessDestroyer(ProcessDestroyer processDestroyer); + /* * Set the working directory of the created process. */ Modified: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ProcessDestroyer.java URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ProcessDestroyer.java?rev=607936&r1=607935&r2=607936&view=diff ============================================================================== --- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ProcessDestroyer.java (original) +++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ProcessDestroyer.java Tue Jan 1 14:50:59 2008 @@ -50,4 +50,11 @@ * successfully removed */ boolean remove(Process process); + + /** + * Returns the number of registered processes. + * + * @return the number of register process + */ + int size(); } Modified: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ShutdownHookProcessDestroyer.java URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ShutdownHookProcessDestroyer.java?rev=607936&r1=607935&r2=607936&view=diff ============================================================================== --- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ShutdownHookProcessDestroyer.java (original) +++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/ShutdownHookProcessDestroyer.java Tue Jan 1 14:50:59 2008 @@ -164,7 +164,16 @@ } } - /** + /** + * Returns the number of registered processes. + * + * @return the number of register process + */ + public int size() { + return processes.size(); + } + + /** * Invoked by the VM when it is exiting. */ public void run() { @@ -172,8 +181,14 @@ running = true; Enumeration e = processes.elements(); while (e.hasMoreElements()) { - ((Process) e.nextElement()).destroy(); - } + Process process = (Process) e.nextElement(); + try { + process.destroy(); + } + catch(Throwable t) { + System.err.println("Unable to terminate process during process shutdown"); + } + } } } } Modified: commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java?rev=607936&r1=607935&r2=607936&view=diff ============================================================================== --- commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java (original) +++ commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java Tue Jan 1 14:50:59 2008 @@ -269,5 +269,86 @@ assertEquals(1, e.getExitValue()); return; } - } + } + + /** + * Test the proper handling of ProcessDestroyer for an synchronous process. + */ + public void testExecuteWithProcessDestroyer() throws Exception { + + CommandLine cl = new CommandLine(testScript); + ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer(); + exec.setProcessDestroyer(processDestroyer); + + assertTrue(processDestroyer.size() == 0); + assertTrue(processDestroyer.isAddedAsShutdownHook() == false); + + int exitValue = exec.execute(cl); + + assertEquals("FOO..", baos.toString().trim()); + assertEquals(0, exitValue); + assertTrue(processDestroyer.size() == 0); + assertTrue(processDestroyer.isAddedAsShutdownHook() == false); + } + + /** + * Test the proper handling of ProcessDestroyer for an asynchronous process. + * Since we do not terminate the process it will be terminated in the + * ShutdownHookProcessDestroyer implementation + */ + public void testExecuteAsyncWithProcessDestroyer1() throws Exception { + + CommandLine cl = new CommandLine(foreverTestScript); + MockExecuteResultHandler handler = new MockExecuteResultHandler(); + ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer(); + ExecuteWatchdog watchdog = new ExecuteWatchdog(Integer.MAX_VALUE); + + assertTrue(exec.getProcessDestroyer() == null); + assertTrue(processDestroyer.size() == 0); + assertTrue(processDestroyer.isAddedAsShutdownHook() == false); + + exec.setWatchdog(watchdog); + exec.setProcessDestroyer(processDestroyer); + exec.execute(cl, handler); + + // wait for script to run + Thread.sleep(2000); + assertNotNull(exec.getProcessDestroyer()); + assertTrue(processDestroyer.size() == 1); + assertTrue(processDestroyer.isAddedAsShutdownHook() == true); + } + + /** + * Test the proper handling of ProcessDestroyer for an asynchronous process. + * Since we do not terminate the process it will be terminated in the + * ShutdownHookProcessDestroyer implementation + */ + public void testExecuteAsyncWithProcessDestroyer2() throws Exception { + + CommandLine cl = new CommandLine(foreverTestScript); + MockExecuteResultHandler handler = new MockExecuteResultHandler(); + ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer(); + ExecuteWatchdog watchdog = new ExecuteWatchdog(Integer.MAX_VALUE); + + assertTrue(exec.getProcessDestroyer() == null); + assertTrue(processDestroyer.size() == 0); + assertTrue(processDestroyer.isAddedAsShutdownHook() == false); + + exec.setWatchdog(watchdog); + exec.setProcessDestroyer(processDestroyer); + exec.execute(cl, handler); + + // wait for script to run + Thread.sleep(2000); + assertNotNull(exec.getProcessDestroyer()); + assertTrue(processDestroyer.size() == 1); + assertTrue(processDestroyer.isAddedAsShutdownHook() == true); + + // teminate it + watchdog.destroyProcess(); + assertTrue(watchdog.killedProcess()); + Thread.sleep(100); + assertTrue(processDestroyer.size() == 0); + assertTrue(processDestroyer.isAddedAsShutdownHook() == false); + } }