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.protocol.utils;
21  
22  import org.waarp.common.command.exception.CommandAbstractException;
23  import org.waarp.common.database.DbPreparedStatement;
24  import org.waarp.common.database.DbSession;
25  import org.waarp.common.database.data.AbstractDbData.UpdatedInfo;
26  import org.waarp.common.database.exception.WaarpDatabaseException;
27  import org.waarp.common.logging.WaarpLogger;
28  import org.waarp.common.logging.WaarpLoggerFactory;
29  import org.waarp.openr66.client.RequestTransfer;
30  import org.waarp.openr66.commander.ClientRunner;
31  import org.waarp.openr66.commander.CommanderNoDb;
32  import org.waarp.openr66.context.ErrorCode;
33  import org.waarp.openr66.context.R66FiniteDualStates;
34  import org.waarp.openr66.context.R66Result;
35  import org.waarp.openr66.context.R66Session;
36  import org.waarp.openr66.context.authentication.R66Auth;
37  import org.waarp.openr66.context.filesystem.R66File;
38  import org.waarp.openr66.context.task.exception.OpenR66RunnerErrorException;
39  import org.waarp.openr66.database.data.DbHostAuth;
40  import org.waarp.openr66.database.data.DbTaskRunner;
41  import org.waarp.openr66.database.data.DbTaskRunner.TASKSTEP;
42  import org.waarp.openr66.protocol.configuration.Configuration;
43  import org.waarp.openr66.protocol.configuration.Messages;
44  import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
45  import org.waarp.openr66.protocol.localhandler.LocalChannelReference;
46  import org.waarp.openr66.protocol.localhandler.LocalServerHandler;
47  import org.waarp.openr66.protocol.localhandler.packet.ErrorPacket;
48  
49  import java.sql.Timestamp;
50  import java.util.Map;
51  
52  /**
53   * Utility class for transfers
54   */
55  public final class TransferUtils {
56    /**
57     * Internal Logger
58     */
59    private static final WaarpLogger logger =
60        WaarpLoggerFactory.getLogger(TransferUtils.class);
61  
62    private TransferUtils() {
63    }
64  
65    /**
66     * Try to restart one Transfer Runner Task
67     *
68     * @param taskRunner
69     *
70     * @return the associated Result
71     */
72    public static R66Result restartTransfer(final DbTaskRunner taskRunner,
73                                            final LocalChannelReference lcr) {
74      final R66Result finalResult =
75          new R66Result(null, true, ErrorCode.InitOk, taskRunner);
76      if (lcr != null) {
77        finalResult.setCode(ErrorCode.QueryStillRunning);
78        finalResult.setOther(Messages.getString("TransferUtils.0")); //$NON-NLS-1$
79      } else {
80        if (taskRunner.isSendThrough()) {
81          // XXX FIXME TODO cannot be restarted... Really?
82        }
83        // Transfer is not running
84        // but maybe need action on database
85        try {
86          if (taskRunner.restart(true)) {
87            taskRunner.forceSaveStatus();
88            finalResult.setCode(ErrorCode.PreProcessingOk);
89            finalResult.setOther(
90                Messages.getString("TransferUtils.1")); //$NON-NLS-1$
91          } else {
92            if (taskRunner.isRequestOnRequested() &&
93                taskRunner.getGloballaststep() < TASKSTEP.POSTTASK.ordinal()) {
94              // send a VALID packet with VALID code to the requester except if client
95              final DbHostAuth host =
96                  R66Auth.getServerAuth(taskRunner.getRequester());
97              if (host == null || host.isClient()) {
98                // cannot be relaunch from there
99                finalResult.setCode(ErrorCode.ConnectionImpossible);
100               finalResult.setOther(
101                   Messages.getString("TransferUtils.2")); //$NON-NLS-1$
102               logger.warn(Messages.getString("TransferUtils.3")); //$NON-NLS-1$
103             } else {
104               final R66Future result = new R66Future(true);
105               if (logger.isInfoEnabled()) {
106                 logger.info("{}{}", Messages.getString("TransferUtils.4"),
107                             taskRunner.toShortString()); //$NON-NLS-1$
108               }
109               final RequestTransfer requestTransfer =
110                   new RequestTransfer(result, taskRunner.getSpecialId(),
111                                       taskRunner.getRequested(),
112                                       taskRunner.getRequester(), false, false,
113                                       true,
114                                       Configuration.configuration.getInternalRunner()
115                                                                  .getNetworkTransaction());
116               requestTransfer.run();
117               result.awaitOrInterruptible();
118               if (!result.isDone()) {
119                 finalResult.setCode(ErrorCode.Internal);
120                 finalResult.setOther(
121                     Messages.getString("TransferUtils.10")); //$NON-NLS-1$
122               } else {
123                 final R66Result finalValue = result.getResult();
124                 switch (finalValue.getCode()) {
125                   case QueryStillRunning:
126                     finalResult.setCode(ErrorCode.QueryStillRunning);
127                     finalResult.setOther(
128                         Messages.getString("TransferUtils.5")); //$NON-NLS-1$
129                     break;
130                   case Running:
131                     finalResult.setCode(ErrorCode.Running);
132                     finalResult.setOther(
133                         Messages.getString("TransferUtils.6")); //$NON-NLS-1$
134                     break;
135                   case PreProcessingOk:
136                     finalResult.setCode(ErrorCode.PreProcessingOk);
137                     finalResult.setOther(
138                         Messages.getString("TransferUtils.7")); //$NON-NLS-1$
139                     break;
140                   case CompleteOk:
141                     finalResult.setCode(ErrorCode.CompleteOk);
142                     finalResult.setOther(
143                         Messages.getString("TransferUtils.8")); //$NON-NLS-1$
144                     taskRunner.setPostTask();
145                     finalizeTaskWithNoSession(taskRunner, null);
146                     taskRunner.setErrorExecutionStatus(
147                         ErrorCode.QueryAlreadyFinished);
148                     taskRunner.forceSaveStatus();
149                     break;
150                   case RemoteError:
151                     finalResult.setCode(ErrorCode.RemoteError);
152                     finalResult.setOther(
153                         Messages.getString("TransferUtils.9")); //$NON-NLS-1$
154                     break;
155                   default:
156                     finalResult.setCode(ErrorCode.Internal);
157                     finalResult.setOther(
158                         Messages.getString("TransferUtils.10")); //$NON-NLS-1$
159                     break;
160                 }
161               }
162             }
163           } else {
164             finalResult.setCode(ErrorCode.CompleteOk);
165             finalResult.setOther(
166                 Messages.getString("TransferUtils.11")); //$NON-NLS-1$
167             taskRunner.setPostTask();
168             finalizeTaskWithNoSession(taskRunner, null);
169             taskRunner.setErrorExecutionStatus(ErrorCode.QueryAlreadyFinished);
170             taskRunner.forceSaveStatus();
171           }
172         }
173       } catch (final OpenR66RunnerErrorException e) {
174         finalResult.setCode(ErrorCode.PreProcessingOk);
175         finalResult.setOther(
176             Messages.getString("TransferUtils.1")); //$NON-NLS-1$
177       }
178     }
179     return finalResult;
180   }
181 
182   /**
183    * Finalize a local task since only Post action has to be done
184    *
185    * @param taskRunner
186    * @param localChannelReference
187    *
188    * @throws OpenR66RunnerErrorException
189    */
190   public static void finalizeTaskWithNoSession(final DbTaskRunner taskRunner,
191                                                final LocalChannelReference localChannelReference)
192       throws OpenR66RunnerErrorException {
193     final R66Session session = new R66Session(false);
194     session.setStatus(50);
195     final String remoteId =
196         taskRunner.isRequestOnRequested()? taskRunner.getRequester() :
197             taskRunner.getRequested();
198     session.getAuth().specialNoSessionAuth(false, remoteId);
199     session.setNoSessionRunner(taskRunner, localChannelReference);
200     if (taskRunner.isSender()) {
201       // Change dir
202       try {
203         session.getDir().changeDirectory(taskRunner.getRule().getSendPath());
204       } catch (final CommandAbstractException e) {
205         throw new OpenR66RunnerErrorException(e);
206       }
207     } else {
208       // Change dir
209       try {
210         session.getDir().changeDirectory(taskRunner.getRule().getWorkPath());
211       } catch (final CommandAbstractException e) {
212         throw new OpenR66RunnerErrorException(e);
213       }
214     }
215     try {
216       try {
217         session.setFileAfterPreRunner(false);
218       } catch (final CommandAbstractException e) {
219         throw new OpenR66RunnerErrorException(e);
220       }
221     } catch (final OpenR66RunnerErrorException e) {
222       logger.error(Messages.getString("TransferUtils.27"),
223                    taskRunner.getFilename()); //$NON-NLS-1$
224       taskRunner.changeUpdatedInfo(UpdatedInfo.INERROR);
225       taskRunner.setErrorExecutionStatus(ErrorCode.FileNotFound);
226       try {
227         taskRunner.update();
228       } catch (final WaarpDatabaseException ignored) {
229         // nothing
230       }
231       throw new OpenR66RunnerErrorException(
232           Messages.getString("TransferUtils.28"), e); //$NON-NLS-1$
233     }
234     final R66File file = session.getFile();
235     final R66Result finalValue =
236         new R66Result(null, true, ErrorCode.CompleteOk, taskRunner);
237     finalValue.setFile(file);
238     finalValue.setRunner(taskRunner);
239     taskRunner.finishTransferTask(ErrorCode.TransferOk);
240     try {
241       taskRunner.finalizeTransfer(localChannelReference, file, finalValue,
242                                   true);
243     } catch (final OpenR66ProtocolSystemException e) {
244       logger.error(Messages.getString("TransferUtils.29"),
245                    taskRunner.toShortString()); //$NON-NLS-1$
246       taskRunner.changeUpdatedInfo(UpdatedInfo.INERROR);
247       taskRunner.setErrorExecutionStatus(ErrorCode.Internal);
248       try {
249         taskRunner.update();
250       } catch (final WaarpDatabaseException ignored) {
251         // nothing
252       }
253       throw new OpenR66RunnerErrorException(
254           Messages.getString("TransferUtils.30"), e); //$NON-NLS-1$
255     }
256   }
257 
258   @SuppressWarnings("unchecked")
259   private static void stopOneTransfer(final DbTaskRunner taskRunner,
260                                       final Object map,
261                                       final R66Session session,
262                                       final String body) {
263     final LocalChannelReference lcr =
264         Configuration.configuration.getLocalTransaction()
265                                    .getFromRequest(taskRunner.getKey());
266     ErrorCode result;
267     final ErrorCode code = ErrorCode.StoppedTransfer;
268     if (lcr != null) {
269       final int rank = taskRunner.getRank();
270       lcr.sessionNewState(R66FiniteDualStates.ERROR);
271       final ErrorPacket perror =
272           new ErrorPacket(Messages.getString("TransferUtils.13") + rank,
273                           //$NON-NLS-1$
274                           code.getCode(), ErrorPacket.FORWARDCLOSECODE);
275       try {
276         // inform local instead of remote
277         LocalServerHandler.channelRead0(lcr, perror);
278       } catch (final Exception e) {
279         logger.warn("Write local packet error" + " : {}", e.getMessage());
280       }
281       result = ErrorCode.StoppedTransfer;
282     } else {
283       // Transfer is not running
284       // if in ERROR already just ignore it
285       if (taskRunner.getUpdatedInfo() == UpdatedInfo.INERROR) {
286         result = ErrorCode.TransferError;
287       } else {
288         // the database saying it is not stopped
289         result = ErrorCode.TransferError;
290         if (taskRunner.stopOrCancelRunner(code)) {
291           result = ErrorCode.StoppedTransfer;
292         }
293       }
294     }
295     final ErrorCode last = taskRunner.getErrorInfo();
296     taskRunner.setErrorExecutionStatus(result);
297     if (map != null) {
298       if (map instanceof Map) {
299         ((Map<String, String>) map).put(taskRunner.getKey(),
300                                         taskRunner.getJsonAsString());
301       } else if (map instanceof StringBuilder) {
302         ((StringBuilder) map).append(taskRunner.toSpecializedHtml(session, body,
303                                                                   lcr != null?
304                                                                       Messages.getString(
305                                                                           "HttpSslHandler.Active") :
306                                                                       Messages.getString(
307                                                                           "HttpSslHandler.NotActive")));
308       }
309     }
310     taskRunner.setErrorExecutionStatus(last);
311   }
312 
313   /**
314    * Stop all selected transfers
315    *
316    * @param dbSession
317    * @param limit
318    * @param session
319    * @param body
320    * @param startid
321    * @param stopid
322    * @param tstart
323    * @param tstop
324    * @param rule
325    * @param req
326    * @param pending
327    * @param transfer
328    * @param error
329    *
330    * @return the associated StringBuilder if the one given as parameter is not
331    *     null
332    */
333   public static void stopSelectedTransfers(final DbSession dbSession,
334                                            final int limit, final Object map,
335                                            final R66Session session,
336                                            final String body,
337                                            final String startid,
338                                            final String stopid,
339                                            final Timestamp tstart,
340                                            final Timestamp tstop,
341                                            final String rule, final String req,
342                                            final boolean pending,
343                                            final boolean transfer,
344                                            final boolean error) {
345     stopSelectedTransfers(dbSession, limit, map, session, body, startid, stopid,
346                           tstart, tstop, rule, req, pending, transfer, error,
347                           null);
348   }
349 
350   public static void stopSelectedTransfers(final DbSession dbSession,
351                                            final int limit, final Object map,
352                                            final R66Session session,
353                                            final String body,
354                                            final String startid,
355                                            final String stopid,
356                                            final Timestamp tstart,
357                                            final Timestamp tstop,
358                                            final String rule, final String req,
359                                            final boolean pending,
360                                            final boolean transfer,
361                                            final boolean error,
362                                            final String host) {
363     if (dbSession == null || dbSession.isDisActive()) {
364       // do it without DB
365       if (ClientRunner.activeRunners != null) {
366         for (final ClientRunner runner : ClientRunner.activeRunners) {
367           final DbTaskRunner taskRunner = runner.getTaskRunner();
368           stopOneTransfer(taskRunner, map, session, body);
369         }
370       }
371       if (CommanderNoDb.todoList != null) {
372         CommanderNoDb.todoList.clear();
373       }
374       return;
375     }
376     DbPreparedStatement preparedStatement = null;
377     try {
378       preparedStatement =
379           DbTaskRunner.getFilterPrepareStatement(dbSession, limit, true,
380                                                  startid, stopid, tstart, tstop,
381                                                  rule, req, pending, transfer,
382                                                  error, false, false, host);
383       preparedStatement.executeQuery();
384       while (preparedStatement.getNext()) {
385         final DbTaskRunner taskRunner =
386             DbTaskRunner.getFromStatement(preparedStatement);
387         stopOneTransfer(taskRunner, map, session, body);
388       }
389       preparedStatement.realClose();
390     } catch (final WaarpDatabaseException e) {
391       if (preparedStatement != null) {
392         preparedStatement.realClose();
393       }
394       logger.error(Messages.getString("TransferUtils.14"),
395                    e.getMessage()); //$NON-NLS-1$
396     }
397   }
398 
399   /**
400    * Method to delete the temporary file
401    *
402    * @param taskRunner
403    * @param map
404    * @param session
405    * @param body
406    */
407   @SuppressWarnings("unchecked")
408   public static void cleanOneTransfer(final DbTaskRunner taskRunner,
409                                       final Object map,
410                                       final R66Session session,
411                                       final String body) {
412     if (!taskRunner.isSender() && !taskRunner.isAllDone()) {
413       String name = null;
414       try {
415         if (session != null) {
416           session.getDir().changeDirectory("/");
417           session.setBadRunner(taskRunner, ErrorCode.QueryAlreadyFinished);
418           final R66File file = session.getFile();
419           if (file != null) {
420             name = file.getFile();
421             if (file.exists()) {
422               logger.info("{}{}", Messages.getString("TransferUtils.18"),
423                           file); //$NON-NLS-1$
424               if (!file.delete()) {
425                 logger.warn(Messages.getString("TransferUtils.19") +
426                             file); //$NON-NLS-1$
427               } else {
428                 taskRunner.setRankAtStartup(0);
429                 taskRunner.setFilename("###FILE DELETED### " + name);
430                 taskRunner.update();
431               }
432             } else if (!name.contains("###FILE DELETED### ")) {
433               taskRunner.setRankAtStartup(0);
434               taskRunner.setFilename("###FILE DELETED### " + name);
435               taskRunner.update();
436             }
437           }
438         }
439       } catch (final CommandAbstractException e1) {
440         logger.warn(Messages.getString("TransferUtils.19") + name + " : {}",
441                     e1.getMessage()); //$NON-NLS-1$
442       } catch (final WaarpDatabaseException ignored) {
443         // nothing
444       }
445     }
446     if (map != null) {
447       if (map instanceof Map) {
448         ((Map<String, String>) map).put(taskRunner.getKey(),
449                                         taskRunner.getJsonAsString());
450       } else if (map instanceof StringBuilder) {
451         final LocalChannelReference lcr =
452             Configuration.configuration.getLocalTransaction()
453                                        .getFromRequest(taskRunner.getKey());
454         ((StringBuilder) map).append(taskRunner.toSpecializedHtml(session, body,
455                                                                   lcr != null?
456                                                                       Messages.getString(
457                                                                           "HttpSslHandler.Active") :
458                                                                       Messages.getString(
459                                                                           "HttpSslHandler.NotActive")));
460       }
461     }
462   }
463 
464   /**
465    * Clean all selected transfers
466    *
467    * @param dbSession
468    * @param limit
469    * @param map
470    * @param session
471    * @param body
472    * @param startid
473    * @param stopid
474    * @param tstart
475    * @param tstop
476    * @param rule
477    * @param req
478    * @param pending
479    * @param transfer
480    * @param error
481    * @param host
482    *
483    * @return the associated StringBuilder if the one given as parameter is not
484    *     null
485    */
486   public static void cleanSelectedTransfers(final DbSession dbSession,
487                                             final int limit, final Object map,
488                                             final R66Session session,
489                                             final String body,
490                                             final String startid,
491                                             final String stopid,
492                                             final Timestamp tstart,
493                                             final Timestamp tstop,
494                                             final String rule, final String req,
495                                             final boolean pending,
496                                             final boolean transfer,
497                                             final boolean error,
498                                             final String host) {
499     if (dbSession == null || dbSession.isDisActive()) {
500       // do it without DB
501       if (ClientRunner.activeRunners != null) {
502         for (final ClientRunner runner : ClientRunner.activeRunners) {
503           final DbTaskRunner taskRunner = runner.getTaskRunner();
504           stopOneTransfer(taskRunner, null, session, null);
505           cleanOneTransfer(taskRunner, map, session, body);
506         }
507       }
508       if (CommanderNoDb.todoList != null) {
509         CommanderNoDb.todoList.clear();
510       }
511       return;
512     }
513     DbPreparedStatement preparedStatement = null;
514     try {
515       preparedStatement =
516           DbTaskRunner.getFilterPrepareStatement(dbSession, limit, true,
517                                                  startid, stopid, tstart, tstop,
518                                                  rule, req, pending, transfer,
519                                                  error, false, false, host);
520       preparedStatement.executeQuery();
521       while (preparedStatement.getNext()) {
522         final DbTaskRunner taskRunner =
523             DbTaskRunner.getFromStatement(preparedStatement);
524         stopOneTransfer(taskRunner, null, session, null);
525         cleanOneTransfer(taskRunner, map, session, body);
526       }
527       preparedStatement.realClose();
528     } catch (final WaarpDatabaseException e) {
529       if (preparedStatement != null) {
530         preparedStatement.realClose();
531       }
532       logger.error(Messages.getString("TransferUtils.14"),
533                    e.getMessage()); //$NON-NLS-1$
534     }
535   }
536 
537 }