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.waarp.common.json.JsonHandler;
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.openr66.client.SubmitTransfer;
28  import org.waarp.openr66.client.TransferArgs;
29  import org.waarp.openr66.context.R66Session;
30  import org.waarp.openr66.context.task.exception.OpenR66RunnerErrorException;
31  import org.waarp.openr66.database.DbConstantR66;
32  import org.waarp.openr66.database.data.DbTaskRunner;
33  import org.waarp.openr66.protocol.utils.R66Future;
34  
35  import java.util.HashMap;
36  import java.util.Map;
37  
38  /**
39   * Transfer task:<br>
40   * <p>
41   * Result of arguments will be as r66send command.<br>
42   * Format is like r66send command in any order except "-info" which should be
43   * the last item, and "-copyinfo"
44   * will copy at first place the original transfer information as the new one,
45   * while still having the
46   * possibility to add new informations through "-info":<br>
47   * "-file filepath -to requestedHost -rule rule [-md5] [-start yyyyMMddHHmmss or
48   * -delay (delay or +delay)]
49   * [-copyinfo] [-info information]" <br>
50   * <br>
51   * INFO is the only one field that can contains blank character and must be
52   * the last field.<br>
53   * <br>
54   * Transfer arguments:<br>
55   * <br>
56   * -to <arg>        Specify the requested Host<br>
57   * (-id <arg>|      Specify the id of transfer<br>
58   * (-file <arg>     Specify the file path to operate on<br>
59   * -rule <arg>))    Specify the Rule<br>
60   * [-block <arg>]   Specify the block size<br>
61   * [-nofollow]      Specify the transfer should not integrate a FOLLOW id<br>
62   * [-md5]           Specify the option to have a hash computed for the
63   * transfer<br>
64   * [-delay <arg>]   Specify the delay time as an epoch time or '+' a delay in ms<br>
65   * [-start <arg>]   Specify the start time as yyyyMMddHHmmss<br>
66   * [-copyinfo]      Specify to copy the original transfer information in
67   * front position back to the new transfer information (eventually in
68   * addition an added transfer information from -info option)<br>
69   * [-info <arg>)    Specify the transfer information (generally in last position)<br>
70   * [-nolog]         Specify to not log anything included database once the
71   * transfer is done<br>
72   * [-notlogWarn |   Specify to log final result as Info if OK<br>
73   * -logWarn]        Specify to log final result as Warn if OK<br>
74   */
75  public class TransferTask extends AbstractTask {
76    /**
77     * Internal Logger
78     */
79    private static final WaarpLogger logger =
80        WaarpLoggerFactory.getLogger(TransferTask.class);
81  
82    /**
83     * @param argRule
84     * @param delay
85     * @param argTransfer
86     * @param session
87     */
88    public TransferTask(final String argRule, final int delay,
89                        final String argTransfer, final R66Session session) {
90      super(TaskType.TRANSFER, delay, argRule, argTransfer, session);
91    }
92  
93    @Override
94    public final void run() {
95      logger.info("Transfer with {}}:{} and {}", argRule, argTransfer, session);
96      String finalname = applyTransferSubstitutions(argRule);
97  
98      finalname = finalname.replaceAll("#([A-Z]+)#", "\\${$1}");
99      final CommandLine commandLine = new CommandLine("dummy");
100     commandLine.setSubstitutionMap(getSubstitutionMap());
101     commandLine.addArguments(finalname, false);
102     final String[] args = commandLine.getArguments();
103 
104     if (args.length < 6) {
105       futureCompletion.setFailure(
106           new OpenR66RunnerErrorException("Not enough argument in Transfer"));
107       return;
108     }
109     final TransferArgs transferArgs =
110         TransferArgs.getParamsInternal(0, args, false);
111     final DbTaskRunner taskRunner = session.getRunner();
112     if (transferArgs != null) {
113       String copied = null;
114       for (final String arg : args) {
115         if ("-copyinfo".equalsIgnoreCase(arg)) {
116           copied = taskRunner.getFileInformation();
117           break;
118         }
119       }
120       // Force to get follow Id if present (and other elements from map) if
121       // not already copied
122       final String follow = taskRunner.getFollowId();
123       if (copied == null && ParametersChecker.isNotEmpty(follow) &&
124           !transferArgs.getTransferInfo()
125                        .contains(TransferArgs.FOLLOW_JSON_KEY)) {
126         transferArgs.setFollowId(follow);
127         final Map<String, Long> map = new HashMap<String, Long>();
128         map.put(TransferArgs.FOLLOW_JSON_KEY, Long.parseLong(follow));
129         copied = JsonHandler.writeAsStringEscaped(map);
130       }
131       TransferArgs.getAllInfo(transferArgs, 0, args, copied);
132     } else {
133       logger.error("Not enough argument in Transfer");
134       futureCompletion.setFailure(
135           new OpenR66RunnerErrorException("Not enough argument in Transfer"));
136       return;
137     }
138     logger.debug("TransferArgs: {} Rule: {} Filename: {}",
139                  transferArgs.getTransferInfo(), transferArgs.getRulename(),
140                  transferArgs.getFilename());
141     final R66Future future = new R66Future(true);
142     final SubmitTransfer transaction =
143         new SubmitTransfer(future, transferArgs.getRemoteHost(),
144                            transferArgs.getFilename(),
145                            transferArgs.getRulename(),
146                            transferArgs.getTransferInfo(), transferArgs.isMD5(),
147                            transferArgs.getBlockSize(),
148                            DbConstantR66.ILLEGALVALUE,
149                            transferArgs.getStartTime());
150     transaction.run();
151     future.awaitOrInterruptible();
152     final DbTaskRunner runner;
153     if (future.isSuccess()) {
154       futureCompletion.setResult(future.getResult());
155       runner = future.getResult().getRunner();
156       if (logger.isInfoEnabled()) {
157         logger.info(
158             "Prepare transfer in     SUCCESS     " + runner.toShortString() +
159             "     <REMOTE>" + transferArgs.getRemoteHost() + "</REMOTE>");
160       }
161       futureCompletion.setSuccess();
162     } else {
163       if (future.getResult() != null) {
164         futureCompletion.setResult(future.getResult());
165         runner = future.getResult().getRunner();
166       } else {
167         runner = null;
168       }
169       if (runner != null) {
170         if (future.getCause() == null) {
171           futureCompletion.cancel();
172         } else {
173           futureCompletion.setFailure(future.getCause());
174         }
175         logger.error(
176             "Prepare transfer in     FAILURE      " + runner.toShortString() +
177             "     <REMOTE>" + transferArgs.getRemoteHost() + "</REMOTE>",
178             future.getCause());
179       } else {
180         if (future.getCause() == null) {
181           futureCompletion.cancel();
182         } else {
183           futureCompletion.setFailure(future.getCause());
184         }
185         logger.error("Prepare transfer in     FAILURE without any runner back",
186                      future.getCause());
187       }
188     }
189   }
190 
191 }