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.regex.MatchResult;
21  import java.util.regex.Matcher;
22  import java.util.regex.Pattern;
23  import java.util.regex.PatternSyntaxException;
24  
25  import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
26  
27  /**
28   * This abstract class implements both the older FTPFileListParser and newer FTPFileEntryParser interfaces with default functionality. All the classes in the
29   * parser subpackage inherit from this.
30   *
31   * This is the base class for all regular expression based FTPFileEntryParser classes
32   */
33  public abstract class RegexFTPFileEntryParserImpl extends FTPFileEntryParserImpl {
34      /**
35       * internal pattern the matcher tries to match, representing a file entry
36       */
37      private Pattern pattern;
38  
39      /**
40       * internal match result used by the parser
41       */
42      private MatchResult result;
43  
44      /**
45       * Internal PatternMatcher object used by the parser. It has protected scope in case subclasses want to make use of it for their own purposes.
46       */
47      protected Matcher _matcher_;
48  
49      /**
50       * The constructor for a RegexFTPFileEntryParserImpl object. The expression is compiled with flags = 0.
51       *
52       * @param regex The regular expression with which this object is initialized.
53       *
54       * @throws IllegalArgumentException Thrown if the regular expression is unparseable. Should not be seen in normal conditions. If it is seen, this is a sign
55       *                                  that a subclass has been created with a bad regular expression. Since the parser must be created before use, this means
56       *                                  that any bad parser subclasses created from this will bomb very quickly, leading to easy detection.
57       */
58  
59      public RegexFTPFileEntryParserImpl(final String regex) {
60          compileRegex(regex, 0);
61      }
62  
63      /**
64       * The constructor for a RegexFTPFileEntryParserImpl object.
65       *
66       * @param regex The regular expression with which this object is initialized.
67       * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none.
68       *
69       * @throws IllegalArgumentException Thrown if the regular expression is unparseable. Should not be seen in normal conditions. If it is seen, this is a sign
70       *                                  that a subclass has been created with a bad regular expression. Since the parser must be created before use, this means
71       *                                  that any bad parser subclasses created from this will bomb very quickly, leading to easy detection.
72       * @since 3.4
73       */
74      public RegexFTPFileEntryParserImpl(final String regex, final int flags) {
75          compileRegex(regex, flags);
76      }
77  
78      /**
79       * Compile the regex and store the {@link Pattern}.
80       *
81       * This is an internal method to do the work so the constructor does not have to call an overrideable method.
82       *
83       * @param regex the expression to compile
84       * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none.
85       * @throws IllegalArgumentException if the regex cannot be compiled
86       */
87      private void compileRegex(final String regex, final int flags) {
88          try {
89              pattern = Pattern.compile(regex, flags);
90          } catch (final PatternSyntaxException pse) {
91              throw new IllegalArgumentException("Unparseable regex supplied: " + regex);
92          }
93      }
94  
95      /**
96       * Convenience method
97       *
98       * @return the number of groups() in the internal MatchResult.
99       */
100 
101     public int getGroupCnt() {
102         if (this.result == null) {
103             return 0;
104         }
105         return this.result.groupCount();
106     }
107 
108     /**
109      * For debugging purposes - returns a string shows each match group by number.
110      *
111      * @return a string shows each match group by number.
112      */
113 
114     public String getGroupsAsString() {
115         final StringBuilder b = new StringBuilder();
116         for (int i = 1; i <= this.result.groupCount(); i++) {
117             b.append(i).append(") ").append(this.result.group(i)).append(System.lineSeparator());
118         }
119         return b.toString();
120     }
121 
122     /**
123      * Convenience method delegates to the internal MatchResult's group() method.
124      *
125      * @param matchNum match group number to be retrieved
126      *
127      * @return the content of the <code>matchnum'th</code> group of the internal match or null if this method is called without a match having been made.
128      */
129     public String group(final int matchNum) {
130         if (this.result == null) {
131             return null;
132         }
133         return this.result.group(matchNum);
134     }
135 
136     /**
137      * Convenience method delegates to the internal MatchResult's matches() method.
138      *
139      * @param s the String to be matched
140      * @return true if s matches this object's regular expression.
141      */
142 
143     public boolean matches(final String s) {
144         this.result = null;
145         _matcher_ = pattern.matcher(s);
146         if (_matcher_.matches()) {
147             this.result = _matcher_.toMatchResult();
148         }
149         return null != this.result;
150     }
151 
152     /**
153      * Alter the current regular expression being utilised for entry parsing and create a new {@link Pattern} instance.
154      *
155      * @param regex The new regular expression
156      * @return true
157      * @since 2.0
158      * @throws IllegalArgumentException if the regex cannot be compiled
159      */
160     public boolean setRegex(final String regex) {
161         compileRegex(regex, 0);
162         return true;
163     }
164 
165     /**
166      * Alter the current regular expression being utilised for entry parsing and create a new {@link Pattern} instance.
167      *
168      * @param regex The new regular expression
169      * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none.
170      * @return true
171      * @since 3.4
172      * @throws IllegalArgumentException if the regex cannot be compiled
173      */
174     public boolean setRegex(final String regex, final int flags) {
175         compileRegex(regex, flags);
176         return true;
177     }
178 }