EMMA Coverage Report (generated Thu May 22 12:08:10 CDT 2014)
[all classes][org.springframework.batch.item.adapter]

COVERAGE SUMMARY FOR SOURCE FILE [AbstractMethodInvokingDelegator.java]

nameclass, %method, %block, %line, %
AbstractMethodInvokingDelegator.java50%  (1/2)83%  (10/12)63%  (148/235)62%  (40/64)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AbstractMethodInvokingDelegator$InvocationTargetThrowableWrapper0%   (0/1)0%   (0/1)0%   (0/4)0%   (0/2)
AbstractMethodInvokingDelegator$InvocationTargetThrowableWrapper (Throwable):... 0%   (0/1)0%   (0/4)0%   (0/2)
     
class AbstractMethodInvokingDelegator100% (1/1)91%  (10/11)64%  (148/231)65%  (40/62)
setArguments (Object []): void 0%   (0/1)0%   (0/10)0%   (0/2)
doInvoke (MethodInvoker): Object 100% (1/1)15%  (6/39)23%  (3/13)
targetClassDeclaresTargetMethod (): boolean 100% (1/1)58%  (56/96)57%  (13/23)
AbstractMethodInvokingDelegator (): void 100% (1/1)100% (3/3)100% (2/2)
afterPropertiesSet (): void 100% (1/1)100% (11/11)100% (4/4)
createMethodInvoker (Object, String): MethodInvoker 100% (1/1)100% (16/16)100% (5/5)
invokeDelegateMethod (): Object 100% (1/1)100% (15/15)100% (3/3)
invokeDelegateMethodWithArgument (Object): Object 100% (1/1)100% (19/19)100% (3/3)
invokeDelegateMethodWithArguments (Object []): Object 100% (1/1)100% (14/14)100% (3/3)
setTargetMethod (String): void 100% (1/1)100% (4/4)100% (2/2)
setTargetObject (Object): void 100% (1/1)100% (4/4)100% (2/2)

