001 // Copyright 2004, 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry.util; 016 017 import java.util.ArrayList; 018 import java.util.HashMap; 019 import java.util.List; 020 import java.util.Map; 021 022 import org.apache.hivemind.ApplicationRuntimeException; 023 import org.apache.oro.text.regex.MalformedPatternException; 024 import org.apache.oro.text.regex.MatchResult; 025 import org.apache.oro.text.regex.Pattern; 026 import org.apache.oro.text.regex.PatternCompiler; 027 import org.apache.oro.text.regex.PatternMatcher; 028 import org.apache.oro.text.regex.PatternMatcherInput; 029 import org.apache.oro.text.regex.Perl5Compiler; 030 import org.apache.oro.text.regex.Perl5Matcher; 031 032 /** 033 * Streamlines the interface to ORO by implicitly constructing the necessary compilers and matchers, 034 * and by caching compiled patterns. 035 * 036 * @author Howard Lewis Ship 037 * @since 3.0 038 */ 039 040 public class RegexpMatcher 041 { 042 private PatternCompiler _patternCompiler; 043 044 private PatternMatcher _matcher; 045 046 private Map _compiledPatterns = new HashMap(); 047 048 private Map _escapedPatternStrings = new HashMap(); 049 050 protected Pattern compilePattern(String pattern) 051 { 052 if (_patternCompiler == null) 053 _patternCompiler = new Perl5Compiler(); 054 055 try 056 { 057 return _patternCompiler.compile(pattern, Perl5Compiler.SINGLELINE_MASK | Perl5Compiler.READ_ONLY_MASK); 058 } 059 catch (MalformedPatternException ex) 060 { 061 throw new ApplicationRuntimeException(ex); 062 } 063 } 064 065 protected Pattern getCompiledPattern(String pattern) 066 { 067 Pattern result = (Pattern) _compiledPatterns.get(pattern); 068 069 if (result == null) 070 { 071 result = compilePattern(pattern); 072 _compiledPatterns.put(pattern, result); 073 } 074 075 return result; 076 } 077 078 /** 079 * Clears any previously compiled patterns. 080 */ 081 082 public void clear() 083 { 084 _compiledPatterns.clear(); 085 } 086 087 protected PatternMatcher getPatternMatcher() 088 { 089 if (_matcher == null) 090 _matcher = new Perl5Matcher(); 091 092 return _matcher; 093 } 094 095 public boolean matches(String pattern, String input) 096 { 097 Pattern compiledPattern = getCompiledPattern(pattern); 098 099 return getPatternMatcher().matches(input, compiledPattern); 100 } 101 102 public boolean contains(String pattern, String input) 103 { 104 Pattern compiledPattern = getCompiledPattern(pattern); 105 106 return getPatternMatcher().contains(input, compiledPattern); 107 } 108 109 public String getEscapedPatternString(String pattern) 110 { 111 String result = (String) _escapedPatternStrings.get(pattern); 112 113 if (result == null) 114 { 115 result = Perl5Compiler.quotemeta(pattern); 116 117 _escapedPatternStrings.put(pattern, result); 118 } 119 120 return result; 121 } 122 123 /** 124 * Given an input string, finds all matches in an input string for the pattern. 125 * 126 * @param pattern 127 * the regexp pattern for matching 128 * @param input 129 * the string to search for matches within 130 * @return array (possibly empty) of matches 131 * @since 4.0 132 */ 133 public RegexpMatch[] getMatches(String pattern, String input) 134 { 135 Pattern compiledPattern = getCompiledPattern(pattern); 136 137 PatternMatcher matcher = getPatternMatcher(); 138 PatternMatcherInput matcherInput = new PatternMatcherInput(input); 139 140 List matches = new ArrayList(); 141 142 while (matcher.contains(matcherInput, compiledPattern)) 143 { 144 MatchResult match = matcher.getMatch(); 145 146 matches.add(new RegexpMatch(match)); 147 } 148 149 return (RegexpMatch[]) matches.toArray(new RegexpMatch[matches.size()]); 150 } 151 152 /** 153 * Given an input string, finds all matches in an input string for the pattern. 154 * 155 * @param pattern 156 * the regexp pattern for matching 157 * @param input 158 * the string to search for matches within 159 * @param subgroup 160 * the group (sub-expression) within the pattern to return as a match 161 * @return array (possibly empty) of matching strings 162 */ 163 public String[] getMatches(String pattern, String input, int subgroup) 164 { 165 Pattern compiledPattern = getCompiledPattern(pattern); 166 167 PatternMatcher matcher = getPatternMatcher(); 168 PatternMatcherInput matcherInput = new PatternMatcherInput(input); 169 170 List matches = new ArrayList(); 171 172 while (matcher.contains(matcherInput, compiledPattern)) 173 { 174 MatchResult match = matcher.getMatch(); 175 176 String matchedInput = match.group(subgroup); 177 178 matches.add(matchedInput); 179 } 180 181 return (String[]) matches.toArray(new String[matches.size()]); 182 } 183 184 }