  				public void remove() {
  					throw new UnsupportedOperationException("cannot remove");
  				}
-@@ -397,6 +403,169 @@
+@@ -397,6 +403,179 @@
  	}
  
  	/**

+				throw new MethodNotFoundException(e);
+			}
+		}
+		Method[] methods = base.getClass().getMethods();
+		for (Method method : methods) {
+			if (method.getName().equals(name)) {
+				if (paramCount == method.getParameterTypes().length) {
+					return method;
+				}
+			}
+		}
+		for (Method method : methods) {
+			if (method.isVarArgs()) {
+				if (paramCount >= method.getParameterTypes().length - 1) {
+					return method;
+				}
+			}
+		}
+		throw new MethodNotFoundException("Cannot find matching method " + name + " on class " + base);
+	}
+
+	private Object[] coerceParams(ELContext context, Method method, Object[] params) {
+		Class<?>[] types = method.getParameterTypes();
+		Object[] args = new Object[types.length];
+		if (method.isVarArgs()) {
+			int varargIndex = types.length - 1;
+			if (params.length < varargIndex) {
+				throw new ELException("bad argument count");
+			}
+			for (int i = 0; i < varargIndex; i++) {
+				coerceValue(args[i], i, params[i], types[i]);
+			}
+			Class<?> varargType = types[varargIndex].getComponentType();
+			int length = params.length - varargIndex;
+			Object array = null;
+			if (length == 1) {
+				Object source = params[varargIndex];
+				if (source == null) { // create empty array
+					array = Array.newInstance(varargType, 0);
+				} else if (source.getClass().isArray()) {
+					if (types[varargIndex].isInstance(source)) { // use source array as is
+						array = source;
+					} else { // coerce array elements
+						length = Array.getLength(source);
+						array = Array.newInstance(varargType, length);
+						for (int i = 0; i < length; i++) {
+							coerceValue(array, i, Array.get(source, i), varargType);
+						}
+					}
+				} else { // single element array
+					array = Array.newInstance(varargType, 1);
+					coerceValue(array, 0, source, varargType);
+				}
+			} else {
+				array = Array.newInstance(varargType, length);
+				for (int i = 0; i < length; i++) {
+					coerceValue(array, i, params[varargIndex + i], varargType);
+				}
+			}
+			args[varargIndex] = array;
+		} else {
+			if (params.length != args.length) {
+				throw new ELException("bad argument count");
+			}
+			for (int i = 0; i < args.length; i++) {
+				coerceValue(args, i, params[i], types[i]);
+			}
+		}
+		return args;
+	}
+
+	private void coerceValue(Object array, int index, Object value, Class<?> type) {
+		if (value != null || type.isPrimitive()) {
+			Array.set(array, index, factory.coerceToType(value, type));
+		}

+			String name = method.toString();
+			Method target = findMethod(base, name, paramTypes, params.length);
+			try {
+				result = target.invoke(base, coerceParams(getExpressionFactory(context), target, params));
+			} catch (InvocationTargetException e) {
+				throw new ELException(e.getCause());
+			} catch (IllegalAccessException e) {
