1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package gnu.inet.ftp;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InterruptedIOException;
25 import java.io.OutputStream;
26 import java.net.InetAddress;
27 import java.net.ServerSocket;
28 import java.net.Socket;
29 import java.net.SocketException;
30 import java.util.zip.DeflaterOutputStream;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 /***
36 * This class implements an FTP-style data connection server thread for PUTing
37 * in a non-passive files/data.
38 * <P>
39 * This class is used internally to the FtpClient class.
40 */
41 public class ActivePutter extends Putter {
42
43 private final static Log log = LogFactory.getLog(ActivePutter.class);
44
45 private InetAddress address;
46
47 private int port;
48
49 private ServerSocket server;
50
51 private int timeout;
52
53 /***
54 * Create a new ActivePutter thread given the InputStream data source.
55 *
56 * @param in
57 * data source
58 * @exception IOException
59 * io error with the ServerSocket
60 */
61 public ActivePutter(InputStream in) throws IOException {
62 super();
63
64
65 this.server = new ServerSocket(0);
66 this.timeout = 30 * 1000;
67
68 this.port = server.getLocalPort();
69 this.address = this.server.getInetAddress();
70
71 this.istream = in;
72 }
73
74
75
76
77
78 /***
79 * get address that this Putter is listening on
80 *
81 * @return server socket IP address
82 */
83 public InetAddress getInetAddress() {
84 return address;
85 }
86
87 /***
88 * get the port this ActivePutter is listening on
89 *
90 * @return port number
91 */
92 public synchronized int getPort() {
93 return port;
94 }
95
96 /***
97 * implements thread behavior. Put data to server using given parameters.
98 */
99 public void run() {
100 boolean signalClosure = false;
101 Socket sock = null;
102 OutputStream ostream = null;
103 long amount = 0;
104 int buffer_size = 0;
105 byte buffer[] = new byte[BUFFER_SIZE];
106
107
108 try {
109
110 server.setSoTimeout(timeout);
111 if (cancelled)
112 throw new InterruptedIOException("Transfer cancelled");
113
114
115
116 sock = server.accept();
117 signalConnectionOpened(new ConnectionEvent(sock.getInetAddress(),
118 sock.getPort()));
119 signalTransferStarted();
120
121 try {
122
123
124 switch (type) {
125 case FtpClientProtocol.TYPE_ASCII:
126 ostream = new AsciiOutputStream(sock.getOutputStream());
127 break;
128 default:
129 ostream = sock.getOutputStream();
130 break;
131 }
132
133
134 switch (mode) {
135 case FtpClientProtocol.MODE_ZLIB:
136 ostream = new DeflaterOutputStream(ostream);
137 break;
138 case FtpClientProtocol.MODE_STREAM:
139 default:
140 break;
141 }
142
143 int len;
144 while ((len = istream.read(buffer)) != -1) {
145 ostream.write(buffer, 0, len);
146 amount += len;
147 buffer_size += len;
148 if (buffer_size >= BUFFER_SIZE) {
149 buffer_size = buffer_size % BUFFER_SIZE;
150 signalTransfered(amount);
151 }
152 yield();
153 }
154 } catch (InterruptedIOException iioe) {
155 if (!cancelled) {
156 log.error(iioe.getMessage(), iioe);
157 }
158 } catch (Exception e) {
159 log.error(e.getMessage(), e);
160 } finally {
161 log.debug("Closing inputstream");
162 if (ostream != null) {
163 ostream.close();
164 }
165 if (!sock.isClosed()) {
166 try {
167 log.debug("Setting socket to 0 lingering");
168 sock.setSoLinger(true, 0);
169 sock.close();
170 } catch (SocketException e) {
171
172 }
173 }
174 signalTransferCompleted();
175 }
176 } catch (Exception ee) {
177 signalConnectionFailed(ee);
178 log.error(ee.getMessage(), ee);
179 } finally {
180 try {
181 log.debug("Closing server socket");
182 server.close();
183 } catch (IOException ex) {
184
185 }
186 }
187
188 if (signalClosure == true && sock != null) {
189 signalConnectionClosed(new ConnectionEvent(sock.getInetAddress(),
190 sock.getPort()));
191 }
192 }
193
194 /***
195 * set connection timeout in milliseconds. must be called before
196 * start()/run()
197 *
198 * @param milliseconds
199 * the number of milliseconds the server socket should wait
200 * for a connection before timing-out. the default timeout is
201 * 30s
202 */
203 public void setTimeout(int milliseconds) {
204 timeout = milliseconds;
205 }
206
207 }
208
209