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  
18  package org.apache.commons.net.ftp.parser;
19  
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.ListIterator;
23  import java.util.regex.MatchResult;
24  import java.util.regex.Matcher;
25  import java.util.regex.Pattern;
26  import java.util.regex.PatternSyntaxException;
27  
28  import org.apache.commons.net.ftp.FTPClientConfig;
29  
30  /**
31   * Special implementation VMSFTPEntryParser with versioning turned on.
32   * This parser removes all duplicates and only leaves the version with the highest
33   * version number for each filename.
34   *
35   * This is a sample of VMS LIST output
36   *
37   *  "1-JUN.LIS;1              9/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RWED,RE)",
38   *  "1-JUN.LIS;2              9/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RWED,RE)",
39   *  "DATA.DIR;1               1/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RWED,RE)",
40   * <P>
41   *
42   * @author  <a href="Winston.Ojeda@qg.com">Winston Ojeda</a>
43   * @author <a href="sestegra@free.fr">Stephane ESTE-GRACIAS</a>
44   * @version $Id: VMSVersioningFTPEntryParser.java 636854 2008-03-13 19:55:01Z sebb $
45   *
46   * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
47   */
48  public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser
49  {
50  
51      private Matcher _preparse_matcher_;
52      private Pattern _preparse_pattern_;
53      private static final String PRE_PARSE_REGEX =
54          "(.*);([0-9]+)\\s*.*";
55  
56      /**
57       * Constructor for a VMSFTPEntryParser object.  Sets the versioning member
58       * to the supplied value.
59       *
60       * @exception IllegalArgumentException
61       * Thrown if the regular expression is unparseable.  Should not be seen
62       * under normal conditions.  It it is seen, this is a sign that
63       * <code>REGEX</code> is  not a valid regular expression.
64       */
65      public VMSVersioningFTPEntryParser()
66      {
67          this(null);
68      }
69  
70      /**
71       * This constructor allows the creation of a VMSVersioningFTPEntryParser 
72       * object with something other than the default configuration.
73       *
74       * @param config The {@link FTPClientConfig configuration} object used to 
75       * configure this parser.
76       * @exception IllegalArgumentException
77       * Thrown if the regular expression is unparseable.  Should not be seen
78       * under normal conditions.  It it is seen, this is a sign that
79       * <code>REGEX</code> is  not a valid regular expression.
80       * @since 1.4
81       */
82      public VMSVersioningFTPEntryParser(FTPClientConfig config)
83      {
84          super();
85          configure(config);
86          try
87          {
88              //_preparse_matcher_ = new Perl5Matcher();
89              _preparse_pattern_ = Pattern.compile(PRE_PARSE_REGEX);
90          }
91          catch (PatternSyntaxException pse)
92          {
93              throw new IllegalArgumentException (
94                  "Unparseable regex supplied:  " + PRE_PARSE_REGEX);
95          }
96  
97     }
98  
99  
100 
101     private static class NameVersion {
102         String name;
103         int versionNumber;
104         NameVersion(String name, String vers) {
105             this.name = name;
106             this.versionNumber = Integer.parseInt(vers);
107         }
108     }
109 
110     /**
111      * Implement hook provided for those implementers (such as
112      * VMSVersioningFTPEntryParser, and possibly others) which return
113      * multiple files with the same name to remove the duplicates ..
114      *
115      * @param original Original list
116      *
117      * @return Original list purged of duplicates
118      */
119     @Override
120     public List<String> preParse(List<String> original) {
121         original = super.preParse(original);
122         HashMap<String, NameVersion> existingEntries = new HashMap<String, NameVersion>();
123         ListIterator<String> iter = original.listIterator();
124         while (iter.hasNext()) {
125             String entry = iter.next().trim();
126             MatchResult result = null;
127             _preparse_matcher_ = _preparse_pattern_.matcher(entry);
128             if (_preparse_matcher_.matches()) {
129                 result = _preparse_matcher_.toMatchResult();
130                 String name = result.group(1);
131                 String version = result.group(2);
132                 NameVersion nv = new NameVersion(name, version);
133                 NameVersion existing = existingEntries.get(name);
134                 if (null != existing) {
135                     if (nv.versionNumber < existing.versionNumber) {
136                         iter.remove();  // removal removes from original list.
137                         continue;
138                     }
139                 }
140                 existingEntries.put(name, nv);
141             }
142 
143         }
144         // we've now removed all entries less than with less than the largest
145         // version number for each name that were listed after the largest.
146         // we now must remove those with smaller than the largest version number
147         // for each name that were found before the largest
148         while (iter.hasPrevious()) {
149             String entry = iter.previous().trim();
150             MatchResult result = null;
151             _preparse_matcher_ = _preparse_pattern_.matcher(entry);
152             if (_preparse_matcher_.matches()) {
153                 result = _preparse_matcher_.toMatchResult();
154                 String name = result.group(1);
155                 String version = result.group(2);
156                 NameVersion nv = new NameVersion(name, version);
157                 NameVersion existing = existingEntries.get(name);
158                 if (null != existing) {
159                     if (nv.versionNumber < existing.versionNumber) {
160                         iter.remove(); // removal removes from original list.
161                     }
162                 }
163             }
164 
165         }
166         return original;
167     }
168 
169 
170     @Override
171     protected boolean isVersioning() {
172         return true;
173     }
174 
175 }
176 
177 /* Emacs configuration
178  * Local variables:        **
179  * mode:             java  **
180  * c-basic-offset:   4     **
181  * indent-tabs-mode: nil   **
182  * End:                    **
183  */