EMMA Coverage Report (generated Thu Jan 24 13:37:04 CST 2013)
[all classes][org.springframework.batch.support]

COVERAGE SUMMARY FOR SOURCE FILE [MethodInvokerUtils.java]

nameclass, %method, %block, %line, %
MethodInvokerUtils.java75%  (3/4)46%  (6/13)42%  (165/391)45%  (26.9/60)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MethodInvokerUtils$10%   (0/1)0%   (0/2)0%   (0/85)0%   (0/10)
MethodInvokerUtils$1 (Class, Class, Class []): void 0%   (0/1)0%   (0/12)0%   (0/1)
doWith (Method): void 0%   (0/1)0%   (0/73)0%   (0/9)
     
class MethodInvokerUtils100% (1/1)29%  (2/7)36%  (81/222)38%  (14.9/39)
MethodInvokerUtils (): void 0%   (0/1)0%   (0/3)0%   (0/1)
getMethodInvokerByAnnotation (Class, Object, Class []): MethodInvoker 0%   (0/1)0%   (0/27)0%   (0/5)
getMethodInvokerByName (Object, String, boolean, Class []): MethodInvoker 0%   (0/1)0%   (0/56)0%   (0/8)
getMethodInvokerForInterface (Class, String, Object, Class []): MethodInvoker 0%   (0/1)0%   (0/13)0%   (0/3)
getParamTypesString (Class []): String 0%   (0/1)0%   (0/35)0%   (0/6)
getMethodInvokerByAnnotation (Class, Object): MethodInvoker 100% (1/1)90%  (60/67)90%  (10.9/12)
getMethodInvokerForSingleArgument (Object): MethodInvoker 100% (1/1)100% (21/21)100% (4/4)
     
class MethodInvokerUtils$2100% (1/1)100% (2/2)100% (46/46)100% (6/6)
MethodInvokerUtils$2 (Class, AtomicReference, Class): void 100% (1/1)100% (12/12)100% (1/1)
doWith (Method): void 100% (1/1)100% (34/34)100% (5/5)
     
class MethodInvokerUtils$3100% (1/1)100% (2/2)100% (38/38)100% (8/8)
MethodInvokerUtils$3 (AtomicReference): void 100% (1/1)100% (6/6)100% (1/1)
doWith (Method): void 100% (1/1)100% (32/32)100% (7/7)

