View Javadoc

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