//***************************************************************************** //* //* (c) Copyright 2002. Glub Tech, Incorporated. All Rights Reserved. //* //* $Id: FTPRead.java 37 2009-05-11 22:46:15Z gary $ //* //***************************************************************************** package com.glub.secureftp.bean; import java.io.*; import java.net.*; import java.util.zip.*; import com.glub.util.*; /** * The <code>FTPRead</code> class is responsible for reading data from the * FTP server. * * @author Brian Knight * @version $Revision: 47 $, $Date: 2009-05-16 10:10:12 -0700 (Sat, 16 May 2009) $ * @since 2.5.19 */ public class FTPRead implements FTPData { /** The control socket. */ private Socket control = null; /** The socket to read from (passive). */ private Socket sock = null; /** The socket to read from (active). */ private ServerSocket servsock = null; /** The input stream from the socket. */ private InputStream input = null; /** The output stream from the socket. */ private OutputStream output = null; /** Used to read in an ascii transfer. */ private BufferedReader reader = null; /** Used to write in an ascii transfer. */ private PrintWriter writer = null; /** Used to set the ascii encoding. */ private String encoding = null; /** A reference to a Progress object. */ private Progress progress = null; /** The starting size of the data being transferred. */ private long startsize = 0; /** The filesize of the data being transferred. */ private long filesize = 0; /** If the transfer is aborted, this will be true */ private boolean aborted = false; /** Do we have to wait for the aborted process to cleanup? **/ private boolean waitForAbort = false; /** Is the stream zlib compressed (mode z)? **/ private boolean zLibCompressed = false; /** * Create a new <code>FTPRead</code> object to be used to retrieve binary * data passively. * * @param s the data socket. * @param os the data stream. */ public FTPRead( Socket s, OutputStream os ) { this( s, os, null, 0, 0 ); } /** * Create a new <code>FTPRead</code> object to be used to retrieve binary * data with progress information passively. * * @param s the data socket. * @param os the data stream. * @param p a <code>Progress</code> object which is used to update * download status. * @param start the start size of the file being downloaded * (used in progress). * @param stop the stop size of the file being downloaded * (used in progress). */ public FTPRead( Socket s, OutputStream os, Progress p, long start, long stop ) { sock = s; output = os; progress = p; startsize = start; filesize = stop; } /** * Create a new <code>FTPRead</code> object to be used to retrieve ascii * data passively. * * @param s the data socket. * @param w the data writer. */ public FTPRead( Socket s, PrintWriter w ) { this( s, w, null, 0, 0 ); } /** * Create a new <code>FTPRead</code> object to be used to retrieve ascii * data with progress information passively. * * @param s the data socket. * @param w the data writer. * @param p a <code>Progress</code> object which is used to update * download status. * @param start the start size of the file being downloaded * (used in progress). * @param stop the stop size of the file being downloaded * (used in progress). */ public FTPRead( Socket s, PrintWriter w, Progress p, long start, long stop ) { sock = s; writer = w; progress = p; startsize = start; filesize = stop; } /** * Create a new <code>FTPRead</code> object to be used to retrieve ascii * data with progress information passively. * * @param s the data socket. * @param w the data writer. * @param p a <code>Progress</code> object which is used to update * download status. * @param start the start size of the file being downloaded * (used in progress). * @param stop the stop size of the file being downloaded * (used in progress). * @param e the data encoding. */ public FTPRead( Socket s, PrintWriter w, Progress p, long start, long stop, String e ) { sock = s; writer = w; progress = p; startsize = start; filesize = stop; encoding = e; } /** * Create a new <code>FTPRead</code> object to be used to retrieve binary * data actively. * * @param ss the data server socket. * @param os the data stream. */ public FTPRead( ServerSocket ss, OutputStream os ) { this( ss, os, null, 0, 0 ); } /** * Create a new <code>FTPRead</code> object to be used to retrieve binary * data with progress information actively. * * @param ss the data server socket. * @param os the data stream. * @param p a <code>Progress</code> object which is used to update * download status. * @param start the start size of the file being downloaded * (used in progress). * @param stop the stop size of the file being downloaded * (used in progress). */ public FTPRead( ServerSocket ss, OutputStream os, Progress p, long start, long stop ) { servsock = ss; output = os; progress = p; startsize = start; filesize = stop; } /** * Create a new <code>FTPRead</code> object to be used to retrieve ascii * data actively. * * @param ss the data server socket. * @param w the data writer. */ public FTPRead( ServerSocket ss, PrintWriter w ) { this( ss, w, null, 0, 0 ); } /** * Create a new <code>FTPRead</code> object to be used to retrieve ascii * data with progress information actively. * * @param ss the data server socket. * @param w the data writer. * @param p a <code>Progress</code> object which is used to update * download status. * @param start the start size of the file being downloaded * (used in progress). * @param stop the stop size of the file being downloaded * (used in progress). */ public FTPRead( ServerSocket ss, PrintWriter w, Progress p, long start, long stop ) { servsock = ss; writer = w; progress = p; startsize = start; filesize = stop; } /** * Create a new <code>FTPRead</code> object to be used to retrieve ascii * data with progress information actively. * * @param ss the data server socket. * @param w the data writer. * @param p a <code>Progress</code> object which is used to update * download status. * @param start the start size of the file being downloaded * (used in progress). * @param stop the stop size of the file being downloaded * (used in progress). * @param e the data encoding. */ public FTPRead( ServerSocket ss, PrintWriter w, Progress p, long start, long stop, String e ) { servsock = ss; writer = w; progress = p; startsize = start; filesize = stop; encoding = e; } /** * Set stream as zLib compressed (mode z). * * @param compressed true if compressed */ public void setZLibCompressed( boolean compressed ) { zLibCompressed = compressed; } /** * Set the control socket (used for abort). * * @param control the control socket */ public void setControlSocket( Socket control ) { this.control = control; } /** * Get the control socket (used for abort). * * @return the control socket. */ public Socket getControlSocket() { return control; } /** * Handle the data transfer. * * @throws FTPException if the FTP server returns an error. */ public void doTransfer() throws FTPException { _doTransfer(); } /** * Abort the data transfer. * * @throws FTPException if the FTP server returns an error. */ public void abortTransfer() throws FTPException { aborted = true; waitForAbort = true; _abortSockets(); //cleanup(); } /** * Called when an aborted transfer is complete. This should not be * called directly. */ public void abortComplete() { waitForAbort = false; } /** * Housekeeping for the data socket. */ protected void cleanup() { _cleanup(); } /* * * The methods below are here for obfuscation purposes. * */ private void _doTransfer() throws FTPException { boolean debug = GTOverride.getBoolean("glub.debug"); if ((output == null && writer == null) || (sock == null && servsock == null)) { return; } try { if (sock == null) { sock = servsock.accept(); Util.close( servsock ); servsock = null; } input = sock.getInputStream(); if ( zLibCompressed ) { input = new InflaterInputStream( input, new Inflater(), 1024 ); } long nbytes = startsize; if (progress != null) progress.startProgress(); if (output != null) { byte[] b = new byte[1024]; int len = 0; while ((len = input.read( b )) >= 0) { output.write( b, 0, len ); nbytes += len; if (progress != null) progress.updateProgress( nbytes, filesize ); } output.flush(); } else { String line = null; InputStreamReader isr = null; if ( encoding != null ) isr = new InputStreamReader( input, encoding ); else isr = new InputStreamReader( input ); reader = new BufferedReader( isr ); if ( debug ) { System.out.println( "Input Encoding = " + isr.getEncoding() ); } while ((line = reader.readLine()) != null) { writer.println( line ); // println okay, write to local system nbytes += (line.length() + 1); if (progress != null) progress.updateProgress( nbytes, filesize ); } writer.flush(); } if (progress != null) progress.finishProgress(); } catch (IOException ioe) { if ( aborted ) { throw new FTPAbortException( "ABOR command successful." ); } else { throw new FTPException( ioe.getMessage() ); } } finally { if ( !aborted ) { cleanup(); } else { while ( waitForAbort ) { try { Thread.sleep(100); //System.out.println("waiting for abort."); } catch ( InterruptedException ie ) { } } cleanup(); throw new FTPAbortException( "ABOR command successful." ); } } } private void _abortSockets() { // wait 10 second just in case the server doesn't drop you... try { Thread.sleep(10000); } catch ( InterruptedException ie ) { //ie.printStackTrace(); } Util.close( sock ); Util.close( servsock ); } private void _cleanup() { Util.close( input ); Util.close( output ); Util.close( reader ); Util.close( writer ); Util.close( sock ); Util.close( servsock ); } }