blob: 3780bf559c1975194fbf46c6f7d28dcdaaee066b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package freemarker.ext.jsp;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import freemarker.template.utility.ClassUtil;
import freemarker.template.utility.StringUtil;
final class TaglibMethodUtil {
private TaglibMethodUtil() {
// Not meant to be instantiated
}
private static final Pattern FUNCTION_SIGNATURE_PATTERN =
Pattern.compile("^([\\w\\.]+(\\s*\\[\\s*\\])?)\\s+([\\w]+)\\s*\\((.*)\\)$");
private static final Pattern FUNCTION_PARAMETER_PATTERN =
Pattern.compile("^([\\w\\.]+)(\\s*\\[\\s*\\])?$");
/**
* Finds method by function signature string which is compliant with
* Tag Library function signature in Java Server Page (TM) Specification.
* A function signature example is as follows: {@code java.lang.String nickName( java.lang.String, int)}
*
* @param clazz Class having the method.
* @param signature Java Server Page (TM) Specification compliant function signature string.
* @return method if found.
*/
public static Method getMethodByFunctionSignature(Class clazz, String signature)
throws SecurityException, NoSuchMethodException, ClassNotFoundException {
Matcher m1 = FUNCTION_SIGNATURE_PATTERN.matcher(signature);
if (!m1.matches()) {
throw new IllegalArgumentException("Invalid function signature.");
}
String methodName = m1.group(3);
String params = m1.group(4).trim();
Class [] paramTypes = null;
if ("".equals(params)) {
paramTypes = new Class[0];
} else {
String [] paramsArray = StringUtil.split(params, ',');
paramTypes = new Class[paramsArray.length];
String token = null;
String paramType = null;
boolean isPrimitive = false;
boolean isArrayType = false;
Matcher m2 = null;
for (int i = 0; i < paramsArray.length; i++) {
token = paramsArray[i].trim();
m2 = FUNCTION_PARAMETER_PATTERN.matcher(token);
if (!m2.matches()) {
throw new IllegalArgumentException("Invalid argument signature: '" + token + "'.");
}
paramType = m2.group(1);
isPrimitive = (paramType.indexOf('.') == -1);
isArrayType = (m2.group(2) != null);
if (isPrimitive) {
if ("byte".equals(paramType)) {
paramTypes[i] = (isArrayType ? byte[].class : byte.class);
} else if ("short".equals(paramType)) {
paramTypes[i] = (isArrayType ? short[].class : short.class);
} else if ("int".equals(paramType)) {
paramTypes[i] = (isArrayType ? int[].class : int.class);
} else if ("long".equals(paramType)) {
paramTypes[i] = (isArrayType ? long[].class : long.class);
} else if ("float".equals(paramType)) {
paramTypes[i] = (isArrayType ? float[].class : float.class);
} else if ("double".equals(paramType)) {
paramTypes[i] = (isArrayType ? double[].class : double.class);
} else if ("boolean".equals(paramType)) {
paramTypes[i] = (isArrayType ? boolean[].class : boolean.class);
} else if ("char".equals(paramType)) {
paramTypes[i] = (isArrayType ? char[].class : char.class);
} else {
throw new IllegalArgumentException("Invalid primitive type: '" + paramType + "'.");
}
} else {
if (isArrayType) {
paramTypes[i] = ClassUtil.forName("[L" + paramType + ";");
} else {
paramTypes[i] = ClassUtil.forName(paramType);
}
}
}
}
return clazz.getMethod(methodName, paramTypes);
}
}