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  */