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: 672723 $
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        public boolean bodyParameterMatches(Class bodyType) {
103            Class actualType = getBodyParameterType();
104            return actualType != null && ObjectHelper.isAssignableFrom(bodyType, actualType);
105        }
106    
107        public List<ParameterInfo> getParameters() {
108            return parameters;
109        }
110    
111        public boolean hasBodyParameter() {
112            return !bodyParameters.isEmpty();
113        }
114    
115        public boolean isHasCustomAnnotation() {
116            return hasCustomAnnotation;
117        }
118    
119        public boolean isReturnTypeVoid() {
120            return method.getReturnType().getName().equals("void");
121        }
122    
123        protected Object invoke(Method mth, Object pojo, Object[] arguments, Exchange exchange) throws IllegalAccessException, InvocationTargetException {
124            return mth.invoke(pojo, arguments);
125        }
126    
127        protected Expression createParametersExpression() {
128            final int size = parameters.size();
129            final Expression[] expressions = new Expression[size];
130            for (int i = 0; i < size; i++) {
131                Expression parameterExpression = parameters.get(i).getExpression();
132                expressions[i] = parameterExpression;
133            }
134            return new Expression<Exchange>() {
135                public Object evaluate(Exchange exchange) {
136                    Object[] answer = new Object[size];
137                    for (int i = 0; i < size; i++) {
138                        Object value = expressions[i].evaluate(exchange);
139                        // now lets try to coerce the value to the required type
140                        Class expectedType = parameters.get(i).getType();
141                        value = ExchangeHelper.convertToType(exchange, expectedType, value);
142                        answer[i] = value;
143                    }
144                    return answer;
145                }
146    
147                @Override
148                public String toString() {
149                    return "ParametersExpression: " + Arrays.asList(expressions);
150                }
151            };
152        }
153    }