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   * @version $Id: VMSVersioningFTPEntryParser.java 1697293 2015-08-24 01:01:00Z sebb $
43   *
44   * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
45   */
46  public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser
47  {
48  
49      private final Pattern _preparse_pattern_;
50      private static final String PRE_PARSE_REGEX =
51          "(.*?);([0-9]+)\\s*.*";
52  
53      /**
54       * Constructor for a VMSFTPEntryParser object.
55       *
56       * @exception IllegalArgumentException
57       * Thrown if the regular expression is unparseable.  Should not be seen
58       * under normal conditions.  It it is seen, this is a sign that
59       * <code>REGEX</code> is  not a valid regular expression.
60       */
61      public VMSVersioningFTPEntryParser()
62      {
63          this(null);
64      }
65  
66      /**
67       * This constructor allows the creation of a VMSVersioningFTPEntryParser
68       * object with something other than the default configuration.
69       *
70       * @param config The {@link FTPClientConfig configuration} object used to
71       * configure this parser.
72       * @exception IllegalArgumentException
73       * Thrown if the regular expression is unparseable.  Should not be seen
74       * under normal conditions.  It it is seen, this is a sign that
75       * <code>REGEX</code> is  not a valid regular expression.
76       * @since 1.4
77       */
78      public VMSVersioningFTPEntryParser(FTPClientConfig config)
79      {
80          super();
81          configure(config);
82          try
83          {
84              //_preparse_matcher_ = new Perl5Matcher();
85              _preparse_pattern_ = Pattern.compile(PRE_PARSE_REGEX);
86          }
87          catch (PatternSyntaxException pse)
88          {
89              throw new IllegalArgumentException (
90                  "Unparseable regex supplied:  " + PRE_PARSE_REGEX);
91          }
92  
93     }
94  
95      /**
96       * Implement hook provided for those implementers (such as
97       * VMSVersioningFTPEntryParser, and possibly others) which return
98       * multiple files with the same name to remove the duplicates ..
99       *
100      * @param original Original list
101      *
102      * @return Original list purged of duplicates
103      */
104     @Override
105     public List<String> preParse(List<String> original) {
106         HashMap<String, Integer> existingEntries = new HashMap<String, Integer>();
107         ListIterator<String> iter = original.listIterator();
108         while (iter.hasNext()) {
109             String entry = iter.next().trim();
110             MatchResult result = null;
111             Matcher _preparse_matcher_ = _preparse_pattern_.matcher(entry);
112             if (_preparse_matcher_.matches()) {
113                 result = _preparse_matcher_.toMatchResult();
114                 String name = result.group(1);
115                 String version = result.group(2);
116                 Integer nv = Integer.valueOf(version);
117                 Integer existing = existingEntries.get(name);
118                 if (null != existing) {
119                     if (nv.intValue() < existing.intValue()) {
120                         iter.remove();  // removes older version from original list.
121                         continue;
122                     }
123                 }
124                 existingEntries.put(name, nv);
125             }
126 
127         }
128         // we've now removed all entries less than with less than the largest
129         // version number for each name that were listed after the largest.
130         // we now must remove those with smaller than the largest version number
131         // for each name that were found before the largest
132         while (iter.hasPrevious()) {
133             String entry = iter.previous().trim();
134             MatchResult result = null;
135             Matcher _preparse_matcher_ = _preparse_pattern_.matcher(entry);
136             if (_preparse_matcher_.matches()) {
137                 result = _preparse_matcher_.toMatchResult();
138                 String name = result.group(1);
139                 String version = result.group(2);
140                 Integer nv = Integer.valueOf(version);
141                 Integer existing = existingEntries.get(name);
142                 if (null != existing) {
143                     if (nv.intValue() < existing.intValue()) {
144                         iter.remove(); // removes older version from original list.
145                     }
146                 }
147             }
148 
149         }
150         return original;
151     }
152 
153 
154     @Override
155     protected boolean isVersioning() {
156         return true;
157     }
158 
159 }
160 
161 /* Emacs configuration
162  * Local variables:        **
163  * mode:             java  **
164  * c-basic-offset:   4     **
165  * indent-tabs-mode: nil   **
166  * End:                    **
167  */