For our internal use I found and updated a *very* simple but seemingly complete one-class FTP java implementation � la UrlConnection, see attachment.
If seen proper, this probably could be donated to Jakarta. If anyone sees some bugs/quirks/shortcomings with this implementation, I would be glad about feedback. -- :) Christoph Reck Thomas H�sler wrote:
Dear all
I am looking for an easy to use Net Library. I am mainly interested in an
implementation of the FTP Protocol. When looking through the jakarta sources
I found the net components in the sandbox projects. But I don't find a build
of them.
Is there no build available or am I looking at the wrong place??? Could
anyone help me to find a build of those components?
Regards
Tom
------------------------------------------------------------------
Thomas H�sler * TietoEnator Consulting AG
Industriestrasse 19 * 8304 Wallisellen * Switzerland
Tel. +41 (43) 233 45 28 * Fax +41 (43) 233 45 10
Mobile +41 (78) 622 03 36
<mailto:[EMAIL PROTECTED]>
http://www.tietoenator.ch
-- :) Christoph Reck
//-------------------------------------------------------------------- /* * $RCSfile: FtpConnection.java,v $ * * $Revision: 1.2 $ * $Date: 2002/03/05 10:09:29 $ * * Copyright DLR 2002 */ //-------------------------------------------------------------------- package de.dlr.dfd.dims.gen.utils; import java.net.*; import java.io.*; import java.util.*; /** * Low-Level worker class that handles FTP protocol (RFC 0959).<p> * * Code from <a href="http://forum.java.sun.com/thread.jsp?forum=31&thread=179383" * >http://forum.java.sun.com/thread.jsp?forum=31&thread=179383<a>. * * @created February 5, 2002 * @author reck */ public class FtpConnection { /** (-1) Default MessageNo **/ public final static int COMMAND_IGNORED = -1; /** (-99) Used when return message cannot be parsed **/ public final static int UNKNOWN_ERROR = -99; /** ** (110) Restart marker reply. In this case, the text is exact and not left to ** the particular implementation; it must read: MARK yyyy = mmmm Where yyyy is ** User-process data stream marker, and mmmm server's equivalent marker (note ** the spaces between markers and "="). */ public final static int RESTART_MARKER_REPLY = 110; /** (120) Service ready in nnn minutes. **/ public final static int SERVICE_NOT_READY = 120; /** (125) Data connection already open; transfer starting. **/ public final static int TRANSFER_STARTING = 125; /** (150) File status okay; about to open data connection. **/ public final static int FILE_STATUS_OK = 150; /** (200) Command okay. **/ public final static int COMMAND_OK = 200; /** (202) Command not implemented, superfluous at this site. **/ public final static int COMMAND_SUPERFLUOUS = 202; /** (211) System status, or system help reply. **/ public final static int SYSTEM_STATUS = 211; /** (212) Directory status. **/ public final static int DIRECTORY_STATUS = 212; /** (213) File status. **/ public final static int FILE_STATUS = 213; /** ** (214) Help message. On how to use the server or the meaning of a particular ** non-standard command. This reply is useful only to the human user. **/ public final static int HELP_MESSAGE = 214; /** ** (215) NAME system type. Where NAME is an official system name from the list ** in the Assigned Numbers document. **/ public final static int SYSTEM_TYPE = 215; /** (220) Service ready for new user. **/ public final static int SERVICE_READY = 220; /** (221) Service closing control connection. Logged out if appropriate. **/ public final static int SERVICE_CLOSING = 221; /** (225) Data connection open; no transfer in progress. **/ public final static int DATA_CONNECTION_OPEN = 225; /** ** (226) Closing data connection. Requested file action successful (for ** example, file transfer or file abort). **/ public final static int DATA_CONNECTION_CLOSED = 226; /** (227) Entering Passive Mode (h1,h2,h3,h4,p1,p2). **/ public final static int PASSIVE_MODE = 227; /** (230) User logged in, proceed. **/ public final static int USER_LOGGED_IN = 230; /** (250) Requested file action okay, completed. **/ public final static int FILE_ACTION_OK = 250; /** (257) "PATHNAME" created. **/ public final static int PATH_OK = 257; /** (331) User name okay, need password. **/ public final static int USER_OK_SEND_PASSWORD = 331; /** (332) Need account for login. **/ public final static int NEED_ACCOUNT_FOR_LOGIN = 332; /** (350) Requested file action pending further information. **/ public final static int FILE_ACTION_PENDING = 350; /** ** (421) Service not available, closing control connection. This may be a ** reply to any command if the service knows it must shut down. **/ public final static int SERVICE_NOT_AVAILABLE = 421; /** (425) Can't open data connection. **/ public final static int DATA_CONNECTION_NOT_OPEN = 425; /** (426) Connection closed; transfer aborted. **/ public final static int TRANSFER_ABORTED = 426; /** (450) Requested file action not taken. File unavailable (e.g., file busy). **/ public final static int FILE_NOT_AVAILABLE = 450; /** (451) Requested action aborted: local error in processing. **/ public final static int FILE_ABORT_LOCAL_ERROR = 451; /** (452) Requested action not taken. Insufficient storage space in system. **/ public final static int FILE_ABORT_NO_SPACE = 452; /** ** (500) Syntax error, command unrecognized. This may include errors such as ** command line too long. **/ public final static int SYNTAX_ERROR = 500; /** (501) Syntax error in parameters or arguments. **/ public final static int SYNTAX_ERROR_PARAM = 501; /** (502) Command not implemented. **/ public final static int COMMAND_NOT_IMPLEMENTED = 502; /** (503) Bad sequence of commands. **/ public final static int BAD_COMMAND_SEQUENCE = 503; /** (504) Command not implemented for that parameter. **/ public final static int PARAM_NOT_IMPLEMENTED = 504; /** (530) Not logged in. **/ public final static int NOT_LOGGED_IN = 530; /** (532) Need account for storing files. **/ public final static int NEED_ACCOUNT_FOR_STORAGE = 532; /** ** (550) Requested action not taken. File unavailable (e.g., file not found, ** no access). **/ public final static int FILE_NOT_FOUND = 550; /** (551) Requested action aborted: page type unknown. **/ public final static int PAGE_TYPE_UNKNOWN = 551; /** ** (552) Requested file action aborted. Exceeded storage allocation (for ** current directory or dataset). **/ public final static int FILE_ABORT_SPACE_ALLOC = 552; /** (553) Requested action not taken. File name not allowed. **/ public final static int INVALID_FILE_NAME = 553; /** (A) ASCII File Transfer Type **/ public final static String ASCII_TRANSFER_TYPE = "A"; /** (I) Binary File Transfer Type **/ public final static String BINARY_TRANSFER_TYPE = "I"; /** (21) Default Server Port **/ public final static int FTP_PORT = 21; /** Command channel socket. **/ protected Socket socket = null; /** Command channel input reader. **/ protected BufferedReader commIn = null; /** Command channel output writer. **/ protected PrintWriter commOut = null; /** Data channel socket. **/ protected Socket dataSocket = null; /** Host FTP server name or IP address. **/ protected String hostAddress = null; /** Host FTP server port. Defaults to {@link #FTP_PORT}. **/ protected int hostPort = FTP_PORT; /** Host server port for passive data transfer. Defaults to (-1). **/ protected int dataPort = -1; protected URL hostURL = null; protected File localDirectory = null; protected String remoteDirectory = null; protected boolean connected = false; protected String errorMessage = null; protected String lastMessage = null; /** Last message number. Parsed from lastMessage. Defaults to {@link ** #COMMAND_IGNORED}. **/ protected int lastMessageNo = COMMAND_IGNORED; /** Current transfer type. Defaults to {@link #ASCII_TRANSFER_TYPE}. **/ protected String currentTransferType = ASCII_TRANSFER_TYPE; /** Transfer block size in bytes. Defaults to (1024). **/ protected int transferBlockSize = 1024; /** Determines if ftp command channel traffic should be sent to System.out. **/ protected boolean debug = false; /** * Empty constructor. */ public FtpConnection() { } /** * Class constructor specifying the host by URL. * * @param hostURL Passed to {@link #setHostURL(URL) setHostURL()}. */ public FtpConnection( URL hostURL ) { setHostURL( hostURL ); } /** * Class constructor specifying the host connection via parameters. * * @param hostAddress Passed to {@link #setHostAddress(String) setHostAddress()}. * @param hostPort Passed to {@link #setHostPort(int) setHostPort()}. */ public FtpConnection( String hostAddress, int hostPort ) { setHostAddress( hostAddress ); setHostPort( hostPort ); } /** * @param debug {@link #debug} */ public void setDebug( boolean debug ) { this.debug = debug; } /** * Sets {@link #hostAddress}. Calls {@link #disconnect()}. * * @param hostAddress {@link #hostAddress} */ public void setHostAddress( String hostAddress ) { disconnect(); this.hostAddress = hostAddress; } /** * Sets {@link #hostPort}. Port values less than one are ignored. Calls {@link * #disconnect()}. * * @param hostPort {@link #hostPort} */ public void setHostPort( int hostPort ) { disconnect(); if( hostPort > 0 ) { this.hostPort = hostPort; } } /** * Sets host params via URL. Only accepts URL with protocol of ftp. Sets * {@link #hostAddress} via {@link #setHostAddress(String) setHostAddress()}. * Sets {@link #hostPort} via {@link #setHostPort(int) setHostPort()}. If URL * is not accepted then {@link #hostAddress} is set to null and {@link * #hostPort} is set to {@link #FTP_PORT}<br> * <br> * Note: User information within the URL is ignored due to the fact that the * Java 1.1 version of the URL class does not support it. * * @param hostURL */ public void setHostURL( URL hostURL ) { disconnect(); if( (hostURL != null) && hostURL.getProtocol().equals( "ftp" ) ) { setHostAddress( hostURL.getHost() ); setHostPort( hostURL.getPort() ); } else { hostAddress = null; hostPort = FTP_PORT; } this.hostURL = hostURL; } /** * @param localDirectory {@link #localDirectory} */ public void setLocalDirectory( File localDirectory ) { this.localDirectory = localDirectory; } /** * Updates {@link #remoteDirectory} and calls {@link #setDirectory(String) * setDirectory()} if connected. Does nothing if passed remoteDirectory is * same as the current {@link #remoteDirectory}. * * @param remoteDirectory {@link #remoteDirectory} * @return True if successfully updated. */ public boolean setRemoteDirectory( String remoteDirectory ) { errorMessage = null; if( !connected ) { this.remoteDirectory = remoteDirectory; return true; } else if( (remoteDirectory != null) && !remoteDirectory.equals(this.remoteDirectory) ) { return setDirectory( remoteDirectory ); } else if( (remoteDirectory != null) && remoteDirectory.equals(this.remoteDirectory) ) { return true; } return false; } /** * Sets {@link #currentTransferType} and sends TYPE command if connected. Sets * {@link #errorMessage} for errors or if transferType is not {@link * #ASCII_TRANSFER_TYPE} or {@link #BINARY_TRANSFER_TYPE}. * * @param transferType {@link #currentTransferType} * @return True if successfully updated. */ public boolean setTransferType( String transferType ) { try { if( transferType.equals( ASCII_TRANSFER_TYPE ) && transferType.equals( BINARY_TRANSFER_TYPE ) ) { errorMessage = "Transfer Type Not Supported"; } else if( !connected || (sendCommand( "TYPE " + transferType ) == COMMAND_OK) ) { currentTransferType = transferType; return true; } } catch( IOException e ) { errorMessage = e.getMessage(); } return false; } /** * Sets {@link #transferBlockSize}. Value ignored if less than one (1). * * @param transferBlockSize {@link #transferBlockSize} * @return True if successfully updated. */ public boolean setTransferBlockSize( int transferBlockSize ) { if( transferBlockSize > 0 ) { this.transferBlockSize = transferBlockSize; return true; } return false; } /** * @return {@link #hostAddress} */ public String getHostAddress() { return hostAddress; } /** * @return {@link #hostPort} */ public int getHostPort() { return hostPort; } /** * @return {@link #hostURL} */ public URL getHostURL() { return hostURL; } /** * @return {@link #localDirectory} */ public File getLocalDirectory() { return localDirectory; } /** * @return {@link #remoteDirectory} */ public String getRemoteDirectory() { return remoteDirectory; } /** * @return {@link #errorMessage} */ public String getErrorMessage() { return errorMessage; } /** * @return {@link #lastMessage} */ public String getLastMessage() { return lastMessage; } /** * @return {@link #lastMessageNo} */ public int getLastMessageNo() { return lastMessageNo; } /** * @return {@link #transferBlockSize} */ public int getTransferBlockSize() { return transferBlockSize; } /** * @return {@link #connected} */ public boolean isConnected() { return connected; } /** * Gets contents of the {@link #remoteDirectory} using the LIST command. * * @return {@link String} array of detailed directory information */ public String[] getList() { return getList( "LIST", null ); } /** * Gets contents of the specified remote directory using the LIST command. * Directory name can be absolute of relative path. * * @param directoryName * @return {@link String} array of detailed directory * information */ public String[] getList( String directoryName ) { return getList( "LIST", directoryName ); } /** * Gets contents of the {@link #remoteDirectory} using the NLST command. * * @return {@link String} array of file and directory names */ public String[] getNameList() { return getList( "NLST", null ); } /** * Gets contents of the specified remote directory using the NLST command. * Directory name can be absolute of relative path. * * @param directoryName * @return {@link String} array of file and directory names */ public String[] getNameList( String directoryName ) { return getList( "NLST", directoryName ); } /** * Connects o host ftp server. Calls {@link #connect(String,String,String)} * with a null account. * * @param username The username for the login. * @param password The password for the login. * @return True if no errors occurred. */ public boolean connect(String username, String password) { return connect(username, password, null); } /** * Connects to host ftp server. Opens {@link #socket}, {@link #commIn}, and * {@link #commOut}. Sends username, password, account}, and {@link * #currentTransferType}. Sets {@link #connected} to true if no errors * occurred. Calls {@link #setDirectory(String) setDirectory()} if * {@link #remoteDirectory} has been specified prior to connection, * otherwise calls {@link #getCurrentDirectory()}. Sets {@link #errorMessage} * for errors. * * @param username The username for the login. * @param password The password for the login. * @param account The account for the login. * @return True if no errors occurred. */ public boolean connect(String username, String password, String account) { errorMessage = null; if( connected ) { return true; } else if( hostAddress == null ) { errorMessage = "Host Address Not Set"; } else if( hostPort < 1 ) { errorMessage = "Port " + Integer.toString( hostPort ) + " is not valid"; } else if( username == null ) { errorMessage = "Username Not Set"; } else { try { socket = new Socket( hostAddress, hostPort ); commIn = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); commOut = new PrintWriter( socket.getOutputStream() ); if( readCommandChannel() != SERVICE_READY ) { errorMessage = lastMessage; } else if( (sendCommand("USER " + username) != USER_OK_SEND_PASSWORD) && (lastMessageNo != USER_LOGGED_IN) && (lastMessageNo != NEED_ACCOUNT_FOR_LOGIN) ) { errorMessage = lastMessage; } else if( password == null && lastMessageNo == USER_OK_SEND_PASSWORD ) { errorMessage = "Password Required For Account " + username; } else if( (password != null) && (lastMessageNo == USER_OK_SEND_PASSWORD) && (sendCommand("PASS " + password) != USER_LOGGED_IN) && (lastMessageNo != NEED_ACCOUNT_FOR_LOGIN) && (lastMessageNo != COMMAND_SUPERFLUOUS) ) { errorMessage = lastMessage; } else if( (account == null) && (lastMessageNo == NEED_ACCOUNT_FOR_LOGIN) ) { errorMessage = "Account Required For Login"; } else if( (account != null) && (sendCommand("ACCT " + account) != USER_LOGGED_IN) && (lastMessageNo != COMMAND_SUPERFLUOUS) ) { errorMessage = lastMessage; } if( errorMessage == null ) { if( remoteDirectory != null ) { setDirectory( remoteDirectory ); } else { getCurrentDirectory(); } if( currentTransferType.equals( ASCII_TRANSFER_TYPE ) ) { sendCommand( "TYPE " + currentTransferType ); } connected = true; return true; } disconnect(); } catch( IOException e ) { errorMessage = e.getMessage(); } } return false; } /** * Sends re-initialize command (REIN). Calls {@link #getCurrentDirectory()}. * Sets {@link #errorMessage} for errors. * * @return True if no errors occurred. */ public boolean reInitialize() { if( connected ) { try { if( sendCommand("REIN") == SERVICE_READY ) { getCurrentDirectory(); return true; } errorMessage = lastMessage; } catch( IOException e ) { errorMessage = e.getMessage(); } } return false; } /** * Sends quit command (QUIT) and disconnects from ftp server. Closes {@link * #dataSocket}, {@link #commIn}, {@link #commOut}, and {@link #socket}. Sets * {@link #connected} to false. */ public void disconnect() { if( connected ) { if( dataSocket != null ) { try { dataSocket.close(); dataSocket = null; } catch( IOException e ) { } } if( commIn != null ) { try { sendCommand( "QUIT" ); } catch( IOException e ) { } if( commIn != null ) { try { commIn.close(); commIn = null; } catch( IOException e ) { } } } if( commOut != null ) { commOut.close(); commOut = null; } if( socket != null ) { try { socket.close(); socket = null; } catch( IOException e ) { } } connected = false; } } /** * Sends change directory up (CDUP) to change current directory to parent * directory. Calls {@link #getCurrentDirectory()}. Sets {@link #errorMessage} * for errors. * * @return True if no errors occurred. */ public boolean changeDirectoryUp() { errorMessage = null; if( connected ) { try { if( (sendCommand( "CDUP" ) == COMMAND_OK) || (lastMessageNo == FILE_ACTION_OK) ) { getCurrentDirectory(); return true; } errorMessage = lastMessage; } catch( IOException e ) { errorMessage = e.getMessage(); } } return false; } /** * Adds passed subDirectory to {@link #remoteDirectory} and calls {@link * #setRemoteDirectory(String) setRemoteDirectory()}. * * @param subDirectory Name of directory in the current directory to change * to. * @return True if no errors occurred. */ public boolean changeDirectoryDown( String subDirectory ) { errorMessage = null; if( connected && (subDirectory != null) && (remoteDirectory != null) ) { if( remoteDirectory.endsWith( "/" ) ) { setRemoteDirectory( remoteDirectory + subDirectory ); } else { setRemoteDirectory( remoteDirectory + "/" + subDirectory ); } } return false; } /** * Convenience method for {@link #setRemoteDirectory(String) * setRemoteDirectory()}. * * @param directoryName {@link #remoteDirectory} * @return Value from setRemoteDirectory() */ public boolean changeDirectory( String directoryName ) { return setRemoteDirectory( directoryName ); } /** * Sends file using the current transfer type. Sets {@link #errorMessage} if * file is null, file does not exist, directory is passed, or not {@link * #connected}. * * @param file File to transfer * @return True if no errors occurred. */ public boolean sendFile( File file ) { errorMessage = null; if( file == null ) { errorMessage = "File Null"; } else if( !file.exists() ) { errorMessage = "File " + file.toString() + " does not exist"; } else if( !file.isFile() ) { errorMessage = file.toString() + " is not a file"; } else if( !connected ) { errorMessage = "Not Connected"; } else if( openDataSocket() ) { FileInputStream fileInput = null; OutputStream outputStream = null; byte[] data = new byte[transferBlockSize]; try { //Have to go by file.length() because some file systems let you read beyond the // end of the file to the size the file takes up on the file system (Win2K). long bytesRemaining = file.length(); fileInput = new FileInputStream( file ); outputStream = dataSocket.getOutputStream(); if( (sendCommand( "STOR " + file.getName() ) != TRANSFER_STARTING) && (lastMessageNo != FILE_STATUS_OK) ) { errorMessage = lastMessage; } else { while( bytesRemaining > 0L ) { if( bytesRemaining < ( new Integer( transferBlockSize ) ).longValue() ) { data = new byte[( new Long( bytesRemaining ) ).intValue()]; } bytesRemaining -= ( new Integer( fileInput.read(data) ) ).longValue(); outputStream.write( data ); //SEND TO LISTNER HERE } } outputStream.flush(); outputStream.close(); fileInput.close(); if( (errorMessage == null) && (readCommandChannel() != DATA_CONNECTION_CLOSED) && (lastMessageNo != FILE_STATUS_OK) ) { errorMessage = lastMessage; } closeDataSocket(); if( errorMessage == null ) { return true; } } catch( IOException e ) { errorMessage = e.getMessage(); } if( outputStream != null ) { try { outputStream.close(); } catch( IOException e ) { } } if( fileInput != null ) { try { fileInput.close(); } catch( IOException e ) { } } } closeDataSocket(); return false; } /** * Calls {@link #setTransferType(String) setTransferType()} with {@link * #ASCII_TRANSFER_TYPE} and calls {@link #sendFile(File) sendFile()} with * passed file. * * @param file Passed to {@link #sendFile(File) sendFile()}. * @return True if no errors occurred. */ public boolean sendAsciiFile( File file ) { if( !setTransferType( ASCII_TRANSFER_TYPE ) ) { return false; } return sendFile( file ); } /** * Calls {@link #setTransferType(String) setTransferType()} with {@link * #BINARY_TRANSFER_TYPE} and calls {@link #sendFile(File) sendFile()} with * passed file. * * @param file Passed to {@link #sendFile(File) sendFile()}. * @return True if no errors occurred. */ public boolean sendBinaryFile( File file ) { if( !setTransferType( BINARY_TRANSFER_TYPE ) ) { return false; } return sendFile( file ); } /** * Retrieves file from the {@link #remoteDirectory} to the {@link * #localDirectory} using the {@link #currentTransferType}. Sets {@link * #errorMessage} if file is null, {@link #localDirectory} is not set, {@link * #localDirectory} does not exist, {@link #localDirectory} is not a * directory, or not currently {@link #connected}. Sets {@link #errorMessage} * if destination file already exists and overWrite not specified. * * @param fileName Name of file in {@link #remoteDirectory}. * @param overWrite Set true if existing file in {@link #localDirectory} * should be overwritten. * @return True if no errors occurred. */ public boolean receiveFile( String fileName, boolean overWrite ) { errorMessage = null; if( fileName == null ) { errorMessage = "File Null"; } else if( (localDirectory == null) || !localDirectory.exists() || !localDirectory.isDirectory() ) { errorMessage = "Invalid Local Directory"; } else if( !connected ) { errorMessage = "Not Connected"; } else if( openDataSocket() ) { File file = new File( localDirectory, fileName ); if( file.exists() && !overWrite ) { errorMessage = "Local File Already Exists"; } else { FileOutputStream fileOutput = null; InputStream inputStream = null; byte[] data = new byte[transferBlockSize]; try { fileOutput = new FileOutputStream( file ); inputStream = dataSocket.getInputStream(); if( sendCommand( "RETR " + file.getName() ) != TRANSFER_STARTING ) { errorMessage = lastMessage; } else { while( inputStream.read( data ) > 0 ) { fileOutput.write( data ); //SEND TO LISTNER HERE } } fileOutput.flush(); fileOutput.close(); inputStream.close(); if( (errorMessage == null) && (readCommandChannel() != DATA_CONNECTION_CLOSED) && (lastMessageNo != FILE_STATUS_OK) ) { errorMessage = lastMessage; } closeDataSocket(); if( errorMessage == null ) { return true; } } catch( IOException e ) { errorMessage = e.getMessage(); } if( inputStream != null ) { try { inputStream.close(); } catch( IOException e ) { } } if( fileOutput != null ) { try { fileOutput.close(); } catch( IOException e ) { } } } } closeDataSocket(); return false; } // end receiveFile() /** * Calls {@link #setTransferType(String) setTransferType()} with {@link * #ASCII_TRANSFER_TYPE} and calls {@link #receiveFile(String,boolean) * receiveFile()}. * * @param fileName Passed to {@link #receiveFile(String,boolean) * receiveFile()}. * @param overWrite Passed to {@link #receiveFile(String,boolean) * receiveFile()}. * @return True if no errors occurred. */ public boolean receiveAsciiFile( String fileName, boolean overWrite ) { if( !currentTransferType.equals( ASCII_TRANSFER_TYPE ) && !setTransferType( ASCII_TRANSFER_TYPE ) ) { return false; } return receiveFile( fileName, overWrite ); } /** * Calls {@link #setTransferType(String) setTransferType()} with {@link * #BINARY_TRANSFER_TYPE} and calls {@link #receiveFile(String,boolean) * receiveFile()}. * * @param fileName Passed to {@link #receiveFile(String,boolean) * receiveFile()}. * @param overWrite Passed to {@link #receiveFile(String,boolean) * receiveFile()}. * @return True if no errors occurred. */ public boolean receiveBinaryFile( String fileName, boolean overWrite ) { if( !currentTransferType.equals( BINARY_TRANSFER_TYPE ) && !setTransferType( BINARY_TRANSFER_TYPE ) ) { return false; } return receiveFile( fileName, overWrite ); } /** * Sends file rename commands (RNFR + RNTO) for the {@link #remoteDirectory}. * Sets {@link #errorMessage} for errors. * * @param oldFileName * @param newFileName * @return True if no errors occurred. */ public boolean renameFile( String oldFileName, String newFileName ) { try { if( !connected ) { errorMessage = "Not Connected"; } else if( (oldFileName == null) || (newFileName == null) ) { errorMessage = "File Name Null"; } else if( sendCommand( "RNFR " + oldFileName ) != FILE_ACTION_PENDING ) { errorMessage = lastMessage; } else if( sendCommand( "RNTO " + newFileName ) != FILE_ACTION_OK ) { errorMessage = lastMessage; } else { return true; } } catch( IOException e ) { errorMessage = e.getMessage(); } return false; } /** * Sends delete file command (DELE). Sets {@link #errorMessage} for errors. * * @param fileName File to delete in {@link #remoteDirectory}. * @return True if no errors occurred. */ public boolean deleteFile( String fileName ) { try { if( !connected ) { errorMessage = "Not Connected"; } else if( fileName == null ) { errorMessage = "File Name Null"; } else if( sendCommand( "DELE " + fileName ) != FILE_ACTION_OK ) { errorMessage = lastMessage; } else { return true; } } catch( IOException e ) { errorMessage = e.getMessage(); } return false; } /** * Sends remove directory command (RMD). Directory name can be absolute of * relative path. Sets {@link #errorMessage} if not connected or directory * name is null. * * @param directoryName Directory to remove. * @return True if no errors occurred. */ public boolean removeDirectory( String directoryName ) { try { if( !connected ) { errorMessage = "Not Connected"; } else if( directoryName == null ) { errorMessage = "Directory Name Null"; } else if( sendCommand( "RMD " + directoryName ) != FILE_ACTION_OK ) { errorMessage = lastMessage; } else { return true; } } catch( IOException e ) { errorMessage = e.getMessage(); } return false; } /** * Sends make directory command (MKD). Directory name can be absolute of * relative path. Sets {@link #errorMessage} if not connected or directory * name is null. * * @param directoryName Directory to create. * @return True if no errors occurred. */ public boolean makeDirectory( String directoryName ) { try { if( !connected ) { errorMessage = "Not Connected"; } else if( directoryName == null ) { errorMessage = "Directory Name Null"; } else if( sendCommand( "MKD " + directoryName ) != PATH_OK ) { errorMessage = lastMessage; } else { return true; } } catch( IOException e ) { errorMessage = e.getMessage(); } return false; } /** * Sends change directory command (CWD). Directory name can be absolute of * relative path. * * @param directory Remote directory to change to. * @return True if no errors occurred. */ protected boolean setDirectory( String directory ) { try { if( sendCommand( "CWD " + directory ) != FILE_ACTION_OK ) { errorMessage = lastMessage; return false; } } catch( IOException e ) { errorMessage = e.getMessage(); return false; } remoteDirectory = directory; return true; } /** * Sends passive mode command (PASV) and sets {@link #dataPort}. * * @return */ protected boolean setPassiveMode() { try { if( sendCommand( "PASV" ) == PASSIVE_MODE ) { StringTokenizer st = new StringTokenizer( lastMessage, "," ); st.nextToken(); st.nextToken(); st.nextToken(); st.nextToken(); dataPort = ( Integer.parseInt( st.nextToken() ) * 256 ) + Integer.parseInt( st.nextToken( ")" ).substring( 1 ) ); return true; } errorMessage = lastMessage; } catch( IOException e ) { errorMessage = e.getMessage(); } return false; } /** * Gets contents of the specified remote directory using the specified * command. Directory name can be absolute of relative path. {@link * #remoteDirectory} is used if specified directory is null. Sets {@link * #errorMessage} if not connected. * * @param command Ftp command to retrieve directory listing (LIST or * NLST). * @param directoryName Remote directory to list (can be null). * @return {@link String} array of directory contents or null if * error occurred. */ protected String[] getList( String command, String directoryName ) { if( !connected ) { errorMessage = "Not Connected"; return null; } else if( !openDataSocket() ) { return null; } else if( !setTransferType( ASCII_TRANSFER_TYPE ) ) { return null; } Vector names = new Vector(); InputStreamReader inputStreamReader = null; BufferedReader bufferedReader = null; String fullCommand = command; if( directoryName != null ) { fullCommand = fullCommand + " " + directoryName; } try { inputStreamReader = new InputStreamReader( dataSocket.getInputStream() ); bufferedReader = new BufferedReader( inputStreamReader ); if( sendCommand( fullCommand ) == TRANSFER_STARTING ) { String line = bufferedReader.readLine(); while( line != null ) { names.addElement( line ); line = bufferedReader.readLine(); } bufferedReader.close(); inputStreamReader.close(); String[] nameList = new String[names.size()]; for( int x = 0; x < names.size(); x++ ) { nameList[x] = ( String ) names.elementAt( x ); } closeDataSocket(); return nameList; } errorMessage = lastMessage; } catch( IOException e ) { errorMessage = e.getMessage(); } if( bufferedReader != null ) { try { bufferedReader.close(); } catch( IOException e ) { } } if( inputStreamReader != null ) { try { inputStreamReader.close(); } catch( IOException e ) { } } closeDataSocket(); return null; } /** * Retrieves current directory (PWD) and sets {@link #remoteDirectory}. */ protected void getCurrentDirectory() { try { if( sendCommand( "PWD" ) != PATH_OK ) { errorMessage = lastMessage; } else { StringTokenizer st = new StringTokenizer( lastMessage, "\"" ); st.nextToken(); remoteDirectory = st.nextToken(); } } catch( IOException e ) { errorMessage = e.getMessage(); } } /** * Reads from {@link #commIn} and sets {@link #lastMessage} and {@link * #lastMessageNo}. Sends {@link #lastMessage} to System.out if {@link #debug} * is true. Calls {@link #disconnect()} if return from server is {@link * #SERVICE_NOT_AVAILABLE}. * * @return {@link #lastMessageNo} if successful; {@link * #UNKNOWN_ERROR} if parse error; {@link #COMMAND_IGNORED} if not * connected. * @exception IOException */ protected int readCommandChannel() throws IOException { if( commIn != null ) { lastMessage = commIn.readLine(); try { lastMessageNo = Integer.parseInt( lastMessage.substring( 0, 3 ) ); } catch( NumberFormatException e ) { lastMessageNo = UNKNOWN_ERROR; } //PUT LISTENER CALL HERE if( debug ) { System.out.println( lastMessage ); } if( lastMessageNo == SERVICE_NOT_AVAILABLE ) { disconnect(); } return lastMessageNo; } return COMMAND_IGNORED; } /** * Sends command to {@link #commOut} and calls {@link #readCommandChannel()}. * Sends command to System.out if {@link #debug} is true. * * @param command Command string to send to server. * @return Value from {@link #readCommandChannel()} or {@link * #COMMAND_IGNORED} if not connected. * @exception IOException */ protected int sendCommand( String command ) throws IOException { if( commOut != null ) { if( debug ) { System.out.println( command ); } commOut.println( command ); commOut.flush(); //PUT LISTNER CALL HERE return readCommandChannel(); } return COMMAND_IGNORED; } /** * Opens the {@link #dataSocket} using {@link #hostAddress} and {@link * #dataPort}. Calls {@link #closeDataSocket()}. * * @return True if socket successfully created. */ protected boolean openDataSocket() { closeDataSocket(); if( connected && setPassiveMode() ) { try { dataSocket = new Socket( hostAddress, dataPort ); return true; } catch( IOException e ) { errorMessage = e.getMessage(); } } return false; } /** * Closes {@link #dataSocket} if not null. */ protected void closeDataSocket() { if( dataSocket != null ) { try { dataSocket.close(); dataSocket = null; } catch( IOException e ) { } } } } // end FtpConnection
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
