View Javadoc

1   // PassiveGetter.java
2   // $Id: PassiveGetter.java,v 1.6 2007/02/21 00:07:50 sjardine Exp $
3   //
4   // Copyright 2000, Joe Phillips <jaiger@innovationsw.com>
5   // Copyright 2001, 2002 Innovation Software Group, LLC - http://www.innovationsw.com
6   //
7   // This library is free software; you can redistribute it and/or
8   // modify it under the terms of the GNU Library General Public
9   // License as published by the Free Software Foundation; either
10  // version 2 of the License, or (at your option) any later version.
11  //
12  // This library is distributed in the hope that it will be useful,
13  // but WITHOUT ANY WARRANTY; without even the implied warranty of
14  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  // Library General Public License for more details.
16  //
17  // You should have received a copy of the GNU Library General Public
18  // License along with this library; if not, write to the Free
19  // Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  //
21  // TODO implement compressed streams
22  
23  package gnu.inet.ftp;
24  
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.InterruptedIOException;
28  import java.io.OutputStream;
29  import java.net.Socket;
30  import java.net.SocketException;
31  import java.util.zip.InflaterInputStream;
32  
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  
36  /***
37   * This class implements an FTP-style data connection thread for GETing
38   * files/data passively. This class is used internally to the FtpClient class.
39   */
40  public class PassiveGetter extends Getter {
41      // private data
42      private PassiveConnection connection;
43  
44      private Socket sock = null;
45  
46      private final static Log log = LogFactory.getLog(PassiveGetter.class);
47  
48      /***
49       * Create a new PassiveGetter instance with the given OutpuStream for data
50       * output and using the given PassiveParameters to connect to the server.
51       * 
52       * @param out
53       *            the OutputStream where retrieved data will be written
54       * @param connection
55       *            the PassiveConnection to the server
56       */
57      public PassiveGetter(OutputStream out, PassiveConnection connection) {
58  	super();
59  
60  	this.ostream = out;
61  	this.connection = connection;
62      }
63  
64      //
65      // public methods
66      //
67  
68      /***
69       * cancel a running transfer sets a flag and calls interrupt() can only be
70       * called once
71       */
72      public void cancel() {
73  	if (!cancelled) {
74  	    cancelled = true;
75  	    interrupt();
76  	    if (sock != null && !sock.isClosed()) {
77  		try {
78  		    log.debug("Setting socket to 0 lingering");
79  		    sock.setSoLinger(true, 0);
80  		    sock.close(); // Interrupt I/O
81  		} catch (IOException e) {
82  		    // do nothing
83  		}
84  	    }
85  	}
86      }
87  
88      /***
89       * get data from server using given parameters.
90       */
91      public void run() {
92  	boolean signalClosure = false;
93  	// Socket sock= null;
94  	InputStream istream = null;
95  	long amount = 0;
96  	int buffer_size = 0;
97  	byte buffer[] = new byte[BUFFER_SIZE];
98  	// this.cancelled= false; // reset cancelled flag
99  	PassiveParameters parameters = connection.getPassiveParameters();
100 
101 	try {
102 	    // make connection
103 	    sock = connection.getSocket();
104 	    if (cancelled)
105 		throw new InterruptedIOException("Transfer cancelled");
106 	    signalConnectionOpened(new ConnectionEvent(parameters
107 		    .getInetAddress(), parameters.getPort()));
108 	    signalClosure = true;
109 	    signalTransferStarted();
110 
111 	    try {
112 
113 		// handle different type settings
114 		switch (type) {
115 		case FtpClientProtocol.TYPE_ASCII:
116 		    istream = new AsciiInputStream(sock.getInputStream());
117 		    break;
118 		default:
119 		    istream = sock.getInputStream();
120 		    break;
121 		}
122 
123 		// handle different mode settings
124 		switch (mode) {
125 		case FtpClientProtocol.MODE_ZLIB:
126 		    istream = new InflaterInputStream(istream);
127 		    break;
128 		case FtpClientProtocol.MODE_STREAM:
129 		default:
130 		    break;
131 		}
132 
133 		int len;
134 		while (!cancelled && ((len = istream.read(buffer)) > 0)) {
135 		    ostream.write(buffer, 0, len);
136 		    amount += len;
137 		    buffer_size += len;
138 		    if (buffer_size >= BUFFER_SIZE) {
139 			buffer_size = buffer_size % BUFFER_SIZE;
140 			signalTransfered(amount);
141 		    }
142 		    yield();
143 		}
144 
145 		ostream.flush();
146 	    } catch (InterruptedIOException iioe) {
147 		if (!cancelled) {
148 		    log.error(iioe.getMessage(), iioe);
149 		}
150 	    } catch (Exception e) {
151 		log.error(e.getMessage(), e);
152 	    } finally {
153 		log.debug("Closing inputstream");
154 		if (istream != null) {
155 		    istream.close();
156 		}
157 		if (!sock.isClosed()) {
158 		    try {
159 			log.debug("Setting socket to 0 lingering");
160 			sock.setSoLinger(true, 0);
161 			sock.close();
162 		    } catch (SocketException e) {
163 			// Don't care.
164 		    }
165 		}
166 		signalTransferCompleted();
167 	    }
168 	} catch (Exception ee) {
169 	    signalConnectionFailed(ee);
170 	    log.error(ee.getMessage(), ee);
171 	}
172 	if (signalClosure == true) {
173 	    signalConnectionClosed(new ConnectionEvent(parameters
174 		    .getInetAddress(), parameters.getPort()));
175 	}
176 	sock = null;
177     }
178 }
179 
180 // PassiveGetter.java