
org.zeroturnaround.process.AbstractProcess Maven / Gradle / Ivy
Show all versions of zt-process-killer Show documentation
package org.zeroturnaround.process;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base implementation of {@link SystemProcess}.
*/
public abstract class AbstractProcess implements SystemProcess {
protected final Logger log = LoggerFactory.getLogger(getClass());
@Override
public String toString() {
return getClass().getSimpleName() + "(" + getDescription() + ")";
}
/**
* @return the description of the system process.
*/
protected abstract String getDescription();
/**
* Causes the current thread to wait, if necessary, until the process handled by this killer has terminated, or the specified timeout is reached.
*
* If the process has already terminated then this method returns immediately with the value true
.
* If the process has not terminated and the timeout value is less than, or equal to, zero, then this method returns immediately with the value false
.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return true
if the process has exited and false
if the timeout is reached before the process has exited.
*/
@Override
public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException {
ExecutorService service = Executors.newSingleThreadScheduledExecutor();
try {
Runnable task = new Runnable() {
@Override
public void run() {
try {
waitFor();
}
catch (InterruptedException e) {
log.debug("Interrupted waiting for {}", getDescription());
}
}
};
service.submit(task).get(timeout, unit);
}
catch (ExecutionException e) {
throw new IllegalStateException("Error occured while waiting for process to finish:", e.getCause());
}
catch (TimeoutException e) {
log.debug("{} is running too long", getDescription());
return false;
}
finally {
// Interrupt the task if it's still running and release the ExecutorService's resources
service.shutdownNow();
}
return true;
}
/**
* Terminates this process. The process is gracefully terminated (like kill -TERM
does).
*
* Note: The process may not terminate at all.
* i.e. isAlive()
may return true
for a any period after destroyGracefully()
is called.
* This method may be chained to waitFor()
if needed.
*
*
* No error is thrown if the process was already terminated.
*
*
* @return this process object.
* @throws UnsupportedOperationException if this implementation is unable to gracefully terminate the process.
*/
@Override
public AbstractProcess destroyGracefully() throws IOException, InterruptedException {
destroy(false);
return this;
}
/**
* Kills this process. The process is forcibly terminated (like kill -KILL
does).
*
* Note: The process may not terminate immediately.
* i.e. isAlive()
may return true
for a brief period after destroyForcefully()
is called.
* This method may be chained to waitFor()
if needed.
*
*
* No error is thrown if the process was already terminated.
*
*
* @return this process object.
* @throws UnsupportedOperationException if this implementation is unable to gracefully terminate the process.
*/
@Override
public AbstractProcess destroyForcefully() throws IOException, InterruptedException {
destroy(true);
return this;
}
/**
* Destroys the process either forcefully or gracefully according to the given option.
*
* Note: The process may not terminate at all.
* i.e. isAlive()
may return true
for a any period after destroy()
is called.
* This method may be chained to waitFor()
if needed.
*
*
* No error is thrown if the process was already terminated.
*
*
* @param forceful true
if the process must be destroyed forcefully (like kill -KILL
),
* false
if it must be destroyed gracefully (like kill -TERM
).
* @return this process object.
* @throws UnsupportedOperationException if this implementation is unable to terminate the process with this forceful
value.
*/
public abstract void destroy(boolean forceful) throws IOException, InterruptedException;
}