1/*
2 * Copyright 2002-2008 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 */
16package org.springframework.batch.support;
17 
18import java.lang.annotation.Annotation;
19import java.lang.annotation.ElementType;
20import java.lang.annotation.Target;
21import java.lang.reflect.Method;
22import java.util.concurrent.atomic.AtomicReference;
23 
24import org.springframework.aop.framework.Advised;
25import org.springframework.core.annotation.AnnotationUtils;
26import org.springframework.util.Assert;
27import org.springframework.util.ClassUtils;
28import org.springframework.util.ObjectUtils;
29import org.springframework.util.ReflectionUtils;
30 
31/**
32 * Utility methods for create MethodInvoker instances.
33 * 
34 * @author Lucas Ward
35 * @since 2.0
36 */
37public class MethodInvokerUtils {
38 
39        /**
40         * Create a {@link MethodInvoker} using the provided method name to search.
41         * 
42         * @param object to be invoked
43         * @param methodName of the method to be invoked
44         * @param paramsRequired boolean indicating whether the parameters are
45         * required, if false, a no args version of the method will be searched for.
46         * @param paramTypes - parameter types of the method to search for.
47         * @return MethodInvoker if the method is found, null if it is not.
48         */
49        public static MethodInvoker getMethodInvokerByName(Object object, String methodName, boolean paramsRequired,
50                        Class<?>... paramTypes) {
51                Assert.notNull(object, "Object to invoke must not be null");
52                Method method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, paramTypes);
53                if (method == null) {
54                        String errorMsg = "no method found with name [" + methodName + "] on class ["
55                                        + object.getClass().getSimpleName() + "] compatable with the signature ["
56                                        + getParamTypesString(paramTypes) + "].";
57                        Assert.isTrue(!paramsRequired, errorMsg);
58                        // if no method was found for the given parameters, and the
59                        // parameters aren't required, then try with no params
60                        method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, new Class[] {});
61                        Assert.notNull(method, errorMsg);
62                }
63                return new SimpleMethodInvoker(object, method);
64        }
65 
66        /**
67         * Create a String representation of the array of parameter types.
68         * 
69         * @param paramTypes
70         * @return String
71         */
72        public static String getParamTypesString(Class<?>... paramTypes) {
73                StringBuffer paramTypesList = new StringBuffer("(");
74                for (int i = 0; i < paramTypes.length; i++) {
75                        paramTypesList.append(paramTypes[i].getSimpleName());
76                        if (i + 1 < paramTypes.length) {
77                                paramTypesList.append(", ");
78                        }
79                }
80                return paramTypesList.append(")").toString();
81        }
82 
83        /**
84         * Create a {@link MethodInvoker} using the provided interface, and method
85         * name from that interface.
86         * 
87         * @param cls the interface to search for the method named
88         * @param methodName of the method to be invoked
89         * @param object to be invoked
90         * @param paramTypes - parameter types of the method to search for.
91         * @return MethodInvoker if the method is found, null if it is not.
92         */
93        public static MethodInvoker getMethodInvokerForInterface(Class<?> cls, String methodName, Object object,
94                        Class<?>... paramTypes) {
95 
96                if (cls.isAssignableFrom(object.getClass())) {
97                        return MethodInvokerUtils.getMethodInvokerByName(object, methodName, true, paramTypes);
98                }
99                else {
100                        return null;
101                }
102        }
103 
104        /**
105         * Create a MethodInvoker from the delegate based on the annotationType.
106         * Ensure that the annotated method has a valid set of parameters.
107         * 
108         * @param annotationType the annotation to scan for
109         * @param target the target object
110         * @param expectedParamTypes the expected parameter types for the method
111         * @return a MethodInvoker
112         */
113        public static MethodInvoker getMethodInvokerByAnnotation(final Class<? extends Annotation> annotationType,
114                        final Object target, final Class<?>... expectedParamTypes) {
115                MethodInvoker mi = MethodInvokerUtils.getMethodInvokerByAnnotation(annotationType, target);
116                final Class<?> targetClass = (target instanceof Advised) ? ((Advised) target).getTargetSource()
117                                .getTargetClass() : target.getClass();
118                if (mi != null) {
119                        ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
120                                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
121                                        Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
122                                        if (annotation != null) {
123                                                Class<?>[] paramTypes = method.getParameterTypes();
124                                                if (paramTypes.length > 0) {
125                                                        String errorMsg = "The method [" + method.getName() + "] on target class ["
126                                                                        + targetClass.getSimpleName() + "] is incompatable with the signature ["
127                                                                        + getParamTypesString(expectedParamTypes) + "] expected for the annotation ["
128                                                                        + annotationType.getSimpleName() + "].";
129 
130                                                        Assert.isTrue(paramTypes.length == expectedParamTypes.length, errorMsg);
131                                                        for (int i = 0; i < paramTypes.length; i++) {
132                                                                Assert.isTrue(expectedParamTypes[i].isAssignableFrom(paramTypes[i]), errorMsg);
133                                                        }
134                                                }
135                                        }
136                                }
137                        });
138                }
139                return mi;
140        }
141 
142        /**
143         * Create {@link MethodInvoker} for the method with the provided annotation
144         * on the provided object. Annotations that cannot be applied to methods
145         * (i.e. that aren't annotated with an element type of METHOD) will cause an
146         * exception to be thrown.
147         * 
148         * @param annotationType to be searched for
149         * @param target to be invoked
150         * @return MethodInvoker for the provided annotation, null if none is found.
151         */
152        public static MethodInvoker getMethodInvokerByAnnotation(final Class<? extends Annotation> annotationType,
153                        final Object target) {
154                Assert.notNull(target, "Target must not be null");
155                Assert.notNull(annotationType, "AnnotationType must not be null");
156                Assert.isTrue(ObjectUtils.containsElement(annotationType.getAnnotation(Target.class).value(),
157                                ElementType.METHOD), "Annotation [" + annotationType + "] is not a Method-level annotation.");
158                final Class<?> targetClass = (target instanceof Advised) ? ((Advised) target).getTargetSource()
159                                .getTargetClass() : target.getClass();
160                if (targetClass == null) {
161                        // Proxy with no target cannot have annotations
162                        return null;
163                }
164                final AtomicReference<Method> annotatedMethod = new AtomicReference<Method>();
165                ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
166                        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
167                                Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
168                                if (annotation != null) {
169                                        Assert.isNull(annotatedMethod.get(), "found more than one method on target class ["
170                                                        + targetClass.getSimpleName() + "] with the annotation type ["
171                                                        + annotationType.getSimpleName() + "].");
172                                        annotatedMethod.set(method);
173                                }
174                        }
175                });
176                Method method = annotatedMethod.get();
177                if (method == null) {
178                        return null;
179                }
180                else {
181                        return new SimpleMethodInvoker(target, annotatedMethod.get());
182                }
183        }
184 
185        /**
186         * Create a {@link MethodInvoker} for the delegate from a single public
187         * method.
188         * 
189         * @param target an object to search for an appropriate method
190         * @return a MethodInvoker that calls a method on the delegate
191         */
192        public static <C, T> MethodInvoker getMethodInvokerForSingleArgument(Object target) {
193                final AtomicReference<Method> methodHolder = new AtomicReference<Method>();
194                ReflectionUtils.doWithMethods(target.getClass(), new ReflectionUtils.MethodCallback() {
195                        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
196                                if (method.getParameterTypes() == null || method.getParameterTypes().length != 1) {
197                                        return;
198                                }
199                                if (method.getReturnType().equals(Void.TYPE) || ReflectionUtils.isEqualsMethod(method)) {
200                                        return;
201                                }
202                                Assert.state(methodHolder.get() == null,
203                                                "More than one non-void public method detected with single argument.");
204                                methodHolder.set(method);
205                        }
206                });
207                Method method = methodHolder.get();
208                return new SimpleMethodInvoker(target, method);
209        }
210}

[all classes][org.springframework.batch.support]
EMMA 2.0.5312 (C) Vladimir Roubtsov