com.anrisoftware.globalpom.exec.core.DefaultCommandExec Maven / Gradle / Ivy
/*
* Copyright 2014-2015 Erwin Müller
*
* This file is part of globalpomutils-exec.
*
* globalpomutils-exec is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* globalpomutils-exec is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with globalpomutils-exec. If not, see .
*/
package com.anrisoftware.globalpom.exec.core;
import static com.anrisoftware.globalpom.exec.core.DefaultProcessModule.getCommandExecFactory;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Observer;
import java.util.concurrent.Future;
import javax.inject.Inject;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import com.anrisoftware.globalpom.exec.api.CommandExec;
import com.anrisoftware.globalpom.exec.api.CommandExecException;
import com.anrisoftware.globalpom.exec.api.CommandExecFactory;
import com.anrisoftware.globalpom.exec.api.CommandInput;
import com.anrisoftware.globalpom.exec.api.CommandLine;
import com.anrisoftware.globalpom.exec.api.CommandOutput;
import com.anrisoftware.globalpom.exec.api.ProcessTask;
import com.anrisoftware.globalpom.threads.api.ListenableFuture.Status;
import com.anrisoftware.globalpom.threads.api.Threads;
/**
* Executes an external command.
*
* @author Erwin Mueller, [email protected]
* @since 1.11
*/
public final class DefaultCommandExec implements CommandExec {
/**
* @see CommandExecFactory#create()
*/
public static CommandExec createCommandExec() {
return getCommandExecFactory().create();
}
private final List observers;
@Inject
private DefaultCommandExecLogger log;
@Inject
private DefaultProcessTaskFactory processTaskFactory;
private Threads threads;
private CommandOutput output;
private CommandOutput error;
private CommandInput input;
private int[] exitCodes;
private boolean destroyOnTimeout;
DefaultCommandExec() {
this.exitCodes = null;
this.destroyOnTimeout = true;
this.observers = new ArrayList();
}
@Override
public void setThreads(Threads threads) {
this.threads = threads;
}
@Override
public void setCommandOutput(CommandOutput output) {
this.output = output;
}
@Override
public void setCommandError(CommandOutput error) {
this.error = error;
}
@Override
public void setCommandInput(CommandInput input) {
this.input = input;
}
@Override
public void setExitCode(int... codes) {
this.exitCodes = codes;
}
@Override
public void setDestroyOnTimeout(boolean flag) {
this.destroyOnTimeout = flag;
}
@Override
public void setObserver(Observer... observer) {
this.observers.addAll(Arrays.asList(observer));
}
@Override
public Future exec(CommandLine commandLine,
PropertyChangeListener... listeners) throws CommandExecException {
try {
ProcessTask task = createProcessTask(commandLine, observers);
return threads.submit(task, setupListener(task, listeners));
} catch (IOException e) {
throw log.errorExecuteCommand(this, e, commandLine);
}
}
private ProcessTask createProcessTask(CommandLine commandLine,
List observers) throws IOException {
DefaultProcessTask task = processTaskFactory.create(commandLine);
task.setThreads(threads);
task.addObserver(observers.toArray(new Observer[] {}));
if (output != null) {
task.setCommandOutput(output.clone());
}
if (error != null) {
task.setCommandError(error.clone());
}
if (input != null) {
task.setCommandInput(input.clone());
}
task.setExitCodes(exitCodes);
return task;
}
private PropertyChangeListener[] setupListener(ProcessTask task,
PropertyChangeListener... l) {
return destroyOnTimeout ? addTimeoutListener(task, l) : l;
}
private PropertyChangeListener[] addTimeoutListener(final ProcessTask task,
PropertyChangeListener... listeners) {
return ArrayUtils.add(listeners, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
Status status = (Status) evt.getNewValue();
if (status == Status.TIMEOUT) {
task.destroy();
}
}
});
}
@Override
public String toString() {
return new ToStringBuilder(this).toString();
}
}