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