DefaultExecuteResultHandler.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.exec;
import java.time.Duration;
import java.time.Instant;
/**
* A default implementation of 'ExecuteResultHandler' used for asynchronous process handling.
*/
public class DefaultExecuteResultHandler implements ExecuteResultHandler {
/** The interval polling the result. */
private static final int SLEEP_TIME_MS = 50;
/** Keep track if the process is still running. */
private volatile boolean hasResult;
/** The exit value of the finished process. */
private volatile int exitValue;
/** Any offending exception. */
private volatile ExecuteException exception;
/**
* Constructs a new instance.
*/
public DefaultExecuteResultHandler() {
this.hasResult = false;
this.exitValue = Executor.INVALID_EXITVALUE;
}
/**
* Gets the {@code exception} causing the process execution to fail.
*
* @return the exception.
* @throws IllegalStateException if the process has not exited yet.
*/
public ExecuteException getException() {
if (!hasResult) {
throw new IllegalStateException("The process has not exited yet therefore no result is available ...");
}
return exception;
}
/**
* Gets the {@code exitValue} of the process.
*
* @return the exitValue.
* @throws IllegalStateException if the process has not exited yet.
*/
public int getExitValue() {
if (!hasResult) {
throw new IllegalStateException("The process has not exited yet therefore no result is available ...");
}
return exitValue;
}
/**
* Tests whether the process exited and a result is available, i.e. exitCode or exception?
*
* @return true whether a result of the execution is available.
*/
public boolean hasResult() {
return hasResult;
}
/**
* @see org.apache.commons.exec.ExecuteResultHandler#onProcessComplete(int)
*/
@Override
public void onProcessComplete(final int exitValue) {
this.exitValue = exitValue;
this.exception = null;
this.hasResult = true;
}
/**
* @see org.apache.commons.exec.ExecuteResultHandler#onProcessFailed(org.apache.commons.exec.ExecuteException)
*/
@Override
public void onProcessFailed(final ExecuteException e) {
this.exitValue = e.getExitValue();
this.exception = e;
this.hasResult = true;
}
/**
* Causes the current thread to wait, if necessary, until the process has terminated. This method returns immediately if the process has already terminated.
* If the process has not yet terminated, the calling thread will be blocked until the process exits.
*
* @throws InterruptedException if the current thread is {@linkplain Thread#interrupt() interrupted} by another thread while it is waiting, then the wait is
* ended and an {@link InterruptedException} is thrown.
*/
public void waitFor() throws InterruptedException {
while (!hasResult()) {
Thread.sleep(SLEEP_TIME_MS);
}
}
/**
* Causes the current thread to wait, if necessary, until the process has terminated. This method returns immediately if the process has already terminated.
* If the process has not yet terminated, the calling thread will be blocked until the process exits.
*
* @param timeout the maximum time to wait.
* @throws InterruptedException if the current thread is {@linkplain Thread#interrupt() interrupted} by another thread while it is waiting, then the wait is
* ended and an {@link InterruptedException} is thrown.
* @since 1.4.0
*/
public void waitFor(final Duration timeout) throws InterruptedException {
final Instant until = Instant.now().plus(timeout);
while (!hasResult() && Instant.now().isBefore(until)) {
Thread.sleep(SLEEP_TIME_MS);
}
}
/**
* Causes the current thread to wait, if necessary, until the process has terminated. This method returns immediately if the process has already terminated.
* If the process has not yet terminated, the calling thread will be blocked until the process exits.
*
* @param timeoutMillis the maximum time to wait in milliseconds.
* @throws InterruptedException if the current thread is {@linkplain Thread#interrupt() interrupted} by another thread while it is waiting, then the wait is
* ended and an {@link InterruptedException} is thrown.
* @deprecated Use {@link #waitFor(Duration)}.
*/
@Deprecated
public void waitFor(final long timeoutMillis) throws InterruptedException {
final long untilMillis = System.currentTimeMillis() + timeoutMillis;
while (!hasResult() && System.currentTimeMillis() < untilMillis) {
Thread.sleep(SLEEP_TIME_MS);
}
}
}