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.waarp.common.exception.InvalidArgumentException;
23  import org.waarp.common.logging.SysErrLogger;
24  import org.waarp.common.logging.WaarpLogger;
25  import org.waarp.common.logging.WaarpLoggerFactory;
26  import org.waarp.common.utility.ParametersChecker;
27  import org.waarp.common.utility.WaarpSystemUtil;
28  import org.waarp.common.utility.WaarpThreadFactory;
29  import org.waarp.openr66.context.ErrorCode;
30  import org.waarp.openr66.context.R66Result;
31  import org.waarp.openr66.context.R66Session;
32  import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
33  
34  import java.util.concurrent.ExecutorService;
35  import java.util.concurrent.Executors;
36  import java.util.concurrent.TimeUnit;
37  
38  /**
39   * Execute a Java command through Class.forName call
40   */
41  public class ExecJavaTask extends AbstractTask {
42    protected boolean businessRequest;
43  
44    /**
45     * Internal Logger
46     */
47    private static final WaarpLogger logger =
48        WaarpLoggerFactory.getLogger(ExecJavaTask.class);
49  
50    /**
51     * @param argRule
52     * @param delay
53     * @param argTransfer
54     * @param session
55     */
56    public ExecJavaTask(final String argRule, final int delay,
57                        final String argTransfer, final R66Session session) {
58      super(TaskType.EXECJAVA, delay, argRule, argTransfer, session);
59    }
60  
61    /**
62     * Set the type
63     *
64     * @param businessRequest
65     */
66    public final void setBusinessRequest(final boolean businessRequest) {
67      this.businessRequest = businessRequest;
68    }
69  
70    @Override
71    public final void run() {
72      if (argRule == null) {
73        logger.error(
74            "ExecJava cannot be done with " + argRule + ':' + argTransfer +
75            " and " + session);
76        futureCompletion.setFailure(
77            new OpenR66ProtocolSystemException("Exec Java cannot be done"));
78        return;
79      }
80      /*
81       * First apply all replacements and format to argRule from context and argTransfer. Will call exec (from first
82       * element of resulting string) with arguments as the following value from the replacements. Return 0 if OK,
83       * else 1 for a warning else as an error. No change should be done in the FILENAME
84       */
85      String finalname = argRule;
86      if (argTransfer != null) {
87        finalname = getReplacedValue(finalname, BLANK.split(argTransfer));
88      }
89      // First get the Class Name
90      final String[] args = BLANK.split(finalname);
91      final String className = args[0];
92      try {
93        ParametersChecker.checkSanityString(className);
94      } catch (final InvalidArgumentException e) {
95        logger.error("ExecJava command is not correct: {}", e.getMessage());
96        final R66Result result =
97            new R66Result(session, false, ErrorCode.CommandNotFound,
98                          session.getRunner());
99        futureCompletion.setResult(result);
100       futureCompletion.cancel();
101       return;
102     }
103     final boolean isSpooled =
104         className.equals(SpooledInformTask.class.getName());
105     if (isSpooled) {
106       logger.debug("Exec with {}:{} and {}", className, argTransfer, session);
107     } else {
108       logger.debug("Exec with {}:{} and {}", argRule, argTransfer, session);
109     }
110     final R66Runnable runnable;
111     try {
112       runnable = (R66Runnable) WaarpSystemUtil.newInstance(className);//NOSONAR
113     } catch (final Exception e) {
114       logger.error("ExecJava command is not available: " + className + ": {}",
115                    e.getMessage());
116       final R66Result result =
117           new R66Result(session, false, ErrorCode.CommandNotFound,
118                         session.getRunner());
119       futureCompletion.setResult(result);
120       futureCompletion.cancel();
121       return;
122     }
123     if (businessRequest) {
124       final boolean istovalidate = Boolean.parseBoolean(args[args.length - 1]);
125       runnable.setArgs(session, waitForValidation, useLocalExec, delay,
126                        className,
127                        finalname.substring(finalname.indexOf(' ') + 1,
128                                            finalname.lastIndexOf(' ')),
129                        businessRequest, istovalidate);
130     } else {
131       runnable.setArgs(session, waitForValidation, useLocalExec, delay,
132                        className, finalname.substring(className.length() + 1),
133                        businessRequest, false);
134     }
135     logger.debug("{} {}", className, runnable.getClass().getName());
136     if (!waitForValidation) {
137       // Do not wait for validation
138       futureCompletion.setSuccess();
139       logger.info("Exec will start but no WAIT with {}", runnable);
140     }
141     final int status;
142     if (waitForValidation && delay <= 100) {
143       runnable.run();
144       status = runnable.getFinalStatus();
145     } else {
146       final ExecutorService executorService = Executors.newSingleThreadExecutor(
147           new WaarpThreadFactory("JavaExecutor"));
148       executorService.execute(runnable);
149       try {
150         Thread.yield();
151         executorService.shutdown();
152         if (waitForValidation) {
153           if (delay > 100) {
154             if (!executorService.awaitTermination(delay,
155                                                   TimeUnit.MILLISECONDS)) {
156               executorService.shutdownNow();
157               logger.error("Exec is in Time Out");
158               status = -1;
159             } else {
160               status = runnable.getFinalStatus();
161             }
162           } else {
163             while (!executorService.awaitTermination(30, TimeUnit.SECONDS)) {
164               // nothing
165             }
166             status = runnable.getFinalStatus();
167           }
168         } else {
169           while (!executorService.awaitTermination(30, TimeUnit.SECONDS)) {
170             // nothing
171           }
172           status = runnable.getFinalStatus();
173         }
174       } catch (final InterruptedException e) {//NOSONAR
175         SysErrLogger.FAKE_LOGGER.ignoreLog(e);
176         logger.error(
177             "Status: " + e.getMessage() + " \t Exec in error with " + runnable);
178         if (waitForValidation) {
179           futureCompletion.cancel();
180         }
181         return;
182       }
183     }
184     if (status == 0) {
185       if (waitForValidation) {
186         final R66Result result =
187             new R66Result(session, true, ErrorCode.CompleteOk, null);
188         result.setOther(runnable.toString());
189         futureCompletion.setResult(result);
190         futureCompletion.setSuccess();
191       }
192       if (isSpooled) {
193         logger.info("Exec OK with {}", className);
194       } else {
195         logger.info("Exec OK with {}", runnable);
196       }
197     } else if (status == 1) {
198       logger.warn("Exec in warning with " + runnable);
199       if (waitForValidation) {
200         final R66Result result =
201             new R66Result(session, true, ErrorCode.CompleteOk, null);
202         result.setOther(runnable.toString());
203         futureCompletion.setResult(result);
204         futureCompletion.setSuccess();
205       }
206     } else {
207       logger.error("Status: " + status + " Exec in error with " + runnable);
208       if (waitForValidation) {
209         futureCompletion.cancel();
210       }
211     }
212   }
213 
214 }