1 /*
2  * Copyright 2002-2009 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.core.type.filter;
18 
19 import java.lang.annotation.Annotation;
20 import java.lang.annotation.Inherited;
21 
22 import org.springframework.core.type.AnnotationMetadata;
23 import org.springframework.core.type.classreading.MetadataReader;
24 
25 /**
26  * A simple filter which matches classes with a given annotation,
27  * checking inherited annotations as well.
28  *
29  * <p>The matching logic mirrors that of <code>Class.isAnnotationPresent()</code>.
30  *
31  * @author Mark Fisher
32  * @author Ramnivas Laddad
33  * @author Juergen Hoeller
34  * @since 2.5
35  */
36 public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter {
37 
38 	private final Class<? extends Annotation> annotationType;
39 
40 	private final boolean considerMetaAnnotations;
41 
42 
43 	/**
44 	 * Create a new AnnotationTypeFilter for the given annotation type.
45 	 * This filter will also match meta-annotations. To disable the
46 	 * meta-annotation matching, use the constructor that accepts a
47 	 * '<code>considerMetaAnnotations</code>' argument. The filter will
48 	 * not match interfaces.
49 	 * @param annotationType the annotation type to match
50 	 */
AnnotationTypeFilter(Class<? extends Annotation> annotationType)51 	public AnnotationTypeFilter(Class<? extends Annotation> annotationType) {
52 		this(annotationType, true);
53 	}
54 
55 	/**
56 	 * Create a new AnnotationTypeFilter for the given annotation type.
57 	 * The filter will not match interfaces.
58 	 * @param annotationType the annotation type to match
59 	 * @param considerMetaAnnotations whether to also match on meta-annotations
60 	 */
AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations)61 	public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) {
62 		this(annotationType, considerMetaAnnotations, false);
63 	}
64 
65 	/**
66 	 * Create a new {@link AnnotationTypeFilter} for the given annotation type.
67 	 * @param annotationType the annotation type to match
68 	 * @param considerMetaAnnotations whether to also match on meta-annotations
69 	 * @param considerInterfaces whether to also match interfaces
70 	 */
AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces)71 	public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) {
72 		super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces);
73 		this.annotationType = annotationType;
74 		this.considerMetaAnnotations = considerMetaAnnotations;
75 	}
76 
77 
78 	@Override
matchSelf(MetadataReader metadataReader)79 	protected boolean matchSelf(MetadataReader metadataReader) {
80 		AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
81 		return metadata.hasAnnotation(this.annotationType.getName()) ||
82 				(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
83 	}
84 
85 	@Override
matchSuperClass(String superClassName)86 	protected Boolean matchSuperClass(String superClassName) {
87 		if (Object.class.getName().equals(superClassName)) {
88 			return Boolean.FALSE;
89 		}
90 		else if (superClassName.startsWith("java.")) {
91 			try {
92 				Class<?> clazz = getClass().getClassLoader().loadClass(superClassName);
93 				return (clazz.getAnnotation(this.annotationType) != null);
94 			}
95 			catch (ClassNotFoundException ex) {
96 				// Class not found - can't determine a match that way.
97 			}
98 		}
99 		return null;
100 	}
101 
102 }
103