1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.net.ftp;
  17. import java.util.List;
  18. /**
  19. * This class implements a bidirectional iterator over an FTPFileList.
  20. * Elements may be retrieved one at at time using the hasNext() - next()
  21. * syntax familiar from Java 2 collections. Alternatively, entries may
  22. * be receieved as an array of any requested number of entries or all of them.
  23. *
  24. * @author <a href="mailto:scohen@apache.org">Steve Cohen</a>
  25. * @version $Id: FTPFileIterator.java,v 1.12 2004/04/21 23:30:33 scohen Exp $
  26. * @see org.apache.commons.net.ftp.FTPFileList
  27. * @see org.apache.commons.net.ftp.FTPFileEntryParser
  28. * @see org.apache.commons.net.ftp.FTPListParseEngine
  29. * @deprecated This class is deprecated as of version 1.2 and will be
  30. * removed in version 2.0 - use FTPFileParseEngine instead
  31. */
  32. public class FTPFileIterator
  33. {
  34. /**
  35. * a vector of strings, each representing a possibly valid ftp file
  36. * entry
  37. */
  38. private List rawlines;
  39. /**
  40. * the parser to which this iterator delegates its parsing duties
  41. */
  42. private FTPFileEntryParser parser;
  43. /**
  44. * constant shorthand for the situation where the raw listing has not
  45. * yet been scanned
  46. */
  47. private static final int UNINIT = -1;
  48. /**
  49. * constant shorthand for the situation where the raw listing has been
  50. * scanned and found to have no valid entry.
  51. */
  52. private static final int DIREMPTY = -2;
  53. /**
  54. * this iterator's current position within <code>rawlines</code>.
  55. */
  56. private int itemptr = 0;
  57. /**
  58. * number within <code>rawlines</code> of the first valid file entry.
  59. */
  60. private int firstGoodEntry = UNINIT;
  61. /**
  62. * "Package-private" constructor. Only the FTPFileList can
  63. * create an iterator, using it's iterator() method. The list
  64. * will be iterated with the list's default parser.
  65. *
  66. * @param rawlist the FTPFileList to be iterated
  67. */
  68. FTPFileIterator (FTPFileList rawlist)
  69. {
  70. this(rawlist, rawlist.getParser());
  71. }
  72. /**
  73. * "Package-private" constructor. Only the FTPFileList can
  74. * create an iterator, using it's iterator() method. The list will be
  75. * iterated with a supplied parser
  76. *
  77. * @param rawlist the FTPFileList to be iterated
  78. * @param parser the system specific parser for raw FTP entries.
  79. */
  80. FTPFileIterator (FTPFileList rawlist,
  81. FTPFileEntryParser parser)
  82. {
  83. this.rawlines = rawlist.getLines();
  84. this.parser = parser;
  85. }
  86. /**
  87. * Delegates to this object's parser member the job of parsing an
  88. * entry.
  89. *
  90. * @param entry A string containing one entry, as determined by the
  91. * parser's getNextEntry() method.
  92. *
  93. * @return an FTPFile object representing this entry or null if it can't be
  94. * parsed as a file
  95. */
  96. private FTPFile parseFTPEntry(String entry)
  97. {
  98. return this.parser.parseFTPEntry(entry);
  99. }
  100. /**
  101. * Skips over any introductory lines and stuff in the listing that does
  102. * not represent files, returning the line number of the first entry
  103. * that does represent a file.
  104. *
  105. * @return the line number within <code>rawlines</code> of the first good
  106. * entry in the array or DIREMPTY if there are no good entries.
  107. */
  108. private int getFirstGoodEntry()
  109. {
  110. FTPFile entry = null;
  111. for (int iter = 0; iter < this.rawlines.size(); iter++)
  112. {
  113. String line = (String) this.rawlines.get(iter);
  114. entry = parseFTPEntry(line);
  115. if (null != entry)
  116. {
  117. return iter;
  118. }
  119. }
  120. return DIREMPTY;
  121. }
  122. /**
  123. * resets iterator to the beginning of the list.
  124. */
  125. private void init()
  126. {
  127. this.itemptr = 0;
  128. this.firstGoodEntry = UNINIT;
  129. }
  130. /**
  131. * shorthand for an empty return value.
  132. */
  133. private static final FTPFile[] EMPTY = new FTPFile[0];
  134. /**
  135. * Returns a list of FTPFile objects for ALL files listed in the server's
  136. * LIST output.
  137. *
  138. * @return a list of FTPFile objects for ALL files listed in the server's
  139. * LIST output.
  140. */
  141. public FTPFile[] getFiles()
  142. {
  143. if (this.itemptr != DIREMPTY)
  144. {
  145. init();
  146. }
  147. return getNext(0);
  148. }
  149. /**
  150. * Returns an array of at most <code>quantityRequested</code> FTPFile
  151. * objects starting at this iterator's current position within its
  152. * associated list. If fewer than <code>quantityRequested</code> such
  153. * elements are available, the returned array will have a length equal
  154. * to the number of entries at and after after the current position.
  155. * If no such entries are found, this array will have a length of 0.
  156. *
  157. * After this method is called the current position is advanced by
  158. * either <code>quantityRequested</code> or the number of entries
  159. * available after the iterator, whichever is fewer.
  160. *
  161. * @param quantityRequested
  162. * the maximum number of entries we want to get. A 0
  163. * passed here is a signal to get ALL the entries.
  164. *
  165. * @return an array of at most <code>quantityRequested</code> FTPFile
  166. * objects starting at the current position of this iterator within its
  167. * list and at least the number of elements which exist in the list at
  168. * and after its current position.
  169. */
  170. public FTPFile[] getNext(int quantityRequested)
  171. {
  172. // if we haven't gotten past the initial junk do so.
  173. if (this.firstGoodEntry == UNINIT)
  174. {
  175. this.firstGoodEntry = getFirstGoodEntry();
  176. }
  177. if (this.firstGoodEntry == DIREMPTY)
  178. {
  179. return EMPTY;
  180. }
  181. int max = this.rawlines.size() - this.firstGoodEntry;
  182. // now that we know the maximum we can possibly get,
  183. // resolve a 0 request to ask for that many.
  184. int howMany = (quantityRequested == 0) ? max : quantityRequested;
  185. howMany = (howMany + this.itemptr < this.rawlines.size())
  186. ? howMany
  187. : this.rawlines.size() - this.itemptr;
  188. FTPFile[] output = new FTPFile[howMany];
  189. for (int i = 0, e = this.firstGoodEntry + this.itemptr ;
  190. i < howMany; i++, e++)
  191. {
  192. output[i] = parseFTPEntry((String) this.rawlines.get(e));
  193. this.itemptr++;
  194. }
  195. return output;
  196. }
  197. /**
  198. * Method for determining whether getNext() will successfully return a
  199. * non-null value.
  200. *
  201. * @return true if there exist any files after the one currently pointed
  202. * to by the internal iterator, false otherwise.
  203. */
  204. public boolean hasNext()
  205. {
  206. int fge = this.firstGoodEntry;
  207. if (fge == DIREMPTY)
  208. {
  209. //directory previously found empty - return false
  210. return false;
  211. }
  212. else if (fge < 0)
  213. {
  214. // we haven't scanned the list yet so do it first
  215. fge = getFirstGoodEntry();
  216. }
  217. return fge + this.itemptr < this.rawlines.size();
  218. }
  219. /**
  220. * Returns a single parsed FTPFile object corresponding to the raw input
  221. * line at this iterator's current position.
  222. *
  223. * After this method is called the internal iterator is advanced by one
  224. * element (unless already at end of list).
  225. *
  226. * @return a single FTPFile object corresponding to the raw input line
  227. * at the position of the internal iterator over the list of raw input
  228. * lines maintained by this object or null if no such object exists.
  229. */
  230. public FTPFile next()
  231. {
  232. FTPFile[] file = getNext(1);
  233. if (file.length > 0)
  234. {
  235. return file[0];
  236. }
  237. else
  238. {
  239. return null;
  240. }
  241. }
  242. /**
  243. * Returns an array of at most <code>quantityRequested</code> FTPFile
  244. * objects starting at the position preceding this iterator's current
  245. * position within its associated list. If fewer than
  246. * <code>quantityRequested</code> such elements are available, the
  247. * returned array will have a length equal to the number of entries after
  248. * the iterator. If no such entries are found, this array will have a
  249. * length of 0. The entries will be ordered in the same order as the
  250. * list, not reversed.
  251. *
  252. * After this method is called the current position is moved back by
  253. * either <code>quantityRequested</code> or the number of entries
  254. * available before the current position, whichever is fewer.
  255. * @param quantityRequested the maximum number of entries we want to get.
  256. * A 0 passed here is a signal to get ALL the entries.
  257. * @return an array of at most <code>quantityRequested</code> FTPFile
  258. * objects starting at the position preceding the current position of
  259. * this iterator within its list and at least the number of elements which
  260. * exist in the list prior to its current position.
  261. */
  262. public FTPFile[] getPrevious(int quantityRequested)
  263. {
  264. int howMany = quantityRequested;
  265. // can't retreat further than we've previously advanced
  266. if (howMany > this.itemptr)
  267. {
  268. howMany = this.itemptr;
  269. }
  270. FTPFile[] output = new FTPFile[howMany];
  271. for (int i = howMany, e = this.firstGoodEntry + this.itemptr; i > 0;)
  272. {
  273. output[--i] = parseFTPEntry((String) this.rawlines.get(--e));
  274. this.itemptr--;
  275. }
  276. return output;
  277. }
  278. /**
  279. * Method for determining whether getPrevious() will successfully return a
  280. * non-null value.
  281. *
  282. * @return true if there exist any files before the one currently pointed
  283. * to by the internal iterator, false otherwise.
  284. */
  285. public boolean hasPrevious()
  286. {
  287. int fge = this.firstGoodEntry;
  288. if (fge == DIREMPTY)
  289. {
  290. //directory previously found empty - return false
  291. return false;
  292. }
  293. else if (fge < 0)
  294. {
  295. // we haven't scanned the list yet so do it first
  296. fge = getFirstGoodEntry();
  297. }
  298. return this.itemptr > fge;
  299. }
  300. /**
  301. * Returns a single parsed FTPFile object corresponding to the raw input
  302. * line at the position preceding that of the internal iterator over
  303. * the list of raw lines maintained by this object
  304. *
  305. * After this method is called the internal iterator is retreated by one
  306. * element (unless it is already at beginning of list).
  307. * @return a single FTPFile object corresponding to the raw input line
  308. * at the position immediately preceding that of the internal iterator
  309. * over the list of raw input lines maintained by this object.
  310. */
  311. public FTPFile previous()
  312. {
  313. FTPFile[] file = getPrevious(1);
  314. if (file.length > 0)
  315. {
  316. return file[0];
  317. }
  318. else
  319. {
  320. return null;
  321. }
  322. }
  323. }
  324. /* Emacs configuration
  325. * Local variables: **
  326. * mode: java **
  327. * c-basic-offset: 4 **
  328. * indent-tabs-mode: nil **
  329. * End: **
  330. */