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 *      https://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
018package org.apache.commons.exec;
019
020import java.io.File;
021import java.io.IOException;
022import java.nio.file.Path;
023import java.util.Map;
024
025/**
026 * The main abstraction to start an external process.
027 *
028 * The interface allows to:
029 * <ul>
030 * <li>set a current working directory for the subprocess</li>
031 * <li>provide a set of environment variables passed to the subprocess</li>
032 * <li>capture the subprocess output of stdout and stderr using an ExecuteStreamHandler</li>
033 * <li>kill long-running processes using an ExecuteWatchdog</li>
034 * <li>define a set of expected exit values</li>
035 * <li>terminate any started processes when the main process is terminating using a ProcessDestroyer</li>
036 * </ul>
037 * <p>
038 * The following example shows the basic usage:
039 * </p>
040 *
041 * <pre>
042 * Executor exec = DefaultExecutor.builder().get();
043 * CommandLine cl = new CommandLine("ls -l");
044 * int exitvalue = exec.execute(cl);
045 * </pre>
046 */
047
048public interface Executor {
049
050    /** Invalid exit code. */
051    int INVALID_EXITVALUE = 0xdeadbeef;
052
053    /**
054     * Executes a command synchronously. The child process inherits all environment variables of the parent process.
055     *
056     * @param command the command to execute.
057     * @return process exit value.
058     * @throws ExecuteException execution of subprocess failed or the subprocess returned a exit value indicating a failure {@link Executor#setExitValue(int)}.
059     * @throws IOException      If an I/O error occurs.
060     */
061    int execute(CommandLine command) throws ExecuteException, IOException;
062
063    /**
064     * Executes a command asynchronously. The child process inherits all environment variables of the parent process. Result provided to callback handler.
065     *
066     * @param command the command to execute.
067     * @param handler capture process termination and exit code.
068     * @throws ExecuteException execution of subprocess failed.
069     * @throws IOException      If an I/O error occurs.
070     */
071    void execute(CommandLine command, ExecuteResultHandler handler) throws ExecuteException, IOException;
072
073    /**
074     * Executes a command synchronously.
075     *
076     * @param command     the command to execute.
077     * @param environment The environment for the new process. If null, the environment of the current process is used.
078     * @return process exit value.
079     * @throws ExecuteException execution of subprocess failed or the subprocess returned a exit value indicating a failure {@link Executor#setExitValue(int)}.
080     * @throws IOException      If an I/O error occurs.
081     */
082    int execute(CommandLine command, Map<String, String> environment) throws ExecuteException, IOException;
083
084    /**
085     * Executes a command asynchronously. The child process inherits all environment variables of the parent process. Result provided to callback handler.
086     *
087     * @param command     the command to execute.
088     * @param environment The environment for the new process. If null, the environment of the current process is used.
089     * @param handler     capture process termination and exit code.
090     * @throws ExecuteException execution of subprocess failed.
091     * @throws IOException      If an I/O error occurs.
092     */
093    void execute(CommandLine command, Map<String, String> environment, ExecuteResultHandler handler) throws ExecuteException, IOException;
094
095    /**
096     * Sets the handler for cleanup of started processes if the main process is going to terminate.
097     *
098     * @return the ProcessDestroyer.
099     */
100    ProcessDestroyer getProcessDestroyer();
101
102    /**
103     * Gets the StreamHandler used for providing input and retrieving the output.
104     *
105     * @return the StreamHandler.
106     */
107    ExecuteStreamHandler getStreamHandler();
108
109    /**
110     * Gets the watchdog used to kill of processes running, typically, too long time.
111     *
112     * @return the watchdog.
113     */
114    ExecuteWatchdog getWatchdog();
115
116    /**
117     * Gets the working directory of the created process.
118     *
119     * @return the working directory.
120     */
121    File getWorkingDirectory();
122
123    /**
124     * Gets the working directory of the created process.
125     *
126     * @return the working directory.
127     * @since 1.5.0
128     */
129    default Path getWorkingDirectoryPath() {
130        return getWorkingDirectory().toPath();
131    }
132
133    /**
134     * 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
135     * code of '0' as successful execution and everything else as failure.
136     *
137     * @param exitValue the exit value (return code) to be checked.
138     * @return {@code true} if {@code exitValue} signals a failure.
139     */
140    boolean isFailure(final int exitValue);
141
142    /**
143     * Sets the {@code exitValue} of the process to be considered successful. If a different exit value is returned by the process then
144     * {@link org.apache.commons.exec.Executor#execute(CommandLine)} will throw an {@link org.apache.commons.exec.ExecuteException}.
145     *
146     * @param value the exit code representing successful execution.
147     */
148    void setExitValue(final int value);
149
150    /**
151     * Sets a list of {@code exitValue} of the process to be considered successful. The caller can pass one of the following values.
152     * <ul>
153     * <li>an array of exit values to be considered successful</li>
154     * <li>an empty array for auto-detect of successful exit codes relying on {@link org.apache.commons.exec.Executor#isFailure(int)}</li>
155     * <li>null to indicate to skip checking of exit codes</li>
156     * </ul>
157     *
158     * If an undefined exit value is returned by the process then {@link org.apache.commons.exec.Executor#execute(CommandLine)} will throw an
159     * {@link org.apache.commons.exec.ExecuteException}.
160     *
161     * @param values a list of the exit codes.
162     */
163    void setExitValues(final int[] values);
164
165    /**
166     * Sets the handler for cleanup of started processes if the main process is going to terminate.
167     *
168     * @param processDestroyer the ProcessDestroyer.
169     */
170    void setProcessDestroyer(ProcessDestroyer processDestroyer);
171
172    /**
173     * 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
174     * might block when writing to stdout and/or stderr (see {@link Process Process}).
175     *
176     * @param streamHandler the stream handler.
177     */
178    void setStreamHandler(ExecuteStreamHandler streamHandler);
179
180    /**
181     * Sets the watchdog used to kill of processes running, typically, too long time.
182     *
183     * @param watchDog the watchdog.
184     */
185    void setWatchdog(ExecuteWatchdog watchDog);
186
187    /**
188     * Sets the working directory of the created process. The working directory must exist when you start the process.
189     *
190     * @param dir the working directory.
191     */
192    void setWorkingDirectory(File dir);
193
194}