001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018 019 package org.apache.commons.exec; 020 021 /** 022 * A default implementation of 'ExecuteResultHandler' used for asynchronous 023 * process handling. 024 */ 025 public class DefaultExecuteResultHandler implements ExecuteResultHandler { 026 027 /** the interval polling the result */ 028 private static final int SLEEP_TIME_MS = 50; 029 030 /** Keep track if the process is still running */ 031 private volatile boolean hasResult; 032 033 /** The exit value of the finished process */ 034 private volatile int exitValue; 035 036 /** Any offending exception */ 037 private volatile ExecuteException exception; 038 039 /** 040 * Constructor. 041 */ 042 public DefaultExecuteResultHandler() { 043 this.hasResult = false; 044 this.exitValue = Executor.INVALID_EXITVALUE; 045 } 046 047 /** 048 * @see org.apache.commons.exec.ExecuteResultHandler#onProcessComplete(int) 049 */ 050 public void onProcessComplete(int exitValue) { 051 this.exitValue = exitValue; 052 this.exception = null; 053 this.hasResult = true; 054 } 055 056 /** 057 * @see org.apache.commons.exec.ExecuteResultHandler#onProcessFailed(org.apache.commons.exec.ExecuteException) 058 */ 059 public void onProcessFailed(ExecuteException e) { 060 this.exitValue = e.getExitValue(); 061 this.exception = e; 062 this.hasResult = true; 063 } 064 065 /** 066 * Get the <code>exception<code> causing the process execution to fail. 067 * 068 * @return Returns the exception. 069 * @throws IllegalStateException if the process has not exited yet 070 */ 071 public ExecuteException getException() { 072 073 if(!hasResult) { 074 throw new IllegalStateException("The process has not exited yet therefore no result is available ..."); 075 } 076 077 return exception; 078 } 079 080 /** 081 * Get the <code>exitValue<code> of the process. 082 * 083 * @return Returns the exitValue. 084 * @throws IllegalStateException if the process has not exited yet 085 */ 086 public int getExitValue() { 087 088 if(!hasResult) { 089 throw new IllegalStateException("The process has not exited yet therefore no result is available ..."); 090 } 091 092 return exitValue; 093 } 094 095 /** 096 * Has the process exited and a result is available, i.e. exitCode or exception? 097 * 098 * @return true if a result of the execution is available 099 */ 100 public boolean hasResult() { 101 return hasResult; 102 } 103 104 /** 105 * Causes the current thread to wait, if necessary, until the 106 * process has terminated. This method returns immediately if 107 * the process has already terminated. If the process has 108 * not yet terminated, the calling thread will be blocked until the 109 * process exits. 110 * 111 * @exception InterruptedException if the current thread is 112 * {@linkplain Thread#interrupt() interrupted} by another 113 * thread while it is waiting, then the wait is ended and 114 * an {@link InterruptedException} is thrown. 115 */ 116 public void waitFor() throws InterruptedException { 117 118 while (!hasResult()) { 119 Thread.sleep(SLEEP_TIME_MS); 120 } 121 } 122 123 /** 124 * Causes the current thread to wait, if necessary, until the 125 * process has terminated. This method returns immediately if 126 * the process has already terminated. If the process has 127 * not yet terminated, the calling thread will be blocked until the 128 * process exits. 129 * 130 * @param timeout the maximum time to wait in milliseconds 131 * @exception InterruptedException if the current thread is 132 * {@linkplain Thread#interrupt() interrupted} by another 133 * thread while it is waiting, then the wait is ended and 134 * an {@link InterruptedException} is thrown. 135 */ 136 public void waitFor(long timeout) throws InterruptedException { 137 138 long until = System.currentTimeMillis() + timeout; 139 140 while (!hasResult() && (System.currentTimeMillis() < until)) { 141 Thread.sleep(SLEEP_TIME_MS); 142 } 143 } 144 }