1/*
2 * Copyright 2006-2013 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 
17package org.springframework.batch.item.adapter;
18 
19import java.lang.reflect.InvocationTargetException;
20import java.lang.reflect.Method;
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.List;
24 
25import org.springframework.beans.factory.InitializingBean;
26import org.springframework.util.Assert;
27import org.springframework.util.MethodInvoker;
28 
29/**
30 * Superclass for delegating classes which dynamically call a custom method of
31 * injected object. Provides convenient API for dynamic method invocation
32 * shielding subclasses from low-level details and exception handling.
33 *
34 * {@link Exception}s thrown by a successfully invoked delegate method are
35 * re-thrown without wrapping. In case the delegate method throws a
36 * {@link Throwable} that doesn't subclass {@link Exception} it will be wrapped
37 * by {@link InvocationTargetThrowableWrapper}.
38 *
39 * @author Robert Kasanicky
40 */
41public abstract class AbstractMethodInvokingDelegator<T> implements InitializingBean {
42 
43        private Object targetObject;
44 
45        private String targetMethod;
46 
47        private Object[] arguments;
48 
49        /**
50         * Invoker the target method with arguments set by
51         * {@link #setArguments(Object[])}.
52         * @return object returned by invoked method
53         * @throws DynamicMethodInvocationException if the {@link MethodInvoker}
54         * used throws exception
55         */
56        protected T invokeDelegateMethod() throws Exception {
57                MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
58                invoker.setArguments(arguments);
59                return doInvoke(invoker);
60        }
61 
62        /**
63         * Invokes the target method with given argument.
64         * @param object argument for the target method
65         * @return object returned by target method
66         * @throws DynamicMethodInvocationException if the {@link MethodInvoker}
67         * used throws exception
68         */
69        protected T invokeDelegateMethodWithArgument(Object object) throws Exception {
70                MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
71                invoker.setArguments(new Object[] { object });
72                return doInvoke(invoker);
73        }
74 
75        /**
76         * Invokes the target method with given arguments.
77         * @param args arguments for the invoked method
78         * @return object returned by invoked method
79         * @throws DynamicMethodInvocationException if the {@link MethodInvoker}
80         * used throws exception
81         */
82        protected T invokeDelegateMethodWithArguments(Object[] args) throws Exception {
83                MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
84                invoker.setArguments(args);
85                return doInvoke(invoker);
86        }
87 
88        /**
89         * Create a new configured instance of {@link MethodInvoker}.
90         */
91        private MethodInvoker createMethodInvoker(Object targetObject, String targetMethod) {
92                HippyMethodInvoker invoker = new HippyMethodInvoker();
93                invoker.setTargetObject(targetObject);
94                invoker.setTargetMethod(targetMethod);
95                invoker.setArguments(arguments);
96                return invoker;
97        }
98 
99        /**
100         * Prepare and invoke the invoker, rethrow checked exceptions as unchecked.
101         * @param invoker configured invoker
102         * @return return value of the invoked method
103         */
104        @SuppressWarnings("unchecked")
105        private T doInvoke(MethodInvoker invoker) throws Exception {
106                try {
107                        invoker.prepare();
108                }
109                catch (ClassNotFoundException e) {
110                        throw new DynamicMethodInvocationException(e);
111                }
112                catch (NoSuchMethodException e) {
113                        throw new DynamicMethodInvocationException(e);
114                }
115 
116                try {
117                        return (T) invoker.invoke();
118                }
119                catch (InvocationTargetException e) {
120                        if (e.getCause() instanceof Exception) {
121                                throw (Exception) e.getCause();
122                        }
123                        else {
124                                throw new InvocationTargetThrowableWrapper(e.getCause());
125                        }
126                }
127                catch (IllegalAccessException e) {
128                        throw new DynamicMethodInvocationException(e);
129                }
130        }
131 
132        @Override
133        public void afterPropertiesSet() throws Exception {
134                Assert.notNull(targetObject);
135                Assert.hasLength(targetMethod);
136                Assert.state(targetClassDeclaresTargetMethod(),
137                                "target class must declare a method with matching name and parameter types");
138        }
139 
140        /**
141         * @return true if target class declares a method matching target method
142         * name with given number of arguments of appropriate type.
143         */
144        private boolean targetClassDeclaresTargetMethod() {
145                MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
146 
147                Method[] memberMethods = invoker.getTargetClass().getMethods();
148                Method[] declaredMethods = invoker.getTargetClass().getDeclaredMethods();
149 
150                List<Method> allMethods = new ArrayList<Method>();
151                allMethods.addAll(Arrays.asList(memberMethods));
152                allMethods.addAll(Arrays.asList(declaredMethods));
153 
154                String targetMethodName = invoker.getTargetMethod();
155 
156                for (Method method : allMethods) {
157                        if (method.getName().equals(targetMethodName)) {
158                                Class<?>[] params = method.getParameterTypes();
159                                if (arguments == null) {
160                                        // don't check signature, assume arguments will be supplied
161                                        // correctly at runtime
162                                        return true;
163                                }
164                                if (arguments.length == params.length) {
165                                        boolean argumentsMatchParameters = true;
166                                        for (int j = 0; j < params.length; j++) {
167                                                if (arguments[j] == null) {
168                                                        continue;
169                                                }
170                                                if (!(params[j].isAssignableFrom(arguments[j].getClass()))) {
171                                                        argumentsMatchParameters = false;
172                                                }
173                                        }
174                                        if (argumentsMatchParameters) {
175                                                return true;
176                                        }
177                                }
178                        }
179                }
180 
181                return false;
182        }
183 
184        /**
185         * @param targetObject the delegate - bean id can be used to set this value
186         * in Spring configuration
187         */
188        public void setTargetObject(Object targetObject) {
189                this.targetObject = targetObject;
190        }
191 
192        /**
193         * @param targetMethod name of the method to be invoked on
194         * {@link #setTargetObject(Object)}.
195         */
196        public void setTargetMethod(String targetMethod) {
197                this.targetMethod = targetMethod;
198        }
199 
200        /**
201         * @param arguments arguments values for the {
202         * {@link #setTargetMethod(String)}. These will be used only when the
203         * subclass tries to invoke the target method without providing explicit
204         * argument values.
205         *
206         * If arguments are set to not-null value {@link #afterPropertiesSet()} will
207         * check the values are compatible with target method's signature. In case
208         * arguments are null (not set) method signature will not be checked and it
209         * is assumed correct values will be supplied at runtime.
210         */
211        public void setArguments(Object[] arguments) {
212                this.arguments = arguments == null ? null : Arrays.asList(arguments).toArray();
213        }
214 
215        /**
216         * Used to wrap a {@link Throwable} (not an {@link Exception}) thrown by a
217         * reflectively-invoked delegate.
218         *
219         * @author Robert Kasanicky
220         */
221        public static class InvocationTargetThrowableWrapper extends RuntimeException {
222 
223                public InvocationTargetThrowableWrapper(Throwable cause) {
224                        super(cause);
225                }
226 
227        }
228}

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