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 018package org.apache.commons.net.ftp.parser; 019 020import java.util.regex.MatchResult; 021import java.util.regex.Matcher; 022import java.util.regex.Pattern; 023import java.util.regex.PatternSyntaxException; 024 025import org.apache.commons.net.ftp.FTPFileEntryParserImpl; 026 027/** 028 * This abstract class implements both the older FTPFileListParser and newer FTPFileEntryParser interfaces with default functionality. All the classes in the 029 * parser subpackage inherit from this. 030 * 031 * This is the base class for all regular expression based FTPFileEntryParser classes 032 */ 033public abstract class RegexFTPFileEntryParserImpl extends FTPFileEntryParserImpl { 034 /** 035 * internal pattern the matcher tries to match, representing a file entry 036 */ 037 private Pattern pattern; 038 039 /** 040 * internal match result used by the parser 041 */ 042 private MatchResult result; 043 044 /** 045 * Internal PatternMatcher object used by the parser. It has protected scope in case subclasses want to make use of it for their own purposes. 046 */ 047 protected Matcher _matcher_; 048 049 /** 050 * The constructor for a RegexFTPFileEntryParserImpl object. The expression is compiled with flags = 0. 051 * 052 * @param regex The regular expression with which this object is initialized. 053 * 054 * @throws IllegalArgumentException Thrown if the regular expression is unparseable. Should not be seen in normal conditions. If it is seen, this is a sign 055 * that a subclass has been created with a bad regular expression. Since the parser must be created before use, this means 056 * that any bad parser subclasses created from this will bomb very quickly, leading to easy detection. 057 */ 058 059 public RegexFTPFileEntryParserImpl(final String regex) { 060 compileRegex(regex, 0); 061 } 062 063 /** 064 * The constructor for a RegexFTPFileEntryParserImpl object. 065 * 066 * @param regex The regular expression with which this object is initialized. 067 * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none. 068 * 069 * @throws IllegalArgumentException Thrown if the regular expression is unparseable. Should not be seen in normal conditions. If it is seen, this is a sign 070 * that a subclass has been created with a bad regular expression. Since the parser must be created before use, this means 071 * that any bad parser subclasses created from this will bomb very quickly, leading to easy detection. 072 * @since 3.4 073 */ 074 public RegexFTPFileEntryParserImpl(final String regex, final int flags) { 075 compileRegex(regex, flags); 076 } 077 078 /** 079 * Compile the regex and store the {@link Pattern}. 080 * 081 * This is an internal method to do the work so the constructor does not have to call an overrideable method. 082 * 083 * @param regex the expression to compile 084 * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none. 085 * @throws IllegalArgumentException if the regex cannot be compiled 086 */ 087 private void compileRegex(final String regex, final int flags) { 088 try { 089 pattern = Pattern.compile(regex, flags); 090 } catch (final PatternSyntaxException pse) { 091 throw new IllegalArgumentException("Unparseable regex supplied: " + regex); 092 } 093 } 094 095 /** 096 * Convenience method 097 * 098 * @return the number of groups() in the internal MatchResult. 099 */ 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}