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 */ 017package org.apache.activemq.filter.function; 018 019import java.util.regex.Matcher; 020import java.util.regex.Pattern; 021import org.apache.activemq.filter.FunctionCallExpression; 022import org.apache.activemq.filter.MessageEvaluationContext; 023import org.apache.activemq.util.LRUCache; 024 025/** 026 * Filter function that matches a value against a regular expression. 027 * <p/> 028 * <p style="margin-left: 4em"> 029 * REGEX( 'A.B', 'A-B' ) 030 * </p> 031 * <p/> 032 * Note that the regular expression is not anchored; use the anchor characters, ^ and $, as-needed. For example, 033 * REGEX( 'AA', 'XAAX' ) evaluates to true while REGEX( '^AA$' , 'XAAX' ) evaluates to false. 034 */ 035 036public class regexMatchFunction implements FilterFunction { 037 protected static final LRUCache<String, Pattern> compiledExprCache = new LRUCache(100); 038 039 /** 040 * Check whether the given expression is a valid call of this function. Two arguments are required. When 041 * evaluated, the arguments are converted to strings if they are not already strings. 042 * 043 * @param expr - the expression consisting of a call to this function. 044 * @return true - if the expression is valid; false - otherwise. 045 */ 046 047 public boolean isValid(FunctionCallExpression expr) { 048 if (expr.getNumArguments() == 2) 049 return true; 050 051 return false; 052 } 053 054 055 /** 056 * Indicate that this Filter Function evaluates to a Boolean result. 057 * 058 * @param expr - the expression consisting of a call to this function. 059 * @return true - this function always evaluates to a Boolean result. 060 */ 061 062 public boolean returnsBoolean(FunctionCallExpression expr) { 063 return true; 064 } 065 066 /** 067 * Evalutate the given expression, which consists of a call to this function, in the context given. Returns 068 * an indication of whether the second argument matches the regular expression in the first argument. 069 * 070 * @param expr - the expression consisting of a call to this function. 071 * @param message_ctx - the context in which the call is being evaluated. 072 * @return true - if the value matches the regular expression; false - otherwise. 073 */ 074 075 public Object evaluate(FunctionCallExpression expr, MessageEvaluationContext message) 076 throws javax.jms.JMSException { 077 Object reg; 078 Object cand; 079 String reg_str; 080 String cand_str; 081 Pattern pat; 082 Matcher match_eng; 083 084 // 085 // Evaluate the first argument (the regular expression). 086 // 087 reg = expr.getArgument(0).evaluate(message); 088 089 if (reg != null) { 090 // Convert to a string, if it's not already a string. 091 if (reg instanceof String) 092 reg_str = (String) reg; 093 else 094 reg_str = reg.toString(); 095 096 097 // 098 // Evaluate the second argument (the candidate to match against the regular 099 // expression). 100 // 101 cand = expr.getArgument(1).evaluate(message); 102 103 if (cand != null) { 104 // Convert to a string, if it's not already a string. 105 if (cand instanceof String) 106 cand_str = (String) cand; 107 else 108 cand_str = cand.toString(); 109 110 111 // 112 // Obtain the compiled regular expression and match it. 113 // 114 115 pat = getCompiledPattern(reg_str); 116 match_eng = pat.matcher(cand_str); 117 118 119 // 120 // Return an indication of whether the regular expression matches at any 121 // point in the candidate (see Matcher#find()). 122 // 123 124 return Boolean.valueOf(match_eng.find()); 125 } 126 } 127 128 return Boolean.FALSE; 129 } 130 131 132 /** 133 * Retrieve a compiled pattern for the given pattern string. A cache of recently used strings is maintained to 134 * improve performance. 135 * 136 * @param reg_ex_str - the string specifying the regular expression. 137 * @return Pattern - compiled form of the regular expression. 138 */ 139 140 protected Pattern getCompiledPattern(String reg_ex_str) { 141 Pattern result; 142 143 // 144 // Look for the compiled pattern in the cache. 145 // 146 147 synchronized (compiledExprCache) { 148 result = compiledExprCache.get(reg_ex_str); 149 } 150 151 152 // 153 // If it was not found, compile it and add it to the cache. 154 // 155 156 if (result == null) { 157 result = Pattern.compile(reg_ex_str); 158 159 synchronized (compiledExprCache) { 160 compiledExprCache.put(reg_ex_str, result); 161 } 162 } 163 164 return result; 165 } 166}