EMMA Coverage Report (generated Thu Jan 24 13:37:04 CST 2013)
[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-2007 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        public void afterPropertiesSet() throws Exception {
133                Assert.notNull(targetObject);
134                Assert.hasLength(targetMethod);
135                Assert.state(targetClassDeclaresTargetMethod(),
136                                "target class must declare a method with matching name and parameter types");
137        }
138 
139        /**
140         * @return true if target class declares a method matching target method
141         * name with given number of arguments of appropriate type.
142         */
143        private boolean targetClassDeclaresTargetMethod() {
144                MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod);
145 
146                Method[] memberMethods = invoker.getTargetClass().getMethods();
147                Method[] declaredMethods = invoker.getTargetClass().getDeclaredMethods();
148 
149                List<Method> allMethods = new ArrayList<Method>();
150                allMethods.addAll(Arrays.asList(memberMethods));
151                allMethods.addAll(Arrays.asList(declaredMethods));
152 
153                String targetMethodName = invoker.getTargetMethod();
154 
155                for (Method method : allMethods) {
156                        if (method.getName().equals(targetMethodName)) {
157                                Class<?>[] params = method.getParameterTypes();
158                                if (arguments == null) {
159                                        // don't check signature, assume arguments will be supplied
160                                        // correctly at runtime
161                                        return true;
162                                }
163                                if (arguments.length == params.length) {
164                                        boolean argumentsMatchParameters = true;
165                                        for (int j = 0; j < params.length; j++) {
166                                                if (arguments[j] == null) {
167                                                        continue;
168                                                }
169                                                if (!(params[j].isAssignableFrom(arguments[j].getClass()))) {
170                                                        argumentsMatchParameters = false;
171                                                }
172                                        }
173                                        if (argumentsMatchParameters)
174                                                return true;
175                                }
176                        }
177                }
178 
179                return false;
180        }
181 
182        /**
183         * @param targetObject the delegate - bean id can be used to set this value
184         * in Spring configuration
185         */
186        public void setTargetObject(Object targetObject) {
187                this.targetObject = targetObject;
188        }
189 
190        /**
191         * @param targetMethod name of the method to be invoked on
192         * {@link #setTargetObject(Object)}.
193         */
194        public void setTargetMethod(String targetMethod) {
195                this.targetMethod = targetMethod;
196        }
197 
198        /**
199         * @param arguments arguments values for the {
200         * {@link #setTargetMethod(String)}. These will be used only when the
201         * subclass tries to invoke the target method without providing explicit
202         * argument values.
203         * 
204         * If arguments are set to not-null value {@link #afterPropertiesSet()} will
205         * check the values are compatible with target method's signature. In case
206         * arguments are null (not set) method signature will not be checked and it
207         * is assumed correct values will be supplied at runtime.
208         */
209        public void setArguments(Object[] arguments) {
210                this.arguments = arguments == null ? null : Arrays.asList(arguments).toArray();
211        }
212 
213        /**
214         * Used to wrap a {@link Throwable} (not an {@link Exception}) thrown by a
215         * reflectively-invoked delegate.
216         * 
217         * @author Robert Kasanicky
218         */
219        public static class InvocationTargetThrowableWrapper extends RuntimeException {
220 
221                public InvocationTargetThrowableWrapper(Throwable cause) {
222                        super(cause);
223                }
224 
225        }
226}

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