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 org.apache.commons.pool.KeyedPoolableObjectFactory; 018 import org.apache.commons.pool.impl.GenericKeyedObjectPool; 019 import org.apache.hivemind.ApplicationRuntimeException; 020 import org.apache.oro.text.regex.Perl5Compiler; 021 022 import java.util.ArrayList; 023 import java.util.HashMap; 024 import java.util.List; 025 import java.util.Map; 026 import java.util.regex.Matcher; 027 import java.util.regex.Pattern; 028 029 /** 030 * Streamlines the interface to ORO by implicitly constructing the necessary compilers and matchers, 031 * and by caching compiled patterns. 032 * 033 */ 034 035 public class RegexpMatcher 036 { 037 private static final long SLEEP_TIME = 1000 * 60 * 4; 038 039 private static final long EVICT_IDLE_TIME = 1000 * 60 * 60; 040 041 private final KeyedPoolableObjectFactory _factory = new RegexpPoolObjectFactory(); 042 043 private final GenericKeyedObjectPool _pool; 044 045 private Map _escapedPatternStrings = new HashMap(); 046 047 public RegexpMatcher() 048 { 049 _pool = new GenericKeyedObjectPool(_factory); 050 051 _pool.setMinEvictableIdleTimeMillis(EVICT_IDLE_TIME); 052 _pool.setTimeBetweenEvictionRunsMillis(SLEEP_TIME); 053 } 054 055 /** 056 * Clears any previously compiled patterns. 057 */ 058 public void clear() 059 { 060 _pool.clear(); 061 } 062 063 public boolean matches(String pattern, String input) 064 { 065 Pattern compiled = null; 066 067 try { 068 069 compiled = (Pattern)_pool.borrowObject(pattern); 070 071 return compiled.matcher(input).matches(); 072 073 } catch (Exception e) { 074 075 throw new ApplicationRuntimeException(e); 076 } finally { 077 078 try { _pool.returnObject(pattern, compiled); } catch (Throwable t) { } 079 } 080 } 081 082 public boolean contains(String pattern, String input) 083 { 084 Pattern compiled = null; 085 086 try { 087 088 compiled = (Pattern)_pool.borrowObject(pattern); 089 090 return compiled.matcher(input).find(); 091 092 } catch (Exception e) { 093 094 throw new ApplicationRuntimeException(e); 095 } finally { 096 097 try { _pool.returnObject(pattern, compiled); } catch (Throwable t) { } 098 } 099 } 100 101 public String getEscapedPatternString(String pattern) 102 { 103 String result = (String) _escapedPatternStrings.get(pattern); 104 105 if (result == null) 106 { 107 result = Perl5Compiler.quotemeta(pattern); 108 109 _escapedPatternStrings.put(pattern, result); 110 } 111 112 return result; 113 } 114 115 /** 116 * Given an input string, finds all matches in an input string for the pattern. 117 * 118 * @param pattern 119 * the regexp pattern for matching 120 * @param input 121 * the string to search for matches within 122 * @return array (possibly empty) of matches 123 * @since 4.0 124 */ 125 public RegexpMatch[] getMatches(String pattern, String input) 126 { 127 Pattern compiled = null; 128 129 try { 130 131 compiled = (Pattern)_pool.borrowObject(pattern); 132 133 Matcher matcher = compiled.matcher(input); 134 List matches = new ArrayList(); 135 136 while (matcher.find()) 137 { 138 int length = matcher.groupCount(); 139 String[] groups = new String[length + 1]; 140 groups[0] = matcher.group(); 141 142 for (int i=1; i <= length; i++) { 143 groups[i] = matcher.group(i); 144 } 145 146 matches.add(new RegexpMatch(length, groups)); 147 } 148 149 return (RegexpMatch[]) matches.toArray(new RegexpMatch[matches.size()]); 150 151 } catch (Exception e) { 152 153 throw new ApplicationRuntimeException(e); 154 } finally { 155 156 try { _pool.returnObject(pattern, compiled); } catch (Throwable t) { } 157 } 158 } 159 160 /** 161 * Given an input string, finds all matches in an input string for the pattern. 162 * 163 * @param pattern 164 * the regexp pattern for matching 165 * @param input 166 * the string to search for matches within 167 * @param subgroup 168 * the group (sub-expression) within the pattern to return as a match 169 * @return array (possibly empty) of matching strings 170 */ 171 public String[] getMatches(String pattern, String input, int subgroup) 172 { 173 Pattern compiled = null; 174 175 try { 176 177 compiled = (Pattern)_pool.borrowObject(pattern); 178 179 Matcher matcher = compiled.matcher(input); 180 List matches = new ArrayList(); 181 182 while (matcher.find()) 183 { 184 String matchedInput = matcher.group(subgroup); 185 186 matches.add(matchedInput); 187 } 188 189 return (String[]) matches.toArray(new String[matches.size()]); 190 191 } catch (Exception e) { 192 193 throw new ApplicationRuntimeException(e); 194 } finally { 195 196 try { _pool.returnObject(pattern, compiled); } catch (Throwable t) { } 197 } 198 } 199 200 }