View Javadoc

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   */
16  
17  package org.springframework.batch.support;
18  
19  import java.lang.annotation.Annotation;
20  import java.lang.annotation.ElementType;
21  import java.lang.annotation.Target;
22  import java.lang.reflect.Method;
23  import java.util.concurrent.atomic.AtomicReference;
24  
25  import org.springframework.aop.support.AopUtils;
26  import org.springframework.core.annotation.AnnotationUtils;
27  import org.springframework.util.Assert;
28  import org.springframework.util.ObjectUtils;
29  import org.springframework.util.ReflectionUtils;
30  
31  /**
32   * MethodResolver implementation that finds a <em>single</em> Method on the
33   * given Class that contains the specified annotation type.
34   * 
35   * @author Mark Fisher
36   */
37  public class AnnotationMethodResolver implements MethodResolver {
38  
39  	private Class<? extends Annotation> annotationType;
40  
41  
42  	/**
43  	 * Create a MethodResolver for the specified Method-level annotation type
44  	 */
45  	public AnnotationMethodResolver(Class<? extends Annotation> annotationType) {
46  		Assert.notNull(annotationType, "annotationType must not be null");
47  		Assert.isTrue(ObjectUtils.containsElement(
48  				annotationType.getAnnotation(Target.class).value(), ElementType.METHOD),
49  				"Annotation [" + annotationType + "] is not a Method-level annotation.");
50  		this.annotationType = annotationType;
51  	}
52  
53  
54  	/**
55  	 * Find a <em>single</em> Method on the Class of the given candidate object
56  	 * that contains the annotation type for which this resolver is searching.
57  	 * 
58  	 * @param candidate the instance whose Class will be checked for the
59  	 * annotation
60  	 * 
61  	 * @return a single matching Method instance or <code>null</code> if the
62  	 * candidate's Class contains no Methods with the specified annotation
63  	 * 
64  	 * @throws IllegalArgumentException if more than one Method has the
65  	 * specified annotation
66  	 */
67      @Override
68  	public Method findMethod(Object candidate) {
69  		Assert.notNull(candidate, "candidate object must not be null");
70  		Class<?> targetClass = AopUtils.getTargetClass(candidate);
71  		if (targetClass == null) {
72  			targetClass = candidate.getClass();
73  		}
74  		return this.findMethod(targetClass);
75  	}
76  
77  	/**
78  	 * Find a <em>single</em> Method on the given Class that contains the
79  	 * annotation type for which this resolver is searching.
80  	 * 
81  	 * @param clazz the Class instance to check for the annotation
82  	 * 
83  	 * @return a single matching Method instance or <code>null</code> if the
84  	 * Class contains no Methods with the specified annotation
85  	 * 
86  	 * @throws IllegalArgumentException if more than one Method has the
87  	 * specified annotation
88  	 */
89      @Override
90  	public Method findMethod(final Class<?> clazz) {
91  		Assert.notNull(clazz, "class must not be null");
92  		final AtomicReference<Method> annotatedMethod = new AtomicReference<Method>();
93  		ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
94              @Override
95  			public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
96  				Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
97  				if (annotation != null) {
98  					Assert.isNull(annotatedMethod.get(), "found more than one method on target class ["
99  							+ clazz + "] with the annotation type [" + annotationType + "]");
100 					annotatedMethod.set(method);
101 				}
102 			}
103 		});
104 		return annotatedMethod.get();
105 	}
106 
107 }