1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.ftp.filesystembased;
21
22 import io.netty.channel.Channel;
23 import io.netty.channel.ChannelFuture;
24 import org.waarp.common.command.exception.CommandAbstractException;
25 import org.waarp.common.exception.FileEndOfTransferException;
26 import org.waarp.common.exception.FileTransferException;
27 import org.waarp.common.file.DataBlock;
28 import org.waarp.common.file.filesystembased.FilesystemBasedFileImpl;
29 import org.waarp.common.logging.WaarpLogger;
30 import org.waarp.common.logging.WaarpLoggerFactory;
31 import org.waarp.common.utility.WaarpNettyUtil;
32 import org.waarp.ftp.core.exception.FtpNoConnectionException;
33 import org.waarp.ftp.core.file.FtpFile;
34 import org.waarp.ftp.core.session.FtpSession;
35
36 import java.util.concurrent.locks.ReentrantLock;
37
38
39
40
41 public abstract class FilesystemBasedFtpFile extends FilesystemBasedFileImpl
42 implements FtpFile {
43
44
45
46 private static final WaarpLogger logger =
47 WaarpLoggerFactory.getLogger(FilesystemBasedFtpFile.class);
48
49
50
51
52 private final ReentrantLock retrieveLock = new ReentrantLock();
53
54
55
56
57
58
59
60
61
62 protected FilesystemBasedFtpFile(final FtpSession session,
63 final FilesystemBasedFtpDir dir,
64 final String path, final boolean append)
65 throws CommandAbstractException {
66 super(session, dir, path, append);
67 }
68
69 @Override
70 public final long length() throws CommandAbstractException {
71 long length = super.length();
72 if (((FtpSession) getSession()).getDataConn()
73 .isFileStreamBlockAsciiImage()) {
74 final long block = (long) Math.ceil(
75 (double) length / (double) getSession().getBlockSize());
76 length += (block + 3) * 3;
77 }
78 return length;
79 }
80
81
82
83
84
85 @Override
86 public final void trueRetrieve() {
87 retrieveLock.lock();
88 try {
89 if (!isReady) {
90 return;
91 }
92
93 try {
94 ((FtpSession) session).getDataConn().getFtpTransferControl()
95 .waitForDataNetworkHandlerReady();
96 } catch (final InterruptedException e) {
97
98 logger.warn("DataNetworkHandler was not ready", e);
99 if (isInReading()) {
100 logger.error("Should not be", e);
101 ((FtpSession) session).getDataConn().getFtpTransferControl()
102 .setTransferAbortedFromInternal(true);
103 }
104 logger.debug(
105 "Possible call while channel was on going to be closed once transfer was done",
106 e);
107 closeFile();
108 ((FtpSession) session).getDataConn().getFtpTransferControl()
109 .setPreEndOfTransfer();
110 return;
111 }
112 final Channel channel;
113 try {
114 channel = ((FtpSession) session).getDataConn().getCurrentDataChannel();
115 } catch (final FtpNoConnectionException e) {
116 if (isInReading()) {
117 logger.error("Should not be", e);
118 ((FtpSession) session).getDataConn().getFtpTransferControl()
119 .setTransferAbortedFromInternal(true);
120 }
121 logger.debug(
122 "Possible call while channel was on going to be closed once transfer was done",
123 e);
124 closeFile();
125 ((FtpSession) session).getDataConn().getFtpTransferControl()
126 .setPreEndOfTransfer();
127 return;
128 }
129 DataBlock block;
130 try {
131 block = readDataBlock();
132 } catch (final FileEndOfTransferException e) {
133
134
135
136 closeFile();
137 ((FtpSession) session).getDataConn().getFtpTransferControl()
138 .setPreEndOfTransfer();
139 return;
140 }
141 if (block == null) {
142
143
144
145 closeFile();
146 ((FtpSession) session).getDataConn().getFtpTransferControl()
147 .setPreEndOfTransfer();
148 return;
149 }
150
151 ChannelFuture future = null;
152 while (block != null && !block.isEOF()) {
153 future = channel.writeAndFlush(block);
154 WaarpNettyUtil.awaitOrInterrupted(future);
155 if (!future.isSuccess()) {
156 closeFile();
157 throw new FileTransferException("File transfer in error");
158 }
159 try {
160 block = readDataBlock();
161 } catch (final FileEndOfTransferException e) {
162 closeFile();
163
164 if (future.isSuccess()) {
165 ((FtpSession) session).getDataConn().getFtpTransferControl()
166 .setPreEndOfTransfer();
167 } else {
168 throw new FileTransferException("File transfer in error");
169 }
170 return;
171 }
172 }
173
174 closeFile();
175 if (block != null) {
176 logger.debug("Write {}", block.getByteCount());
177 future = channel.writeAndFlush(block);
178 }
179
180 if (future != null) {
181 WaarpNettyUtil.awaitOrInterrupted(future);
182 if (future.isSuccess()) {
183 ((FtpSession) session).getDataConn().getFtpTransferControl()
184 .setPreEndOfTransfer();
185 } else {
186 throw new FileTransferException("LAST Write is not successful",
187 future.cause());
188 }
189 }
190 } catch (final FileTransferException e) {
191
192 logger.error("File Transfer Exception: {}", e.getMessage(), e);
193 ((FtpSession) session).getDataConn().getFtpTransferControl()
194 .setTransferAbortedFromInternal(true);
195 } catch (final CommandAbstractException e) {
196 logger.error("Should not be", e);
197 ((FtpSession) session).getDataConn().getFtpTransferControl()
198 .setTransferAbortedFromInternal(true);
199 } finally {
200 retrieveLock.unlock();
201 }
202 }
203 }