001 /* 002 * Copyright 2001-2005 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.net.ftp; 017 import java.util.List; 018 019 /** 020 * This class implements a bidirectional iterator over an FTPFileList. 021 * Elements may be retrieved one at at time using the hasNext() - next() 022 * syntax familiar from Java 2 collections. Alternatively, entries may 023 * be receieved as an array of any requested number of entries or all of them. 024 * 025 * @author <a href="mailto:scohen@apache.org">Steve Cohen</a> 026 * @version $Id: FTPFileIterator.java 165675 2005-05-02 20:09:55Z rwinston $ 027 * @see org.apache.commons.net.ftp.FTPFileList 028 * @see org.apache.commons.net.ftp.FTPFileEntryParser 029 * @see org.apache.commons.net.ftp.FTPListParseEngine 030 * @deprecated This class is deprecated as of version 1.2 and will be 031 * removed in version 2.0 - use FTPFileParseEngine instead 032 */ 033 public class FTPFileIterator 034 { 035 /** 036 * a vector of strings, each representing a possibly valid ftp file 037 * entry 038 */ 039 private List rawlines; 040 041 /** 042 * the parser to which this iterator delegates its parsing duties 043 */ 044 private FTPFileEntryParser parser; 045 046 /** 047 * constant shorthand for the situation where the raw listing has not 048 * yet been scanned 049 */ 050 private static final int UNINIT = -1; 051 052 /** 053 * constant shorthand for the situation where the raw listing has been 054 * scanned and found to have no valid entry. 055 */ 056 private static final int DIREMPTY = -2; 057 058 /** 059 * this iterator's current position within <code>rawlines</code>. 060 */ 061 private int itemptr = 0; 062 063 /** 064 * number within <code>rawlines</code> of the first valid file entry. 065 */ 066 private int firstGoodEntry = UNINIT; 067 068 /** 069 * "Package-private" constructor. Only the FTPFileList can 070 * create an iterator, using it's iterator() method. The list 071 * will be iterated with the list's default parser. 072 * 073 * @param rawlist the FTPFileList to be iterated 074 */ 075 FTPFileIterator (FTPFileList rawlist) 076 { 077 this(rawlist, rawlist.getParser()); 078 } 079 080 /** 081 * "Package-private" constructor. Only the FTPFileList can 082 * create an iterator, using it's iterator() method. The list will be 083 * iterated with a supplied parser 084 * 085 * @param rawlist the FTPFileList to be iterated 086 * @param parser the system specific parser for raw FTP entries. 087 */ 088 FTPFileIterator (FTPFileList rawlist, 089 FTPFileEntryParser parser) 090 { 091 this.rawlines = rawlist.getLines(); 092 this.parser = parser; 093 } 094 095 /** 096 * Delegates to this object's parser member the job of parsing an 097 * entry. 098 * 099 * @param entry A string containing one entry, as determined by the 100 * parser's getNextEntry() method. 101 * 102 * @return an FTPFile object representing this entry or null if it can't be 103 * parsed as a file 104 */ 105 private FTPFile parseFTPEntry(String entry) 106 { 107 return this.parser.parseFTPEntry(entry); 108 } 109 110 /** 111 * Skips over any introductory lines and stuff in the listing that does 112 * not represent files, returning the line number of the first entry 113 * that does represent a file. 114 * 115 * @return the line number within <code>rawlines</code> of the first good 116 * entry in the array or DIREMPTY if there are no good entries. 117 */ 118 private int getFirstGoodEntry() 119 { 120 FTPFile entry = null; 121 for (int iter = 0; iter < this.rawlines.size(); iter++) 122 { 123 String line = (String) this.rawlines.get(iter); 124 entry = parseFTPEntry(line); 125 if (null != entry) 126 { 127 return iter; 128 } 129 } 130 return DIREMPTY; 131 } 132 133 /** 134 * resets iterator to the beginning of the list. 135 */ 136 private void init() 137 { 138 this.itemptr = 0; 139 this.firstGoodEntry = UNINIT; 140 } 141 142 /** 143 * shorthand for an empty return value. 144 */ 145 private static final FTPFile[] EMPTY = new FTPFile[0]; 146 147 /** 148 * Returns a list of FTPFile objects for ALL files listed in the server's 149 * LIST output. 150 * 151 * @return a list of FTPFile objects for ALL files listed in the server's 152 * LIST output. 153 */ 154 public FTPFile[] getFiles() 155 { 156 if (this.itemptr != DIREMPTY) 157 { 158 init(); 159 } 160 return getNext(0); 161 } 162 163 /** 164 * Returns an array of at most <code>quantityRequested</code> FTPFile 165 * objects starting at this iterator's current position within its 166 * associated list. If fewer than <code>quantityRequested</code> such 167 * elements are available, the returned array will have a length equal 168 * to the number of entries at and after after the current position. 169 * If no such entries are found, this array will have a length of 0. 170 * 171 * After this method is called the current position is advanced by 172 * either <code>quantityRequested</code> or the number of entries 173 * available after the iterator, whichever is fewer. 174 * 175 * @param quantityRequested 176 * the maximum number of entries we want to get. A 0 177 * passed here is a signal to get ALL the entries. 178 * 179 * @return an array of at most <code>quantityRequested</code> FTPFile 180 * objects starting at the current position of this iterator within its 181 * list and at least the number of elements which exist in the list at 182 * and after its current position. 183 */ 184 public FTPFile[] getNext(int quantityRequested) 185 { 186 187 // if we haven't gotten past the initial junk do so. 188 if (this.firstGoodEntry == UNINIT) 189 { 190 this.firstGoodEntry = getFirstGoodEntry(); 191 } 192 if (this.firstGoodEntry == DIREMPTY) 193 { 194 return EMPTY; 195 } 196 197 int max = this.rawlines.size() - this.firstGoodEntry; 198 199 // now that we know the maximum we can possibly get, 200 // resolve a 0 request to ask for that many. 201 202 int howMany = (quantityRequested == 0) ? max : quantityRequested; 203 howMany = (howMany + this.itemptr < this.rawlines.size()) 204 ? howMany 205 : this.rawlines.size() - this.itemptr; 206 207 FTPFile[] output = new FTPFile[howMany]; 208 209 for (int i = 0, e = this.firstGoodEntry + this.itemptr ; 210 i < howMany; i++, e++) 211 { 212 output[i] = parseFTPEntry((String) this.rawlines.get(e)); 213 this.itemptr++; 214 } 215 return output; 216 } 217 218 /** 219 * Method for determining whether getNext() will successfully return a 220 * non-null value. 221 * 222 * @return true if there exist any files after the one currently pointed 223 * to by the internal iterator, false otherwise. 224 */ 225 public boolean hasNext() 226 { 227 int fge = this.firstGoodEntry; 228 if (fge == DIREMPTY) 229 { 230 //directory previously found empty - return false 231 return false; 232 } 233 else if (fge < 0) 234 { 235 // we haven't scanned the list yet so do it first 236 fge = getFirstGoodEntry(); 237 } 238 return fge + this.itemptr < this.rawlines.size(); 239 } 240 241 /** 242 * Returns a single parsed FTPFile object corresponding to the raw input 243 * line at this iterator's current position. 244 * 245 * After this method is called the internal iterator is advanced by one 246 * element (unless already at end of list). 247 * 248 * @return a single FTPFile object corresponding to the raw input line 249 * at the position of the internal iterator over the list of raw input 250 * lines maintained by this object or null if no such object exists. 251 */ 252 public FTPFile next() 253 { 254 FTPFile[] file = getNext(1); 255 if (file.length > 0) 256 { 257 return file[0]; 258 } 259 else 260 { 261 return null; 262 } 263 } 264 265 /** 266 * Returns an array of at most <code>quantityRequested</code> FTPFile 267 * objects starting at the position preceding this iterator's current 268 * position within its associated list. If fewer than 269 * <code>quantityRequested</code> such elements are available, the 270 * returned array will have a length equal to the number of entries after 271 * the iterator. If no such entries are found, this array will have a 272 * length of 0. The entries will be ordered in the same order as the 273 * list, not reversed. 274 * 275 * After this method is called the current position is moved back by 276 * either <code>quantityRequested</code> or the number of entries 277 * available before the current position, whichever is fewer. 278 * @param quantityRequested the maximum number of entries we want to get. 279 * A 0 passed here is a signal to get ALL the entries. 280 * @return an array of at most <code>quantityRequested</code> FTPFile 281 * objects starting at the position preceding the current position of 282 * this iterator within its list and at least the number of elements which 283 * exist in the list prior to its current position. 284 */ 285 public FTPFile[] getPrevious(int quantityRequested) 286 { 287 int howMany = quantityRequested; 288 // can't retreat further than we've previously advanced 289 if (howMany > this.itemptr) 290 { 291 howMany = this.itemptr; 292 } 293 FTPFile[] output = new FTPFile[howMany]; 294 for (int i = howMany, e = this.firstGoodEntry + this.itemptr; i > 0;) 295 { 296 output[--i] = parseFTPEntry((String) this.rawlines.get(--e)); 297 this.itemptr--; 298 } 299 return output; 300 } 301 302 /** 303 * Method for determining whether getPrevious() will successfully return a 304 * non-null value. 305 * 306 * @return true if there exist any files before the one currently pointed 307 * to by the internal iterator, false otherwise. 308 */ 309 public boolean hasPrevious() 310 { 311 int fge = this.firstGoodEntry; 312 if (fge == DIREMPTY) 313 { 314 //directory previously found empty - return false 315 return false; 316 } 317 else if (fge < 0) 318 { 319 // we haven't scanned the list yet so do it first 320 fge = getFirstGoodEntry(); 321 } 322 323 return this.itemptr > fge; 324 } 325 326 /** 327 * Returns a single parsed FTPFile object corresponding to the raw input 328 * line at the position preceding that of the internal iterator over 329 * the list of raw lines maintained by this object 330 * 331 * After this method is called the internal iterator is retreated by one 332 * element (unless it is already at beginning of list). 333 * @return a single FTPFile object corresponding to the raw input line 334 * at the position immediately preceding that of the internal iterator 335 * over the list of raw input lines maintained by this object. 336 */ 337 public FTPFile previous() 338 { 339 FTPFile[] file = getPrevious(1); 340 if (file.length > 0) 341 { 342 return file[0]; 343 } 344 else 345 { 346 return null; 347 } 348 } 349 } 350 351 /* Emacs configuration 352 * Local variables: ** 353 * mode: java ** 354 * c-basic-offset: 4 ** 355 * indent-tabs-mode: nil ** 356 * End: ** 357 */