1 /* ActiveModeDTP.java -- 2 Copyright (C) 2003, 2004 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.java.net.protocol.ftp; 40 41 import java.io.IOException; 42 import java.io.InputStream; 43 import java.io.OutputStream; 44 import java.net.InetAddress; 45 import java.net.ServerSocket; 46 import java.net.Socket; 47 48 /** 49 * An active mode FTP data transfer process. 50 * This starts a server on the specified port listening for a data 51 * connection. It converts the socket input into a file stream for reading. 52 * 53 * @author Chris Burdess (dog@gnu.org) 54 */ 55 final class ActiveModeDTP 56 implements DTP, Runnable 57 { 58 59 ServerSocket server; 60 Socket socket; 61 DTPInputStream in; 62 DTPOutputStream out; 63 boolean completed; 64 boolean inProgress; 65 int transferMode; 66 IOException exception; 67 Thread acceptThread; 68 int connectionTimeout; 69 ActiveModeDTP(InetAddress localhost, int port, int connectionTimeout, int timeout)70 ActiveModeDTP(InetAddress localhost, int port, 71 int connectionTimeout, int timeout) 72 throws IOException 73 { 74 completed = false; 75 inProgress = false; 76 server = new ServerSocket(port, 1, localhost); 77 if (timeout > 0) 78 { 79 server.setSoTimeout(timeout); 80 } 81 if (connectionTimeout <= 0) 82 { 83 connectionTimeout = 20000; 84 } 85 this.connectionTimeout = connectionTimeout; 86 acceptThread = new Thread(this, "ActiveModeDTP"); 87 acceptThread.setDaemon(true); 88 acceptThread.start(); 89 } 90 91 /** 92 * Start listening. 93 */ run()94 public void run() 95 { 96 try 97 { 98 socket = server.accept(); 99 //System.err.println("Accepted connection from "+socket.getInetAddress()+":"+socket.getPort()); 100 } 101 catch (IOException e) 102 { 103 exception = e; 104 } 105 } 106 107 /** 108 * Waits until a client has connected. 109 */ waitFor()110 public void waitFor() 111 throws IOException 112 { 113 try 114 { 115 acceptThread.join(connectionTimeout); 116 } 117 catch (InterruptedException e) 118 { 119 } 120 if (exception != null) 121 { 122 throw exception; 123 } 124 if (socket == null) 125 { 126 server.close(); 127 throw new IOException("client did not connect before timeout"); 128 } 129 acceptThread = null; 130 } 131 132 /** 133 * Returns an input stream from which a remote file can be read. 134 */ getInputStream()135 public InputStream getInputStream() 136 throws IOException 137 { 138 if (inProgress) 139 { 140 throw new IOException("Transfer in progress"); 141 } 142 if (acceptThread != null) 143 { 144 waitFor(); 145 } 146 switch (transferMode) 147 { 148 case FTPConnection.MODE_STREAM: 149 in = new StreamInputStream(this, socket.getInputStream()); 150 break; 151 case FTPConnection.MODE_BLOCK: 152 in = new BlockInputStream(this, socket.getInputStream()); 153 break; 154 case FTPConnection.MODE_COMPRESSED: 155 in = new CompressedInputStream(this, socket.getInputStream()); 156 break; 157 default: 158 throw new IllegalStateException("invalid transfer mode"); 159 } 160 in.setTransferComplete(false); 161 return in; 162 } 163 164 /** 165 * Returns an output stream to which a local file can be written for 166 * upload. 167 */ getOutputStream()168 public OutputStream getOutputStream() throws IOException 169 { 170 if (inProgress) 171 { 172 throw new IOException("Transfer in progress"); 173 } 174 if (acceptThread != null) 175 { 176 waitFor(); 177 } 178 switch (transferMode) 179 { 180 case FTPConnection.MODE_STREAM: 181 out = new StreamOutputStream(this, socket.getOutputStream()); 182 break; 183 case FTPConnection.MODE_BLOCK: 184 out = new BlockOutputStream(this, socket.getOutputStream()); 185 break; 186 case FTPConnection.MODE_COMPRESSED: 187 out = new CompressedOutputStream(this, socket.getOutputStream()); 188 break; 189 default: 190 throw new IllegalStateException("invalid transfer mode"); 191 } 192 out.setTransferComplete(false); 193 return out; 194 } 195 setTransferMode(int mode)196 public void setTransferMode(int mode) 197 { 198 transferMode = mode; 199 } 200 complete()201 public void complete() 202 { 203 completed = true; 204 if (!inProgress) 205 { 206 transferComplete(); 207 } 208 } 209 abort()210 public boolean abort() 211 { 212 completed = true; 213 transferComplete(); 214 return inProgress; 215 } 216 transferComplete()217 public void transferComplete() 218 { 219 if (socket == null) 220 { 221 return; 222 } 223 if (in != null) 224 { 225 in.setTransferComplete(true); 226 } 227 if (out != null) 228 { 229 out.setTransferComplete(true); 230 } 231 completed = completed || (transferMode == FTPConnection.MODE_STREAM); 232 if (completed && socket != null) 233 { 234 try 235 { 236 socket.close(); 237 } 238 catch (IOException e) 239 { 240 } 241 try 242 { 243 server.close(); 244 } 245 catch (IOException e) 246 { 247 } 248 } 249 } 250 251 } 252