001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 019package org.apache.commons.net.ftp.parser; 020 021import java.util.regex.MatchResult; 022import java.util.regex.Matcher; 023import java.util.regex.Pattern; 024import java.util.regex.PatternSyntaxException; 025 026import org.apache.commons.net.ftp.FTPFileEntryParserImpl; 027 028/** 029 * This abstract class implements both the older FTPFileListParser and 030 * newer FTPFileEntryParser interfaces with default functionality. 031 * All the classes in the parser subpackage inherit from this. 032 * 033 * This is the base class for all regular expression based FTPFileEntryParser classes 034 */ 035public abstract class RegexFTPFileEntryParserImpl extends 036 FTPFileEntryParserImpl { 037 /** 038 * internal pattern the matcher tries to match, representing a file 039 * entry 040 */ 041 private Pattern pattern = null; 042 043 /** 044 * internal match result used by the parser 045 */ 046 private MatchResult result = null; 047 048 /** 049 * Internal PatternMatcher object used by the parser. It has protected 050 * scope in case subclasses want to make use of it for their own purposes. 051 */ 052 protected Matcher _matcher_ = null; 053 054 /** 055 * The constructor for a RegexFTPFileEntryParserImpl object. 056 * The expression is compiled with flags = 0. 057 * 058 * @param regex The regular expression with which this object is 059 * initialized. 060 * 061 * @exception IllegalArgumentException 062 * Thrown if the regular expression is unparseable. Should not be seen in 063 * normal conditions. It it is seen, this is a sign that a subclass has 064 * been created with a bad regular expression. Since the parser must be 065 * created before use, this means that any bad parser subclasses created 066 * from this will bomb very quickly, leading to easy detection. 067 */ 068 069 public RegexFTPFileEntryParserImpl(String regex) { 070 super(); 071 compileRegex(regex, 0); 072 } 073 074 /** 075 * The constructor for a RegexFTPFileEntryParserImpl object. 076 * 077 * @param regex The regular expression with which this object is 078 * initialized. 079 * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none. 080 * 081 * @exception IllegalArgumentException 082 * Thrown if the regular expression is unparseable. Should not be seen in 083 * normal conditions. It it is seen, this is a sign that a subclass has 084 * been created with a bad regular expression. Since the parser must be 085 * created before use, this means that any bad parser subclasses created 086 * from this will bomb very quickly, leading to easy detection. 087 * @since 3.4 088 */ 089 public RegexFTPFileEntryParserImpl(String regex, final int flags) { 090 super(); 091 compileRegex(regex, flags); 092 } 093 094 /** 095 * Convenience method delegates to the internal MatchResult's matches() 096 * method. 097 * 098 * @param s the String to be matched 099 * @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}