Coverage Report - org.apache.camel.spring.util.BeanInfo
 
Classes in this File Line Coverage Branch Coverage Complexity
BeanInfo
46% 
35% 
0
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.camel.spring.util;
 18  
 
 19  
 import org.aopalliance.intercept.MethodInvocation;
 20  
 import org.apache.camel.Body;
 21  
 import org.apache.camel.Exchange;
 22  
 import org.apache.camel.Expression;
 23  
 import org.apache.camel.Header;
 24  
 import org.apache.camel.Property;
 25  
 import org.apache.camel.RuntimeCamelException;
 26  
 import org.apache.camel.builder.ExpressionBuilder;
 27  
 import org.apache.commons.logging.Log;
 28  
 import org.apache.commons.logging.LogFactory;
 29  
 
 30  
 import java.lang.annotation.Annotation;
 31  
 import java.lang.reflect.Method;
 32  
 import java.util.Arrays;
 33  
 import java.util.Collection;
 34  
 import java.util.Map;
 35  
 import java.util.concurrent.ConcurrentHashMap;
 36  
 
 37  
 /**
 38  
  * Represents the metadata about a bean type created via a combination of
 39  
  * introspection and annotations together with some useful sensible defaults
 40  
  *
 41  
  * @version $Revision: $
 42  
  */
 43  
 public class BeanInfo {
 44  1
     private static final transient Log log = LogFactory.getLog(BeanInfo.class);
 45  
 
 46  
     private Class type;
 47  
     private MethodInvocationStrategy strategy;
 48  1
     private Map<String, MethodInfo> operations = new ConcurrentHashMap<String, MethodInfo>();
 49  
     private MethodInfo defaultExpression;
 50  
 
 51  1
     public BeanInfo(Class type, MethodInvocationStrategy strategy) {
 52  1
         this.type = type;
 53  1
         this.strategy = strategy;
 54  1
     }
 55  
 
 56  
     public Class getType() {
 57  0
         return type;
 58  
     }
 59  
 
 60  
     public void introspect() {
 61  0
         introspect(getType());
 62  0
         if (operations.size() == 1) {
 63  0
             Collection<MethodInfo> methodInfos = operations.values();
 64  0
             for (MethodInfo methodInfo : methodInfos) {
 65  0
                 defaultExpression = methodInfo;
 66  0
             }
 67  
         }
 68  0
     }
 69  
 
 70  
     public MethodInvocation createInvocation(Method method, Object pojo, Exchange messageExchange) throws RuntimeCamelException {
 71  1
         MethodInfo methodInfo = introspect(type, method);
 72  1
         return methodInfo.createMethodInvocation(pojo, messageExchange);
 73  
     }
 74  
 
 75  
     public MethodInvocation createInvocation(Object pojo, Exchange messageExchange) throws RuntimeCamelException {
 76  0
         MethodInfo methodInfo = null;
 77  
 
 78  
         // TODO use some other mechanism?
 79  0
         String name = messageExchange.getIn().getHeader("org.apache.camel.MethodName", String.class);
 80  0
         if (name != null) {
 81  0
             methodInfo = operations.get(name);
 82  
         }
 83  0
         if (methodInfo == null) {
 84  0
             methodInfo = defaultExpression;
 85  
         }
 86  0
         if (methodInfo != null) {
 87  0
             return methodInfo.createMethodInvocation(pojo, messageExchange);
 88  
         }
 89  0
         return null;
 90  
     }
 91  
 
 92  
     protected void introspect(Class clazz) {
 93  0
         Method[] methods = clazz.getDeclaredMethods();
 94  0
         for (Method method : methods) {
 95  0
             introspect(clazz, method);
 96  
         }
 97  0
         Class superclass = clazz.getSuperclass();
 98  0
         if (superclass != null && !superclass.equals(Object.class)) {
 99  0
             introspect(superclass);
 100  
         }
 101  0
     }
 102  
 
 103  
     protected MethodInfo introspect(Class clazz, Method method) {
 104  1
         Class[] parameterTypes = method.getParameterTypes();
 105  1
         Annotation[][] parameterAnnotations = method.getParameterAnnotations();
 106  1
         final Expression[] parameterExpressions = new Expression[parameterTypes.length];
 107  2
         for (int i = 0; i < parameterTypes.length; i++) {
 108  1
             Class parameterType = parameterTypes[i];
 109  1
             Expression expression = createParameterUnmarshalExpression(clazz, method,
 110  
                     parameterType, parameterAnnotations[i]);
 111  1
             if (expression == null) {
 112  1
                 if (log.isDebugEnabled()) {
 113  0
                     log.debug("No expression available for method: "
 114  
                             + method.toString() + " parameter: " + i + " so ignoring method");
 115  
                 }
 116  1
                 if (parameterTypes.length == 1) {
 117  
                         // lets assume its the body
 118  1
                         expression = ExpressionBuilder.bodyExpression(parameterType);
 119  1
                 }
 120  
                 else {
 121  0
                         return null;
 122  
                 }
 123  
             }
 124  1
             parameterExpressions[i] = expression;
 125  
         }
 126  
 
 127  
         // now lets add the method to the repository
 128  1
         String opName = method.getName();
 129  
 
 130  
         /*
 131  
 
 132  
         TODO allow an annotation to expose the operation name to use
 133  
 
 134  
         if (method.getAnnotation(Operation.class) != null) {
 135  
             String name = method.getAnnotation(Operation.class).name();
 136  
             if (name != null && name.length() > 0) {
 137  
                 opName = name;
 138  
             }
 139  
         }
 140  
         */
 141  1
         Expression parametersExpression = createMethodParametersExpression(parameterExpressions);
 142  1
         MethodInfo methodInfo = new MethodInfo(clazz, method, parametersExpression);
 143  1
         operations.put(opName, methodInfo);
 144  1
         return methodInfo;
 145  
     }
 146  
 
 147  
     protected Expression createMethodParametersExpression(final Expression[] parameterExpressions) {
 148  1
         return new Expression<Exchange>() {
 149  
             public Object evaluate(Exchange exchange) {
 150  1
                 Object[] answer = new Object[parameterExpressions.length];
 151  2
                 for (int i = 0; i < parameterExpressions.length; i++) {
 152  1
                     Expression parameterExpression = parameterExpressions[i];
 153  1
                     answer[i] = parameterExpression.evaluate(exchange);
 154  
                 }
 155  1
                 return answer;
 156  
             }
 157  
 
 158  
             @Override
 159  1
             public String toString() {
 160  0
                 return "parametersExpression" + Arrays.asList(parameterExpressions);
 161  
             }
 162  
         };
 163  
     }
 164  
 
 165  
     /**
 166  
      * Creates an expression for the given parameter type if the parameter can be mapped
 167  
      * automatically or null if the parameter cannot be mapped due to unsufficient
 168  
      * annotations or not fitting with the default type conventions.
 169  
      */
 170  
     protected Expression createParameterUnmarshalExpression(Class clazz, Method method, Class parameterType, Annotation[] parameterAnnotation) {
 171  
 
 172  
         // TODO look for a parameter annotation that converts into an expression
 173  1
         for (Annotation annotation : parameterAnnotation) {
 174  0
             Expression answer = createParameterUnmarshalExpressionForAnnotation(
 175  
                     clazz, method, parameterType, annotation);
 176  0
             if (answer != null) {
 177  0
                 return answer;
 178  
             }
 179  
         }
 180  1
         return strategy.getDefaultParameterTypeExpression(parameterType);
 181  
     }
 182  
 
 183  
     protected Expression createParameterUnmarshalExpressionForAnnotation(Class clazz, Method method, Class parameterType, Annotation annotation) {
 184  0
         if (annotation instanceof Property) {
 185  0
             Property propertyAnnotation = (Property) annotation;
 186  0
             return ExpressionBuilder.propertyExpression(propertyAnnotation.name());
 187  
         }
 188  0
         else if (annotation instanceof Header) {
 189  0
             Header headerAnnotation = (Header) annotation;
 190  0
             return ExpressionBuilder.headerExpression(headerAnnotation.name());
 191  
         }
 192  0
         else if (annotation instanceof Body) {
 193  0
             Body content = (Body) annotation;
 194  0
             return ExpressionBuilder.bodyExpression(parameterType);
 195  
 
 196  
             // TODO allow annotations to be used to create expressions?
 197  
 /*
 198  
         } else if (annotation instanceof XPath) {
 199  
             XPath xpathAnnotation = (XPath) annotation;
 200  
             return new JAXPStringXPathExpression(xpathAnnotation.xpath());
 201  
         }
 202  
 */
 203  
         }
 204  0
         return null;
 205  
     }
 206  
 }