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:
018: import java.util.List;
019:
020: /**
021: * This class implements a bidirectional iterator over an FTPFileList.
022: * Elements may be retrieved one at at time using the hasNext() - next()
023: * syntax familiar from Java 2 collections. Alternatively, entries may
024: * be receieved as an array of any requested number of entries or all of them.
025: *
026: * @author <a href="mailto:scohen@apache.org">Steve Cohen</a>
027: * @version $Id: FTPFileIterator.java 165675 2005-05-02 20:09:55Z rwinston $
028: * @see org.apache.commons.net.ftp.FTPFileList
029: * @see org.apache.commons.net.ftp.FTPFileEntryParser
030: * @see org.apache.commons.net.ftp.FTPListParseEngine
031: * @deprecated This class is deprecated as of version 1.2 and will be
032: * removed in version 2.0 - use FTPFileParseEngine instead
033: */
034: public class FTPFileIterator {
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: this (rawlist, rawlist.getParser());
077: }
078:
079: /**
080: * "Package-private" constructor. Only the FTPFileList can
081: * create an iterator, using it's iterator() method. The list will be
082: * iterated with a supplied parser
083: *
084: * @param rawlist the FTPFileList to be iterated
085: * @param parser the system specific parser for raw FTP entries.
086: */
087: FTPFileIterator(FTPFileList rawlist, FTPFileEntryParser parser) {
088: this .rawlines = rawlist.getLines();
089: this .parser = parser;
090: }
091:
092: /**
093: * Delegates to this object's parser member the job of parsing an
094: * entry.
095: *
096: * @param entry A string containing one entry, as determined by the
097: * parser's getNextEntry() method.
098: *
099: * @return an FTPFile object representing this entry or null if it can't be
100: * parsed as a file
101: */
102: private FTPFile parseFTPEntry(String entry) {
103: return this .parser.parseFTPEntry(entry);
104: }
105:
106: /**
107: * Skips over any introductory lines and stuff in the listing that does
108: * not represent files, returning the line number of the first entry
109: * that does represent a file.
110: *
111: * @return the line number within <code>rawlines</code> of the first good
112: * entry in the array or DIREMPTY if there are no good entries.
113: */
114: private int getFirstGoodEntry() {
115: FTPFile entry = null;
116: for (int iter = 0; iter < this .rawlines.size(); iter++) {
117: String line = (String) this .rawlines.get(iter);
118: entry = parseFTPEntry(line);
119: if (null != entry) {
120: return iter;
121: }
122: }
123: return DIREMPTY;
124: }
125:
126: /**
127: * resets iterator to the beginning of the list.
128: */
129: private void init() {
130: this .itemptr = 0;
131: this .firstGoodEntry = UNINIT;
132: }
133:
134: /**
135: * shorthand for an empty return value.
136: */
137: private static final FTPFile[] EMPTY = new FTPFile[0];
138:
139: /**
140: * Returns a list of FTPFile objects for ALL files listed in the server's
141: * LIST output.
142: *
143: * @return a list of FTPFile objects for ALL files listed in the server's
144: * LIST output.
145: */
146: public FTPFile[] getFiles() {
147: if (this .itemptr != DIREMPTY) {
148: init();
149: }
150: return getNext(0);
151: }
152:
153: /**
154: * Returns an array of at most <code>quantityRequested</code> FTPFile
155: * objects starting at this iterator's current position within its
156: * associated list. If fewer than <code>quantityRequested</code> such
157: * elements are available, the returned array will have a length equal
158: * to the number of entries at and after after the current position.
159: * If no such entries are found, this array will have a length of 0.
160: *
161: * After this method is called the current position is advanced by
162: * either <code>quantityRequested</code> or the number of entries
163: * available after the iterator, whichever is fewer.
164: *
165: * @param quantityRequested
166: * the maximum number of entries we want to get. A 0
167: * passed here is a signal to get ALL the entries.
168: *
169: * @return an array of at most <code>quantityRequested</code> FTPFile
170: * objects starting at the current position of this iterator within its
171: * list and at least the number of elements which exist in the list at
172: * and after its current position.
173: */
174: public FTPFile[] getNext(int quantityRequested) {
175:
176: // if we haven't gotten past the initial junk do so.
177: if (this .firstGoodEntry == UNINIT) {
178: this .firstGoodEntry = getFirstGoodEntry();
179: }
180: if (this .firstGoodEntry == DIREMPTY) {
181: return EMPTY;
182: }
183:
184: int max = this .rawlines.size() - this .firstGoodEntry;
185:
186: // now that we know the maximum we can possibly get,
187: // resolve a 0 request to ask for that many.
188:
189: int howMany = (quantityRequested == 0) ? max
190: : quantityRequested;
191: howMany = (howMany + this .itemptr < this .rawlines.size()) ? howMany
192: : this .rawlines.size() - this .itemptr;
193:
194: FTPFile[] output = new FTPFile[howMany];
195:
196: for (int i = 0, e = this .firstGoodEntry + this .itemptr; i < howMany; i++, e++) {
197: output[i] = parseFTPEntry((String) this .rawlines.get(e));
198: this .itemptr++;
199: }
200: return output;
201: }
202:
203: /**
204: * Method for determining whether getNext() will successfully return a
205: * non-null value.
206: *
207: * @return true if there exist any files after the one currently pointed
208: * to by the internal iterator, false otherwise.
209: */
210: public boolean hasNext() {
211: int fge = this .firstGoodEntry;
212: if (fge == DIREMPTY) {
213: //directory previously found empty - return false
214: return false;
215: } else if (fge < 0) {
216: // we haven't scanned the list yet so do it first
217: fge = getFirstGoodEntry();
218: }
219: return fge + this .itemptr < this .rawlines.size();
220: }
221:
222: /**
223: * Returns a single parsed FTPFile object corresponding to the raw input
224: * line at this iterator's current position.
225: *
226: * After this method is called the internal iterator is advanced by one
227: * element (unless already at end of list).
228: *
229: * @return a single FTPFile object corresponding to the raw input line
230: * at the position of the internal iterator over the list of raw input
231: * lines maintained by this object or null if no such object exists.
232: */
233: public FTPFile next() {
234: FTPFile[] file = getNext(1);
235: if (file.length > 0) {
236: return file[0];
237: } else {
238: return null;
239: }
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: int howMany = quantityRequested;
264: // can't retreat further than we've previously advanced
265: if (howMany > this .itemptr) {
266: howMany = this .itemptr;
267: }
268: FTPFile[] output = new FTPFile[howMany];
269: for (int i = howMany, e = this .firstGoodEntry + this .itemptr; i > 0;) {
270: output[--i] = parseFTPEntry((String) this .rawlines.get(--e));
271: this .itemptr--;
272: }
273: return output;
274: }
275:
276: /**
277: * Method for determining whether getPrevious() will successfully return a
278: * non-null value.
279: *
280: * @return true if there exist any files before the one currently pointed
281: * to by the internal iterator, false otherwise.
282: */
283: public boolean hasPrevious() {
284: int fge = this .firstGoodEntry;
285: if (fge == DIREMPTY) {
286: //directory previously found empty - return false
287: return false;
288: } else if (fge < 0) {
289: // we haven't scanned the list yet so do it first
290: fge = getFirstGoodEntry();
291: }
292:
293: return this .itemptr > fge;
294: }
295:
296: /**
297: * Returns a single parsed FTPFile object corresponding to the raw input
298: * line at the position preceding that of the internal iterator over
299: * the list of raw lines maintained by this object
300: *
301: * After this method is called the internal iterator is retreated by one
302: * element (unless it is already at beginning of list).
303: * @return a single FTPFile object corresponding to the raw input line
304: * at the position immediately preceding that of the internal iterator
305: * over the list of raw input lines maintained by this object.
306: */
307: public FTPFile previous() {
308: FTPFile[] file = getPrevious(1);
309: if (file.length > 0) {
310: return file[0];
311: } else {
312: return null;
313: }
314: }
315: }
316:
317: /* Emacs configuration
318: * Local variables: **
319: * mode: java **
320: * c-basic-offset: 4 **
321: * indent-tabs-mode: nil **
322: * End: **
323: */
|