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 }