View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.context.task;
21  
22  import org.apache.commons.exec.CommandLine;
23  import org.apache.commons.exec.DefaultExecutor;
24  import org.apache.commons.exec.ExecuteWatchdog;
25  import org.apache.commons.exec.PumpStreamHandler;
26  import org.waarp.common.logging.WaarpLogger;
27  import org.waarp.common.logging.WaarpLoggerFactory;
28  import org.waarp.openr66.context.R66Session;
29  import org.waarp.openr66.context.task.localexec.LocalExecClient;
30  import org.waarp.openr66.protocol.configuration.Configuration;
31  
32  import java.io.PipedInputStream;
33  import java.io.PipedOutputStream;
34  
35  /**
36   * Execute an external command
37   */
38  public class ExecTask extends AbstractExecTask {
39  
40    /**
41     * Internal Logger
42     */
43    private static final WaarpLogger logger =
44        WaarpLoggerFactory.getLogger(ExecTask.class);
45  
46    /**
47     * @param argRule
48     * @param delay
49     * @param argTransfer
50     * @param session
51     */
52    public ExecTask(final String argRule, final int delay,
53                    final String argTransfer, final R66Session session) {
54      super(TaskType.EXEC, delay, argRule, argTransfer, session);
55    }
56  
57    @Override
58    public final void run() {
59      /*
60       * First apply all replacements and format to argRule from context and argTransfer. Will call exec (from first
61       * element of resulting string) with arguments as the following value from the replacements. Return 0 if OK,
62       * else 1 for a warning else as an error. No change should be done in the FILENAME
63       */
64      logger.debug("Exec with " + argRule + ':' + argTransfer + " and {}",
65                   session);
66      final String finalname = applyTransferSubstitutions(argRule);
67  
68      // Check if the execution will be done through LocalExec daemon
69      if (Configuration.configuration.isUseLocalExec() && useLocalExec) {
70        final LocalExecClient localExecClient = new LocalExecClient();
71        if (localExecClient.connect()) {
72          localExecClient.runOneCommand(finalname, delay, waitForValidation,
73                                        futureCompletion);
74          localExecClient.disconnect();
75          return;
76        } // else continue
77      }
78  
79      final PrepareCommandExec prepareCommandExec =
80          new PrepareCommandExec(this, finalname, true,
81                                 waitForValidation).invoke();
82      if (prepareCommandExec.isError()) {
83        return;
84      }
85      final CommandLine commandLine = prepareCommandExec.getCommandLine();
86      final DefaultExecutor defaultExecutor =
87          prepareCommandExec.getDefaultExecutor();
88      final PipedInputStream inputStream = prepareCommandExec.getInputStream();
89      final PipedOutputStream outputStream = prepareCommandExec.getOutputStream();
90      final PumpStreamHandler pumpStreamHandler =
91          prepareCommandExec.getPumpStreamHandler();
92      final ExecuteWatchdog watchdog = prepareCommandExec.getWatchdog();
93  
94      if (!waitForValidation) {
95        // Do not wait for validation
96        futureCompletion.setSuccess();
97        logger.info("Exec will start but no WAIT with {}", commandLine);
98      }
99  
100     final ExecuteCommand executeCommand =
101         new ExecuteCommand(this, commandLine, defaultExecutor, inputStream,
102                            outputStream, pumpStreamHandler, null).invoke();
103     if (executeCommand.isError()) {
104       return;
105     }
106     int status = executeCommand.getStatus();
107 
108     if (defaultExecutor.isFailure(status) && watchdog != null &&
109         watchdog.killedProcess()) {
110       // kill by the watchdoc (time out)
111       logger.error("Exec is in Time Out");
112       status = -1;
113     }
114     if (status == 0) {
115       if (waitForValidation) {
116         futureCompletion.setSuccess();
117       }
118       logger.info("Exec OK with {}", commandLine);
119     } else if (status == 1) {
120       logger.warn("Exec in warning with " + commandLine);
121       if (waitForValidation) {
122         futureCompletion.setSuccess();
123       }
124     } else {
125       logger.error("Status: " + status + " Exec in error with " + commandLine);
126       if (waitForValidation) {
127         futureCompletion.cancel();
128       }
129     }
130   }
131 
132   @Override
133   final void finalizeFromError(final Runnable threadReader, final int status,
134                                final CommandLine commandLine,
135                                final Exception e) {
136     logger.error("Status: " + status + " Exec in error with " + commandLine +
137                  " returns " + e.getMessage());
138     if (waitForValidation) {
139       futureCompletion.setFailure(e);
140     }
141   }
142 }