KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > binding > method > MethodInvoker


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.springframework.binding.method;
17
18 import java.lang.reflect.Method JavaDoc;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.springframework.binding.convert.ConversionService;
23 import org.springframework.binding.convert.support.DefaultConversionService;
24 import org.springframework.core.style.StylerUtils;
25 import org.springframework.util.CachingMapDecorator;
26
27 /**
28  * A helper for invoking typed methods on abritrary objects, with support for
29  * argument value type conversion from values retrieved from a argument
30  * attribute source.
31  *
32  * @author Keith Donald
33  */

34 public class MethodInvoker {
35
36     protected static final Log logger = LogFactory.getLog(MethodInvoker.class);
37
38     /**
39      * Conversion service for converting arguments to the neccessary type if
40      * required.
41      */

42     private ConversionService conversionService = new DefaultConversionService();
43
44     /**
45      * A cache of invoked bean methods, keyed weakly.
46      */

47     private CachingMapDecorator methodCache = new CachingMapDecorator(true) {
48         public Object JavaDoc create(Object JavaDoc key) {
49             return ((ClassMethodKey)key).getMethod();
50         }
51     };
52
53     /**
54      * Sets the conversion service to convert argument values as needed.
55      */

56     public void setConversionService(ConversionService conversionService) {
57         this.conversionService = conversionService;
58     }
59
60     /**
61      * Invoke the method on the bean provided. Argument values are pulled from
62      * the provided argument source.
63      *
64      * @param signature the definition of the method to invoke, including the
65      * method name and the method argument types
66      * @param bean the bean to invoke
67      * @param argumentSource the source for method arguments
68      * @return the invoked method's return value
69      * @throws MethodInvocationException the method could not be invoked
70      */

71     public Object JavaDoc invoke(MethodSignature signature, Object JavaDoc bean, Object JavaDoc argumentSource)
72             throws MethodInvocationException {
73         Parameters parameters = signature.getParameters();
74         Object JavaDoc[] arguments = new Object JavaDoc[parameters.size()];
75         for (int i = 0; i < parameters.size(); i++) {
76             Parameter parameter = parameters.getParameter(i);
77             Object JavaDoc argument = parameter.getName().evaluate(argumentSource, null);
78             arguments[i] = applyTypeConversion(argument, parameter.getType());
79         }
80         Class JavaDoc[] parameterTypes = parameters.getTypesArray();
81         for (int i = 0; i < parameterTypes.length; i++) {
82             if (parameterTypes[i] == null) {
83                 Object JavaDoc argument = arguments[i];
84                 if (argument != null) {
85                     parameterTypes[i] = argument.getClass();
86                 }
87             }
88         }
89         ClassMethodKey key = new ClassMethodKey(bean.getClass(), signature.getMethodName(), parameterTypes);
90         try {
91             Method JavaDoc method = (Method JavaDoc)methodCache.get(key);
92             if (logger.isDebugEnabled()) {
93                 logger.debug("Invoking method with signature [" + key + "] with arguments "
94                         + StylerUtils.style(arguments) + " on bean [" + bean + "]");
95
96             }
97             Object JavaDoc returnValue = method.invoke(bean, arguments);
98             if (logger.isDebugEnabled()) {
99                 logger.debug("Invoked method with signature [" + key + "]' returned value [" + returnValue + "]");
100             }
101             return returnValue;
102         }
103         catch (Exception JavaDoc e) {
104             throw new MethodInvocationException(key, arguments, e);
105         }
106     }
107
108     /**
109      * Apply type conversion on the event parameter if neccessary
110      *
111      * @param parameterValue the raw argument value
112      * @param targetType the target type for the matching method argument
113      * @return the converted method argument
114      */

115     protected Object JavaDoc applyTypeConversion(Object JavaDoc parameterValue, Class JavaDoc targetType) {
116         if (parameterValue == null || targetType == null) {
117             return parameterValue;
118         }
119         return conversionService.getConversionExecutor(parameterValue.getClass(), targetType).execute(parameterValue);
120     }
121 }
Popular Tags