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 */
017 package org.apache.camel.language.juel;
018
019 import java.lang.reflect.Method;
020 import java.lang.reflect.Modifier;
021 import java.util.ArrayList;
022 import java.util.List;
023
024 import javax.el.BeanELResolver;
025 import javax.el.ELContext;
026 import javax.el.PropertyNotFoundException;
027
028 /**
029 * An extension of the JUEL {@link BeanELResolver} which also supports the resolving of methods
030 *
031 * @version
032 */
033 public class BeanAndMethodELResolver extends BeanELResolver {
034 public BeanAndMethodELResolver() {
035 super(false);
036 }
037
038 @Override
039 public Object getValue(ELContext elContext, Object base, Object property) {
040 try {
041 return (property instanceof Method) ? property : super.getValue(elContext, base, property);
042 } catch (PropertyNotFoundException e) {
043 // lets see if its a method call...
044 Method method = findMethod(elContext, base, property);
045 if (method != null) {
046 elContext.setPropertyResolved(true);
047 return method;
048 } else {
049 throw e;
050 }
051 }
052 }
053
054 protected Method findMethod(ELContext elContext, Object base, Object property) {
055 if (base != null) {
056 Method[] methods = base.getClass().getMethods();
057 List<Method> matching = new ArrayList<Method>();
058 for (Method method : methods) {
059 if (method.getName().equals(property.toString()) && Modifier.isPublic(method.getModifiers())) {
060 matching.add(method);
061 }
062 }
063 int size = matching.size();
064 if (size > 0) {
065 if (size > 1) {
066 // TODO there's currently no way for JUEL to tell us how many parameters there are
067 // so lets just pick the first one that has a single param by default
068 for (Method method : matching) {
069 Class<?>[] paramTypes = method.getParameterTypes();
070 if (paramTypes.length == 1) {
071 return method;
072 }
073 }
074 }
075 // lets default to the first one
076 return matching.get(0);
077 }
078 }
079 return null;
080 }
081 }