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.hivemind.methodmatch; 016 017 import java.util.ArrayList; 018 import java.util.List; 019 020 import org.apache.hivemind.ApplicationRuntimeException; 021 import org.apache.hivemind.util.StringUtils; 022 023 /** 024 * Parses a method pattern (consisting of a name pattern, followed by an optional parameters 025 * pattern) into a {@link org.apache.hivemind.methodmatch.MethodFilter}. In most cases, the 026 * patterns will require several checks (i.e., match against name, match against parameters) in 027 * which case a {@link org.apache.hivemind.methodmatch.CompositeFilter} is returned. 028 * 029 * @author Howard Lewis Ship 030 */ 031 032 public class MethodPatternParser 033 { 034 private List _filters; 035 036 public MethodFilter parseMethodPattern(String pattern) 037 { 038 _filters = new ArrayList(); 039 040 int parenx = pattern.indexOf('('); 041 042 String namePattern = parenx < 0 ? pattern : pattern.substring(0, parenx); 043 044 parseNamePattern(pattern, namePattern); 045 046 if (parenx >= 0) 047 parseParametersPattern(pattern, pattern.substring(parenx)); 048 049 switch (_filters.size()) 050 { 051 case 0: 052 return new MatchAllFilter(); 053 054 case 1: 055 056 return (MethodFilter) _filters.get(0); 057 058 default: 059 return new CompositeFilter(_filters); 060 } 061 } 062 063 private void parseNamePattern(String methodPattern, String namePattern) 064 { 065 if (namePattern.equals("*")) 066 return; 067 068 if (namePattern.length() == 0) 069 throw new ApplicationRuntimeException(MethodMatchMessages 070 .missingNamePattern(methodPattern)); 071 072 if (namePattern.startsWith("*") && namePattern.endsWith("*")) 073 { 074 String substring = namePattern.substring(1, namePattern.length() - 1); 075 076 validateNamePattern(methodPattern, substring); 077 078 _filters.add(new InfixNameFilter(substring)); 079 return; 080 } 081 082 if (namePattern.startsWith("*")) 083 { 084 String suffix = namePattern.substring(1); 085 086 validateNamePattern(methodPattern, suffix); 087 088 _filters.add(new NameSuffixFilter(suffix)); 089 return; 090 } 091 092 if (namePattern.endsWith("*")) 093 { 094 String prefix = namePattern.substring(0, namePattern.length() - 1); 095 096 validateNamePattern(methodPattern, prefix); 097 098 _filters.add(new NamePrefixFilter(prefix)); 099 return; 100 } 101 102 validateNamePattern(methodPattern, namePattern); 103 104 _filters.add(new ExactNameFilter(namePattern)); 105 } 106 107 private void parseParametersPattern(String methodPattern, String pattern) 108 { 109 if (pattern.equals("()")) 110 { 111 addParameterCountFilter(0); 112 return; 113 } 114 115 if (!pattern.endsWith(")")) 116 throw new ApplicationRuntimeException(MethodMatchMessages 117 .invalidParametersPattern(methodPattern)); 118 119 // Trim off leading and trailing parens. 120 121 pattern = pattern.substring(1, pattern.length() - 1); 122 123 char ch = pattern.charAt(0); 124 125 if (Character.isDigit(ch)) 126 { 127 addParameterCountFilter(methodPattern, pattern); 128 return; 129 } 130 131 String[] names = StringUtils.split(pattern); 132 133 // Would be nice to do some kind of validation here, to prove 134 // that the provided class names exist, and that 135 // primitive types names are valid. 136 137 addParameterCountFilter(names.length); 138 for (int i = 0; i < names.length; i++) 139 _filters.add(new ParameterFilter(i, names[i].trim())); 140 141 } 142 143 private void addParameterCountFilter(String methodPattern, String pattern) 144 { 145 try 146 { 147 int count = Integer.parseInt(pattern); 148 addParameterCountFilter(count); 149 } 150 catch (NumberFormatException ex) 151 { 152 throw new ApplicationRuntimeException(MethodMatchMessages 153 .invalidParametersPattern(methodPattern)); 154 } 155 } 156 157 private void addParameterCountFilter(int count) 158 { 159 // Add the count filter first, since it is always the least expensive test. 160 _filters.add(0, new ParameterCountFilter(count)); 161 } 162 163 private void validateNamePattern(String methodPattern, String nameSubstring) 164 { 165 if (nameSubstring.indexOf('*') >= 0) 166 throw new ApplicationRuntimeException(MethodMatchMessages 167 .invalidNamePattern(methodPattern)); 168 } 169 }