View Javadoc

1   /*
2    * Copyright 2001-2005 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  /**
20   * This class implements a bidirectional iterator over an FTPFileList.
21   * Elements may be retrieved one at at time using the hasNext() - next()
22   * syntax familiar from Java 2 collections.  Alternatively, entries may
23   * be receieved as an array of any requested number of entries or all of them.
24   *
25   * @author <a href="mailto:scohen@apache.org">Steve Cohen</a>
26   * @version $Id: FTPFileIterator.java 165675 2005-05-02 20:09:55Z rwinston $
27   * @see org.apache.commons.net.ftp.FTPFileList
28   * @see org.apache.commons.net.ftp.FTPFileEntryParser
29   * @see org.apache.commons.net.ftp.FTPListParseEngine
30   * @deprecated This class is deprecated as of version 1.2 and will be
31   * removed in version 2.0 - use FTPFileParseEngine instead
32   */
33  public class FTPFileIterator
34  {
35      /**
36       * a vector of strings, each representing a possibly valid ftp file
37       * entry
38       */
39      private List rawlines;
40  
41      /**
42       * the parser to which this iterator delegates its parsing duties
43       */
44      private FTPFileEntryParser parser;
45  
46      /**
47       * constant shorthand for the situation where the raw listing has not
48       * yet been scanned
49       */
50      private static final int UNINIT = -1;
51  
52      /**
53       * constant shorthand for the situation where the raw listing has been
54       * scanned and found to have no valid entry.
55       */
56      private static final int DIREMPTY = -2;
57  
58      /**
59       * this iterator's current position within <code>rawlines</code>.
60       */
61      private int itemptr = 0;
62  
63      /**
64       * number within <code>rawlines</code> of the first valid file entry.
65       */
66      private int firstGoodEntry = UNINIT;
67  
68      /**
69       * "Package-private" constructor.  Only the FTPFileList can
70       * create an iterator, using it's iterator() method.  The list
71       * will be iterated with the list's default parser.
72       *
73       * @param rawlist the FTPFileList to be iterated
74       */
75      FTPFileIterator (FTPFileList rawlist)
76      {
77          this(rawlist, rawlist.getParser());
78      }
79  
80      /**
81       * "Package-private" constructor.  Only the FTPFileList can
82       * create an iterator, using it's iterator() method.  The list will be
83       * iterated with a supplied parser
84       *
85       * @param rawlist the FTPFileList to be iterated
86       * @param parser the system specific parser for raw FTP entries.
87       */
88      FTPFileIterator (FTPFileList rawlist,
89                              FTPFileEntryParser parser)
90      {
91          this.rawlines = rawlist.getLines();
92          this.parser = parser;
93      }
94  
95      /**
96       * Delegates to this object's parser member the job of parsing an
97       * entry.
98       *
99       * @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  */