001 /* 002 * ftp4j - A pure Java FTP client library 003 * 004 * Copyright (C) 2008 Carlo Pelliccia (www.sauronsoftware.it) 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019 package it.sauronsoftware.ftp4j; 020 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.OutputStream; 024 import java.util.ArrayList; 025 import java.util.Iterator; 026 027 /** 028 * This class is used to represent a communication channel with a FTP server. 029 * 030 * @author Carlo Pelliccia 031 * @version 1.1 032 */ 033 public class FTPCommunicationChannel { 034 035 /** 036 * The FTPCommunicationListener objects registered on the channel. 037 */ 038 private ArrayList communicationListeners = new ArrayList(); 039 040 /** 041 * The connection. 042 */ 043 private FTPConnection connection = null; 044 045 /** 046 * The stream-reader channel established with the remote server. 047 */ 048 private NVTASCIIReader reader = null; 049 050 /** 051 * The stream-writer channel established with the remote server. 052 */ 053 private NVTASCIIWriter writer = null; 054 055 /** 056 * It builds a FTP communication channel. 057 * 058 * @param connection 059 * The underlying connection. 060 * @param charsetName 061 * The name of the charset that has to be used to encode and 062 * decode the communication. 063 * @throws IOException 064 * If a I/O error occurs. 065 */ 066 public FTPCommunicationChannel(FTPConnection connection, String charsetName) 067 throws IOException { 068 this.connection = connection; 069 InputStream inStream = connection.getInputStream(); 070 OutputStream outStream = connection.getOutputStream(); 071 // Wrap the streams into reader and writer objects. 072 reader = new NVTASCIIReader(inStream, charsetName); 073 writer = new NVTASCIIWriter(outStream, charsetName); 074 } 075 076 /** 077 * This method adds a FTPCommunicationListener to the object. 078 * 079 * @param listener 080 * The listener. 081 */ 082 public void addCommunicationListener(FTPCommunicationListener listener) { 083 communicationListeners.add(listener); 084 } 085 086 /** 087 * This method removes a FTPCommunicationListener previously added to the 088 * object. 089 * 090 * @param listener 091 * The listener to be removed. 092 */ 093 public void removeCommunicationListener(FTPCommunicationListener listener) { 094 communicationListeners.remove(listener); 095 } 096 097 /** 098 * Closes the channel. 099 */ 100 public void close() { 101 try { 102 connection.close(); 103 } catch (Exception e) { 104 ; 105 } 106 } 107 108 /** 109 * This method returns a list with all the FTPCommunicationListener used by 110 * the client. 111 * 112 * @return A list with all the FTPCommunicationListener used by the client. 113 */ 114 public FTPCommunicationListener[] getCommunicationListeners() { 115 int size = communicationListeners.size(); 116 FTPCommunicationListener[] ret = new FTPCommunicationListener[size]; 117 for (int i = 0; i < size; i++) { 118 ret[i] = (FTPCommunicationListener) communicationListeners.get(i); 119 } 120 return ret; 121 } 122 123 /** 124 * This method reads a line from the remote server. 125 * 126 * @return The string read. 127 * @throws IOException 128 * If an I/O error occurs during the operation. 129 */ 130 private String read() throws IOException { 131 // Read the line from the server. 132 String line = reader.readLine(); 133 if (line == null) { 134 throw new IOException("FTPConnection closed"); 135 } 136 // Call received() method on every communication listener 137 // registered. 138 for (Iterator iter = communicationListeners.iterator(); iter.hasNext();) { 139 FTPCommunicationListener l = (FTPCommunicationListener) iter.next(); 140 l.received(line); 141 } 142 // Return the line read. 143 return line; 144 } 145 146 /** 147 * This method sends a command line to the server. 148 * 149 * @param command 150 * The command to be sent. 151 * @throws IOException 152 * If an I/O error occurs. 153 */ 154 public void sendFTPCommand(String command) throws IOException { 155 writer.writeLine(command); 156 for (Iterator iter = communicationListeners.iterator(); iter.hasNext();) { 157 FTPCommunicationListener l = (FTPCommunicationListener) iter.next(); 158 l.sent(command); 159 } 160 } 161 162 /** 163 * This method reads and parses a FTP reply statement from the server. 164 * 165 * @return The reply from the server. 166 * @throws IOException 167 * If an I/O error occurs. 168 * @throws FTPIllegalReplyException 169 * If the server doesn't reply in a FTP-compliant way. 170 */ 171 public FTPReply readFTPReply() throws IOException, FTPIllegalReplyException { 172 int code = 0; 173 ArrayList messages = new ArrayList(); 174 do { 175 String statement = read(); 176 int l = statement.length(); 177 if (code == 0 && l < 3) { 178 throw new FTPIllegalReplyException(); 179 } 180 int aux; 181 try { 182 aux = Integer.parseInt(statement.substring(0, 3)); 183 } catch (Exception e) { 184 if (code == 0) { 185 throw new FTPIllegalReplyException(); 186 } else { 187 aux = 0; 188 } 189 } 190 if (code != 0 && aux != 0 && aux != code) { 191 throw new FTPIllegalReplyException(); 192 } 193 if (code == 0) { 194 code = aux; 195 } 196 if (aux > 0 && l > 3) { 197 char s = statement.charAt(3); 198 String message = statement.substring(4, l); 199 messages.add(message); 200 if (s == ' ') { 201 break; 202 } else if (s == '-') { 203 continue; 204 } else { 205 throw new FTPIllegalReplyException(); 206 } 207 } else { 208 messages.add(statement); 209 } 210 } while (true); 211 int size = messages.size(); 212 String[] m = new String[size]; 213 for (int i = 0; i < size; i++) { 214 m[i] = (String) messages.get(i); 215 } 216 return new FTPReply(code, m); 217 } 218 219 /** 220 * Changes the current charset. 221 * 222 * @param charsetName 223 * The new charset. 224 * @throws IOException 225 * If I/O error occurs. 226 * @since 1.1 227 */ 228 public void changeCharset(String charsetName) throws IOException { 229 reader.changeCharset(charsetName); 230 writer.changeCharset(charsetName); 231 } 232 233 }