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 }