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.component.bean;
018    
019    import java.lang.reflect.AccessibleObject;
020    import java.lang.reflect.InvocationTargetException;
021    import java.lang.reflect.Method;
022    import java.util.Arrays;
023    import java.util.List;
024    
025    import org.apache.camel.Exchange;
026    import org.apache.camel.Expression;
027    import org.apache.camel.util.ExchangeHelper;
028    import org.apache.camel.util.ObjectHelper;
029    
030    /**
031     * Information about a method to be used for invocation.
032     *
033     * @version $Revision: 41830 $
034     */
035    public class MethodInfo {
036        private Class type;
037        private Method method;
038        private final List<ParameterInfo> parameters;
039        private final List<ParameterInfo> bodyParameters;
040        private final boolean hasCustomAnnotation;
041        private Expression parametersExpression;
042    
043        public MethodInfo(Class type, Method method, List<ParameterInfo> parameters, List<ParameterInfo> bodyParameters, boolean hasCustomAnnotation) {
044            this.type = type;
045            this.method = method;
046            this.parameters = parameters;
047            this.bodyParameters = bodyParameters;
048            this.hasCustomAnnotation = hasCustomAnnotation;
049            this.parametersExpression = createParametersExpression();
050        }
051    
052        public String toString() {
053            return method.toString();
054        }
055    
056        public MethodInvocation createMethodInvocation(final Object pojo, final Exchange messageExchange) {
057            final Object[] arguments = (Object[]) parametersExpression.evaluate(messageExchange);
058            return new MethodInvocation() {
059                public Method getMethod() {
060                    return method;
061                }
062    
063                public Object[] getArguments() {
064                    return arguments;
065                }
066    
067                public Object proceed() throws Throwable {
068                    return invoke(method, pojo, arguments, messageExchange);
069                }
070    
071                public Object getThis() {
072                    return pojo;
073                }
074    
075                public AccessibleObject getStaticPart() {
076                    return method;
077                }
078            };
079        }
080    
081        public Class getType() {
082            return type;
083        }
084    
085        public Method getMethod() {
086            return method;
087        }
088    
089        public Expression getParametersExpression() {
090            return parametersExpression;
091        }
092    
093        public List<ParameterInfo> getBodyParameters() {
094            return bodyParameters;
095        }
096    
097        public Class getBodyParameterType() {
098            ParameterInfo parameterInfo = bodyParameters.get(0);
099            return parameterInfo.getType();
100        }
101    
102    
103        public boolean bodyParameterMatches(Class bodyType) {
104            Class actualType = getBodyParameterType();
105            return actualType != null && ObjectHelper.isAssignableFrom(bodyType, actualType);
106        }
107    
108        public List<ParameterInfo> getParameters() {
109            return parameters;
110        }
111    
112        public boolean hasBodyParameter() {
113            return !bodyParameters.isEmpty();
114        }
115    
116        public boolean isHasCustomAnnotation() {
117            return hasCustomAnnotation;
118        }
119    
120        protected Object invoke(Method mth, Object pojo, Object[] arguments, Exchange exchange) throws IllegalAccessException, InvocationTargetException {
121            return mth.invoke(pojo, arguments);
122        }
123    
124        protected Expression createParametersExpression() {
125            final int size = parameters.size();
126            final Expression[] expressions = new Expression[size];
127            for (int i = 0; i < size; i++) {
128                Expression parameterExpression = parameters.get(i).getExpression();
129                expressions[i] = parameterExpression;
130            }
131            return new Expression<Exchange>() {
132                public Object evaluate(Exchange exchange) {
133                    Object[] answer = new Object[size];
134                    for (int i = 0; i < size; i++) {
135                        Object value = expressions[i].evaluate(exchange);
136                        // now lets try to coerce the value to the required type
137                        Class expectedType = parameters.get(i).getType();
138                        value = ExchangeHelper.convertToType(exchange, expectedType, value);
139                        answer[i] = value;
140                    }
141                    return answer;
142                }
143    
144                @Override
145                public String toString() {
146                    return "ParametersExpression: " + Arrays.asList(expressions);
147                }
148            };
149        }
150    }