Registers a function in the EL context by looking up the static method in the given class. The method name may include a return type and parameter signature in the format returnType methodName(paramTypes). The function is then callable in EL expressions as prefix:function(args). @pa
(String prefix, String function, String className, String methodName)
| 148 | * @throws NoSuchMethodException if the method cannot be found or is not a public static method |
| 149 | */ |
| 150 | public void defineFunction(String prefix, String function, String className, String methodName) |
| 151 | throws ClassNotFoundException, NoSuchMethodException { |
| 152 | |
| 153 | if (prefix == null || function == null || className == null || methodName == null) { |
| 154 | throw new NullPointerException(Util.message(context, "elProcessor.defineFunctionNullParams")); |
| 155 | } |
| 156 | |
| 157 | // Check the imports |
| 158 | Class<?> clazz = context.getImportHandler().resolveClass(className); |
| 159 | |
| 160 | if (clazz == null) { |
| 161 | clazz = Class.forName(className, true, Thread.currentThread().getContextClassLoader()); |
| 162 | } |
| 163 | |
| 164 | if (!Modifier.isPublic(clazz.getModifiers())) { |
| 165 | throw new ClassNotFoundException( |
| 166 | Util.message(context, "elProcessor.defineFunctionInvalidClass", className)); |
| 167 | } |
| 168 | |
| 169 | MethodSignature sig = new MethodSignature(context, methodName, className); |
| 170 | |
| 171 | if (function.isEmpty()) { |
| 172 | function = sig.getName(); |
| 173 | } |
| 174 | |
| 175 | // Only returns public methods. Module access is checked below. |
| 176 | Method[] methods = clazz.getMethods(); |
| 177 | |
| 178 | for (Method method : methods) { |
| 179 | if (!Modifier.isStatic(method.getModifiers())) { |
| 180 | continue; |
| 181 | } |
| 182 | if (!Util.canAccess(null, method)) { |
| 183 | continue; |
| 184 | } |
| 185 | if (method.getName().equals(sig.getName())) { |
| 186 | if (sig.getParamTypeNames() == null) { |
| 187 | // Only a name provided, no signature so map the first |
| 188 | // method declared |
| 189 | manager.mapFunction(prefix, function, method); |
| 190 | return; |
| 191 | } |
| 192 | if (sig.getParamTypeNames().length != method.getParameterTypes().length) { |
| 193 | continue; |
| 194 | } |
| 195 | if (sig.getParamTypeNames().length == 0) { |
| 196 | manager.mapFunction(prefix, function, method); |
| 197 | return; |
| 198 | } else { |
| 199 | Class<?>[] types = method.getParameterTypes(); |
| 200 | String[] typeNames = sig.getParamTypeNames(); |
| 201 | boolean match = true; |
| 202 | for (int i = 0; i < types.length; i++) { |
| 203 | if (i == types.length - 1 && method.isVarArgs()) { |
| 204 | String typeName = typeNames[i]; |
| 205 | if (typeName.endsWith("...")) { |
| 206 | typeName = typeName.substring(0, typeName.length() - 3); |
| 207 | if (!typeName.equals(types[i].getName())) { |