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.client;
21  
22  import org.waarp.common.database.exception.WaarpDatabaseException;
23  import org.waarp.common.logging.WaarpLoggerFactory;
24  import org.waarp.openr66.commander.ClientRunner;
25  import org.waarp.openr66.context.ErrorCode;
26  import org.waarp.openr66.context.R66Result;
27  import org.waarp.openr66.context.task.exception.OpenR66RunnerErrorException;
28  import org.waarp.openr66.database.data.DbTaskRunner;
29  import org.waarp.openr66.protocol.configuration.Configuration;
30  import org.waarp.openr66.protocol.exception.OpenR66ProtocolNoConnectionException;
31  import org.waarp.openr66.protocol.exception.OpenR66ProtocolNotYetConnectionException;
32  import org.waarp.openr66.protocol.exception.OpenR66ProtocolPacketException;
33  import org.waarp.openr66.protocol.localhandler.LocalChannelReference;
34  import org.waarp.openr66.protocol.networkhandler.NetworkTransaction;
35  import org.waarp.openr66.protocol.utils.R66Future;
36  
37  /**
38   * Class for Recv Through client
39   * <p>
40   * This class does not included the real file transfer since it is up to the
41   * business project to implement how
42   * to write new data received from the remote host. If an error occurs, no
43   * transfer log is kept.
44   * <p>
45   * 1) Configuration must have been loaded<br>
46   * <br>
47   * 2) Pipeline and NetworkTransaction must have been initiated:<br>
48   * <tt>     Configuration.configuration.pipelineInit();</tt><br>
49   * <tt>     NetworkTransaction networkTransaction = new
50   * NetworkTransaction();</tt><br>
51   * <br>
52   * 3) Prepare the request of transfer:<br>
53   * <tt>     R66Future futureReq = new R66Future(true);</tt><br>
54   * <tt>     RecvThroughHandler rth = new RecvThroughHandler(...);</tt><br>
55   * <tt>     RecvThroughClient transaction = new RecvThroughClient(futureReq,
56   * rth, ...);</tt><br>
57   * <tt>     transaction.run();</tt><br>
58   * <br>
59   * 4) If everything is in success, wait for the transfer to finish:<br>
60   * <tt>     futureReq.awaitUninterruptibly();</tt><br>
61   * <tt>     R66Result result = futureReq.getResult();</tt><br>
62   * <br>
63   * 5) If there is the need to re-do, just re-execute the steps from 3 to 4.<br>
64   * Don't forget at the very end to finish the global structure (steps 3 to 4 no
65   * more executed):<br>
66   * <tt>     networkTransaction.closeAll();</tt><br>
67   * <br>
68   * <br>
69   *
70   * @see TestRecvThroughClient Class as example of usage in test part
71   */
72  public class RecvThroughClient extends AbstractTransfer {
73    protected final NetworkTransaction networkTransaction;
74    protected LocalChannelReference localChannelReference;
75    protected final RecvThroughHandler handler;
76  
77    /**
78     * @param future
79     * @param remoteHost
80     * @param filename
81     * @param rulename
82     * @param fileinfo
83     * @param isMD5
84     * @param blocksize
85     * @param id
86     * @param networkTransaction
87     */
88    public RecvThroughClient(final R66Future future,
89                             final RecvThroughHandler handler,
90                             final String remoteHost, final String filename,
91                             final String rulename, final String fileinfo,
92                             final boolean isMD5, final int blocksize,
93                             final long id,
94                             final NetworkTransaction networkTransaction) {
95      // timestart since immediate
96      super(RecvThroughClient.class, future, filename, rulename, fileinfo, isMD5,
97            remoteHost, blocksize, id, null);
98      this.networkTransaction = networkTransaction;
99      this.handler = handler;
100   }
101 
102   /**
103    * Prior to call this method, the pipeline and NetworkTransaction must have
104    * been initialized. It is the
105    * responsibility of the caller to finish all network resources.
106    */
107   @Override
108   public void run() {
109     if (logger == null) {
110       logger = WaarpLoggerFactory.getLogger(RecvThroughClient.class);
111     }
112     final DbTaskRunner taskRunner = initRequest();
113     if (taskRunner == null) {
114       // already an error from there
115       return;
116     }
117     try {
118       final ClientRunner runner =
119           new ClientRunner(networkTransaction, taskRunner, future);
120       runner.setRecvThroughHandler(handler);
121       OpenR66ProtocolNotYetConnectionException exc = null;
122       for (int i = 0; i < Configuration.RETRYNB; i++) {
123         try {
124           runner.runTransfer();
125           exc = null;
126           break;
127         } catch (final OpenR66RunnerErrorException e) {
128           logger.error("Cannot Transfer", e);
129           future.setResult(
130               new R66Result(e, null, true, ErrorCode.Internal, taskRunner));
131           future.setFailure(e);
132           return;
133         } catch (final OpenR66ProtocolNoConnectionException e) {
134           logger.error("Cannot Connect", e);
135           future.setResult(
136               new R66Result(e, null, true, ErrorCode.ConnectionImpossible,
137                             taskRunner));
138           finalizeInErrorTransferRequest(runner, taskRunner,
139                                          ErrorCode.ConnectionImpossible);
140           future.setFailure(e);
141           return;
142         } catch (final OpenR66ProtocolPacketException e) {
143           logger.error("Bad Protocol", e);
144           future.setResult(new R66Result(e, null, true, ErrorCode.TransferError,
145                                          taskRunner));
146           future.setFailure(e);
147           return;
148         } catch (final OpenR66ProtocolNotYetConnectionException e) {
149           logger.debug("Not Yet Connected", e);
150           exc = e;
151         }
152       }
153       if (exc != null) {
154         taskRunner.setLocalChannelReference(new LocalChannelReference());
155         logger.error("Cannot Connect", exc);
156         future.setResult(
157             new R66Result(exc, null, true, ErrorCode.ConnectionImpossible,
158                           taskRunner));
159         future.setFailure(exc);
160       }
161     } finally {
162       if (taskRunner != null) {
163         if (future.isFailed() || nolog) {
164           try {
165             taskRunner.delete();
166           } catch (final WaarpDatabaseException ignored) {
167             // nothing
168           }
169         }
170       }
171     }
172   }
173 
174 }