001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020package org.apache.commons.exec;
021
022import java.io.File;
023import java.io.IOException;
024import java.nio.file.Path;
025import java.util.Map;
026
027/**
028 * The main abstraction to start an external process.
029 *
030 * The interface allows to:
031 * <ul>
032 * <li>set a current working directory for the subprocess</li>
033 * <li>provide a set of environment variables passed to the subprocess</li>
034 * <li>capture the subprocess output of stdout and stderr using an ExecuteStreamHandler</li>
035 * <li>kill long-running processes using an ExecuteWatchdog</li>
036 * <li>define a set of expected exit values</li>
037 * <li>terminate any started processes when the main process is terminating using a ProcessDestroyer</li>
038 * </ul>
039 * <p>
040 * The following example shows the basic usage:
041 * </p>
042 *
043 * <pre>
044 * Executor exec = DefaultExecutor.builder().get();
045 * CommandLine cl = new CommandLine("ls -l");
046 * int exitValue = exec.execute(cl);
047 * </pre>
048 */
049
050public interface Executor {
051
052    /** Invalid exit code. */
053    int INVALID_EXITVALUE = 0xdeadbeef;
054
055    /**
056     * Executes a command synchronously. The child process inherits all environment variables of the parent process.
057     *
058     * @param command the command to execute.
059     * @return process exit value.
060     * @throws ExecuteException execution of subprocess failed or the subprocess returned an exit value indicating a failure {@link Executor#setExitValue(int)}.
061     * @throws IOException      If an I/O error occurs.
062     */
063    int execute(CommandLine command) throws ExecuteException, IOException;
064
065    /**
066     * Executes a command asynchronously. The child process inherits all environment variables of the parent process. Result provided to callback handler.
067     *
068     * @param command the command to execute.
069     * @param handler capture process termination and exit code.
070     * @throws ExecuteException execution of subprocess failed.
071     * @throws IOException      If an I/O error occurs.
072     */
073    void execute(CommandLine command, ExecuteResultHandler handler) throws ExecuteException, IOException;
074
075    /**
076     * Executes a command synchronously.
077     *
078     * @param command     the command to execute.
079     * @param environment The environment for the new process. If null, the environment of the current process is used.
080     * @return process exit value.
081     * @throws ExecuteException execution of subprocess failed or the subprocess returned an exit value indicating a failure {@link Executor#setExitValue(int)}.
082     * @throws IOException      If an I/O error occurs.
083     */
084    int execute(CommandLine command, Map<String, String> environment) throws ExecuteException, IOException;
085
086    /**
087     * Executes a command asynchronously. The child process inherits all environment variables of the parent process. Result provided to callback handler.
088     *
089     * @param command     the command to execute.
090     * @param environment The environment for the new process. If null, the environment of the current process is used.
091     * @param handler     capture process termination and exit code.
092     * @throws ExecuteException execution of subprocess failed.
093     * @throws IOException      If an I/O error occurs.
094     */
095    void execute(CommandLine command, Map<String, String> environment, ExecuteResultHandler handler) throws ExecuteException, IOException;
096
097    /**
098     * Sets the handler for cleanup of started processes if the main process is going to terminate.
099     *
100     * @return the ProcessDestroyer.
101     */
102    ProcessDestroyer getProcessDestroyer();
103
104    /**
105     * Gets the StreamHandler used for providing input and retrieving the output.
106     *
107     * @return the StreamHandler.
108     */
109    ExecuteStreamHandler getStreamHandler();
110
111    /**
112     * Gets the watchdog used to kill of processes running, typically, too long time.
113     *
114     * @return the watchdog.
115     */
116    ExecuteWatchdog getWatchdog();
117
118    /**
119     * Gets the working directory of the created process.
120     *
121     * @return the working directory.
122     */
123    File getWorkingDirectory();
124
125    /**
126     * Gets the working directory of the created process.
127     *
128     * @return the working directory.
129     * @since 1.5.0
130     */
131    default Path getWorkingDirectoryPath() {
132        return getWorkingDirectory().toPath();
133    }
134
135    /**
136     * Tests whether {@code exitValue} signals a failure. If no exit values are set than the default conventions of the OS is used. e.g. most OS regard an exit
137     * code of '0' as successful execution and everything else as failure.
138     *
139     * @param exitValue the exit value (return code) to be checked.
140     * @return {@code true} if {@code exitValue} signals a failure.
141     */
142    boolean isFailure(int exitValue);
143
144    /**
145     * Sets the {@code exitValue} of the process to be considered successful. If a different exit value is returned by the process then
146     * {@link org.apache.commons.exec.Executor#execute(CommandLine)} will throw an {@link org.apache.commons.exec.ExecuteException}.
147     *
148     * @param value the exit code representing successful execution.
149     */
150    void setExitValue(int value);
151
152    /**
153     * Sets a list of {@code exitValue} of the process to be considered successful. The caller can pass one of the following values.
154     * <ul>
155     * <li>an array of exit values to be considered successful</li>
156     * <li>an empty array for auto-detect of successful exit codes relying on {@link org.apache.commons.exec.Executor#isFailure(int)}</li>
157     * <li>null to indicate to skip checking of exit codes</li>
158     * </ul>
159     *
160     * If an undefined exit value is returned by the process then {@link org.apache.commons.exec.Executor#execute(CommandLine)} will throw an
161     * {@link org.apache.commons.exec.ExecuteException}.
162     *
163     * @param values a list of the exit codes.
164     */
165    void setExitValues(int[] values);
166
167    /**
168     * Sets the handler for cleanup of started processes if the main process is going to terminate.
169     *
170     * @param processDestroyer the ProcessDestroyer.
171     */
172    void setProcessDestroyer(ProcessDestroyer processDestroyer);
173
174    /**
175     * Sets a custom the StreamHandler used for providing input and retrieving the output. If you don't provide a proper stream handler the executed process
176     * might block when writing to stdout and/or stderr (see {@link Process Process}).
177     *
178     * @param streamHandler the stream handler.
179     */
180    void setStreamHandler(ExecuteStreamHandler streamHandler);
181
182    /**
183     * Sets the watchdog used to kill of processes running, typically, too long time.
184     *
185     * @param watchDog the watchdog.
186     */
187    void setWatchdog(ExecuteWatchdog watchDog);
188
189    /**
190     * Sets the working directory of the created process. The working directory must exist when you start the process.
191     *
192     * @param dir the working directory.
193     */
194    void setWorkingDirectory(File dir);
195
196}