Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@110 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
27 changed files with 1893 additions and 0 deletions
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
/* |
||||
* Copyright 2002-2006 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.annotation; |
||||
|
||||
import org.springframework.core.OrderComparator; |
||||
import org.springframework.core.Ordered; |
||||
|
||||
/** |
||||
* {@link java.util.Comparator} implementation that checks |
||||
* {@link org.springframework.core.Ordered} as well as the |
||||
* {@link Order} annotation, with an order value provided by an |
||||
* <code>Ordered</code> instance overriding a statically defined |
||||
* annotation value (if any). |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.0.1 |
||||
* @see org.springframework.core.Ordered |
||||
* @see Order |
||||
*/ |
||||
public class AnnotationAwareOrderComparator extends OrderComparator { |
||||
|
||||
protected int getOrder(Object obj) { |
||||
if (obj instanceof Ordered) { |
||||
return ((Ordered) obj).getOrder(); |
||||
} |
||||
if (obj != null) { |
||||
Order order = obj.getClass().getAnnotation(Order.class); |
||||
if (order != null) { |
||||
return order.value(); |
||||
} |
||||
} |
||||
return Ordered.LOWEST_PRECEDENCE; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,345 @@
@@ -0,0 +1,345 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.annotation; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.reflect.Method; |
||||
import java.util.Arrays; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.core.BridgeMethodResolver; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* General utility methods for working with annotations, handling bridge methods |
||||
* (which the compiler generates for generic declarations) as well as super |
||||
* methods (for optional "annotation inheritance"). Note that none of |
||||
* this is provided by the JDK's introspection facilities themselves. |
||||
* |
||||
* <p>As a general rule for runtime-retained annotations (e.g. for transaction |
||||
* control, authorization or service exposure), always use the lookup methods on |
||||
* this class (e.g., {@link #findAnnotation(Method, Class)}, |
||||
* {@link #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)}) |
||||
* instead of the plain annotation lookup methods in the JDK. You can still |
||||
* explicitly choose between lookup on the given class level only |
||||
* ({@link #getAnnotation(Method, Class)}) and lookup in the entire inheritance |
||||
* hierarchy of the given method ({@link #findAnnotation(Method, Class)}). |
||||
* |
||||
* @author Rob Harrop |
||||
* @author Juergen Hoeller |
||||
* @author Sam Brannen |
||||
* @author Mark Fisher |
||||
* @since 2.0 |
||||
* @see java.lang.reflect.Method#getAnnotations() |
||||
* @see java.lang.reflect.Method#getAnnotation(Class) |
||||
*/ |
||||
public abstract class AnnotationUtils { |
||||
|
||||
/** The attribute name for annotations with a single element */ |
||||
static final String VALUE = "value"; |
||||
|
||||
|
||||
/** |
||||
* Get all {@link Annotation Annotations} from the supplied {@link Method}. |
||||
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler. |
||||
* @param method the method to look for annotations on |
||||
* @return the annotations found |
||||
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) |
||||
*/ |
||||
public static Annotation[] getAnnotations(Method method) { |
||||
return BridgeMethodResolver.findBridgedMethod(method).getAnnotations(); |
||||
} |
||||
|
||||
/** |
||||
* Get a single {@link Annotation} of <code>annotationType</code> from the |
||||
* supplied {@link Method}. |
||||
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler. |
||||
* @param method the method to look for annotations on |
||||
* @param annotationType the annotation class to look for |
||||
* @return the annotations found |
||||
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) |
||||
*/ |
||||
public static <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) { |
||||
return BridgeMethodResolver.findBridgedMethod(method).getAnnotation(annotationType); |
||||
} |
||||
|
||||
/** |
||||
* Get a single {@link Annotation} of <code>annotationType</code> from the |
||||
* supplied {@link Method}, traversing its super methods if no annotation |
||||
* can be found on the given method itself. |
||||
* <p>Annotations on methods are not inherited by default, so we need to handle |
||||
* this explicitly. Tge |
||||
* @param method the method to look for annotations on |
||||
* @param annotationType the annotation class to look for |
||||
* @return the annotation found, or <code>null</code> if none found |
||||
*/ |
||||
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) { |
||||
A annotation = getAnnotation(method, annotationType); |
||||
Class<?> cl = method.getDeclaringClass(); |
||||
while (annotation == null) { |
||||
cl = cl.getSuperclass(); |
||||
if (cl == null || cl == Object.class) { |
||||
break; |
||||
} |
||||
try { |
||||
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes()); |
||||
annotation = getAnnotation(equivalentMethod, annotationType); |
||||
} |
||||
catch (NoSuchMethodException ex) { |
||||
// We're done...
|
||||
} |
||||
} |
||||
return annotation; |
||||
} |
||||
|
||||
/** |
||||
* Find a single {@link Annotation} of <code>annotationType</code> from the |
||||
* supplied {@link Class}, traversing its interfaces and super classes |
||||
* if no annotation can be found on the given class itself. |
||||
* <p>This method explicitly handles class-level annotations which are |
||||
* not declared as {@link java.lang.annotation.Inherited inherited} |
||||
* <i>as well as annotations on interfaces</i>. |
||||
* <p>The algorithm operates as follows: Searches for an annotation on the given |
||||
* class and returns it if found. Else searches all interfaces that the given |
||||
* class declares, returning the annotation from the first matching candidate, |
||||
* if any. Else proceeds with introspection of the superclass of the given class, |
||||
* checking the superclass itself; if no annotation found there, proceeds with |
||||
* the interfaces that the superclass declares. Recursing up through the entire |
||||
* superclass hierarchy if no match is found. |
||||
* @param clazz the class to look for annotations on |
||||
* @param annotationType the annotation class to look for |
||||
* @return the annotation found, or <code>null</code> if none found |
||||
*/ |
||||
public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) { |
||||
Assert.notNull(clazz, "Class must not be null"); |
||||
A annotation = clazz.getAnnotation(annotationType); |
||||
if (annotation != null) { |
||||
return annotation; |
||||
} |
||||
for (Class<?> ifc : clazz.getInterfaces()) { |
||||
annotation = findAnnotation(ifc, annotationType); |
||||
if (annotation != null) { |
||||
return annotation; |
||||
} |
||||
} |
||||
Class superClass = clazz.getSuperclass(); |
||||
if (superClass == null || superClass == Object.class) { |
||||
return null; |
||||
} |
||||
return findAnnotation(superClass, annotationType); |
||||
} |
||||
|
||||
/** |
||||
* Find the first {@link Class} in the inheritance hierarchy of the |
||||
* specified <code>clazz</code> (including the specified |
||||
* <code>clazz</code> itself) which declares an annotation for the |
||||
* specified <code>annotationType</code>, or <code>null</code> if not |
||||
* found. If the supplied <code>clazz</code> is <code>null</code>, |
||||
* <code>null</code> will be returned. |
||||
* <p>If the supplied <code>clazz</code> is an interface, only the interface
|
||||
* itself will be checked; the inheritance hierarchy for interfaces will not |
||||
* be traversed. |
||||
* <p>The standard {@link Class} API does not provide a mechanism for |
||||
* determining which class in an inheritance hierarchy actually declares an |
||||
* {@link Annotation}, so we need to handle this explicitly. |
||||
* @param annotationType the Class object corresponding to the annotation type |
||||
* @param clazz the Class object corresponding to the class on which to |
||||
* check for the annotation, or <code>null</code>. |
||||
* @return the first {@link Class} in the inheritance hierarchy of the |
||||
* specified <code>clazz</code> which declares an annotation for the specified |
||||
* <code>annotationType</code>, or <code>null</code> if not found. |
||||
* @see Class#isAnnotationPresent(Class) |
||||
* @see Class#getDeclaredAnnotations() |
||||
*/ |
||||
public static Class<?> findAnnotationDeclaringClass(Class<? extends Annotation> annotationType, Class<?> clazz) { |
||||
Assert.notNull(annotationType, "Annotation type must not be null"); |
||||
if (clazz == null || clazz.equals(Object.class)) { |
||||
return null; |
||||
} |
||||
return (isAnnotationDeclaredLocally(annotationType, clazz)) ? |
||||
clazz : findAnnotationDeclaringClass(annotationType, clazz.getSuperclass()); |
||||
} |
||||
|
||||
/** |
||||
* Determine whether an annotation for the specified <code>annotationType</code> |
||||
* is declared locally on the supplied <code>clazz</code>. |
||||
* The supplied {@link Class} object may represent any type. |
||||
* <p>Note: This method does <strong>not</strong> determine if the annotation |
||||
* is {@link java.lang.annotation.Inherited inherited}. For greater clarity |
||||
* regarding inherited annotations, consider using |
||||
* {@link #isAnnotationInherited(Class, Class)} instead. |
||||
* @param annotationType the Class object corresponding to the annotation type |
||||
* @param clazz the Class object corresponding to the class on which to |
||||
* check for the annotation |
||||
* @return <code>true</code> if an annotation for the specified |
||||
* <code>annotationType</code> is declared locally on the supplied <code>clazz</code> |
||||
* @see Class#getDeclaredAnnotations() |
||||
* @see #isAnnotationInherited(Class, Class) |
||||
*/ |
||||
public static boolean isAnnotationDeclaredLocally(Class<? extends Annotation> annotationType, Class<?> clazz) { |
||||
Assert.notNull(annotationType, "Annotation type must not be null"); |
||||
Assert.notNull(clazz, "Class must not be null"); |
||||
boolean declaredLocally = false; |
||||
for (Annotation annotation : Arrays.asList(clazz.getDeclaredAnnotations())) { |
||||
if (annotation.annotationType().equals(annotationType)) { |
||||
declaredLocally = true; |
||||
break; |
||||
} |
||||
} |
||||
return declaredLocally; |
||||
} |
||||
|
||||
/** |
||||
* Determine whether an annotation for the specified <code>annotationType</code> |
||||
* is present on the supplied <code>clazz</code> and is |
||||
* {@link java.lang.annotation.Inherited inherited} |
||||
* (i.e., not declared locally for the class). |
||||
* <p>If the supplied <code>clazz</code> is an interface, only the interface
|
||||
* itself will be checked. In accord with standard meta-annotation |
||||
* semantics, the inheritance hierarchy for interfaces will not be |
||||
* traversed. See the {@link java.lang.annotation.Inherited JavaDoc} for the |
||||
* @Inherited meta-annotation for further details regarding annotation |
||||
* inheritance. |
||||
* @param annotationType the Class object corresponding to the annotation type |
||||
* @param clazz the Class object corresponding to the class on which to |
||||
* check for the annotation |
||||
* @return <code>true</code> if an annotation for the specified |
||||
* <code>annotationType</code> is present on the supplied <code>clazz</code> |
||||
* and is {@link java.lang.annotation.Inherited inherited} |
||||
* @see Class#isAnnotationPresent(Class) |
||||
* @see #isAnnotationDeclaredLocally(Class, Class) |
||||
*/ |
||||
public static boolean isAnnotationInherited(Class<? extends Annotation> annotationType, Class<?> clazz) { |
||||
Assert.notNull(annotationType, "Annotation type must not be null"); |
||||
Assert.notNull(clazz, "Class must not be null"); |
||||
return (clazz.isAnnotationPresent(annotationType) && !isAnnotationDeclaredLocally(annotationType, clazz)); |
||||
} |
||||
|
||||
/** |
||||
* Retrieve the given annotation's attributes as a Map. |
||||
* @param annotation the annotation to retrieve the attributes for |
||||
* @return the Map of annotation attributes, with attribute names as keys |
||||
* and corresponding attribute values as values |
||||
*/ |
||||
public static Map<String, Object> getAnnotationAttributes(Annotation annotation) { |
||||
Map<String, Object> attrs = new HashMap<String, Object>(); |
||||
Method[] methods = annotation.annotationType().getDeclaredMethods(); |
||||
for (int j = 0; j < methods.length; j++) { |
||||
Method method = methods[j]; |
||||
if (method.getParameterTypes().length == 0 && method.getReturnType() != void.class) { |
||||
try { |
||||
attrs.put(method.getName(), method.invoke(annotation)); |
||||
} |
||||
catch (Exception ex) { |
||||
throw new IllegalStateException("Could not obtain annotation attribute values", ex); |
||||
} |
||||
} |
||||
} |
||||
return attrs; |
||||
} |
||||
|
||||
/** |
||||
* Retrieve the <em>value</em> of the <code>"value"</code> |
||||
* attribute of a single-element Annotation, given an annotation instance. |
||||
* @param annotation the annotation instance from which to retrieve the value |
||||
* @return the attribute value, or <code>null</code> if not found |
||||
* @see #getValue(Annotation, String) |
||||
*/ |
||||
public static Object getValue(Annotation annotation) { |
||||
return getValue(annotation, VALUE); |
||||
} |
||||
|
||||
/** |
||||
* Retrieve the <em>value</em> of a named Annotation attribute, given an |
||||
* annotation instance. |
||||
* @see #getValue(Annotation) |
||||
* @param annotation the annotation instance from which to retrieve the value |
||||
* @param attributeName the name of the attribute value to retrieve |
||||
* @return the attribute value, or <code>null</code> if not found |
||||
*/ |
||||
public static Object getValue(Annotation annotation, String attributeName) { |
||||
try { |
||||
Method method = annotation.annotationType().getDeclaredMethod(attributeName, new Class[0]); |
||||
return method.invoke(annotation); |
||||
} |
||||
catch (Exception ex) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Retrieve the <em>default value</em> of the |
||||
* <code>"value"</code> attribute of a single-element |
||||
* Annotation, given an annotation instance. |
||||
* @param annotation the annotation instance from which to retrieve |
||||
* the default value |
||||
* @return the default value, or <code>null</code> if not found |
||||
* @see #getDefaultValue(Annotation, String) |
||||
*/ |
||||
public static Object getDefaultValue(Annotation annotation) { |
||||
return getDefaultValue(annotation, VALUE); |
||||
} |
||||
|
||||
/** |
||||
* Retrieve the <em>default value</em> of a named Annotation attribute, |
||||
* given an annotation instance. |
||||
* @param annotation the annotation instance from which to retrieve |
||||
* the default value |
||||
* @param attributeName the name of the attribute value to retrieve |
||||
* @return the default value of the named attribute, or <code>null</code> |
||||
* if not found. |
||||
* @see #getDefaultValue(Class, String) |
||||
*/ |
||||
public static Object getDefaultValue(Annotation annotation, String attributeName) { |
||||
return getDefaultValue(annotation.annotationType(), attributeName); |
||||
} |
||||
|
||||
/** |
||||
* Retrieve the <em>default value</em> of the |
||||
* <code>"value"</code> attribute of a single-element |
||||
* Annotation, given the {@link Class annotation type}. |
||||
* @param annotationType the <em>annotation type</em> for which the |
||||
* default value should be retrieved |
||||
* @return the default value, or <code>null</code> if not found |
||||
* @see #getDefaultValue(Class, String) |
||||
*/ |
||||
public static Object getDefaultValue(Class<? extends Annotation> annotationType) { |
||||
return getDefaultValue(annotationType, VALUE); |
||||
} |
||||
|
||||
/** |
||||
* Retrieve the <em>default value</em> of a named Annotation attribute, |
||||
* given the {@link Class annotation type}. |
||||
* @param annotationType the <em>annotation type</em> for which the |
||||
* default value should be retrieved |
||||
* @param attributeName the name of the attribute value to retrieve. |
||||
* @return the default value of the named attribute, or <code>null</code> |
||||
* if not found |
||||
* @see #getDefaultValue(Annotation, String) |
||||
*/ |
||||
public static Object getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) { |
||||
try { |
||||
Method method = annotationType.getDeclaredMethod(attributeName, new Class[0]); |
||||
return method.getDefaultValue(); |
||||
} |
||||
catch (Exception ex) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright 2002-2006 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.annotation; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.springframework.core.Ordered; |
||||
|
||||
/** |
||||
* Annotation to define ordering. |
||||
* |
||||
* <p>Value is optional, and represents order value as defined |
||||
* in the Ordered interface. Lower values have higher priority. |
||||
* Default value is <code>Integer.MAX_VALUE</code>, indicating lowest |
||||
* priority (losing to any other specified order value). |
||||
* |
||||
* @author Rod Johnson |
||||
* @since 2.0 |
||||
* @see org.springframework.core.Ordered |
||||
* @see AnnotationAwareOrderComparator |
||||
*/ |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) |
||||
public @interface Order { |
||||
|
||||
int value() default Ordered.LOWEST_PRECEDENCE; |
||||
|
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<html> |
||||
<body> |
||||
|
||||
Core support package for Java 5 annotations. |
||||
|
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type; |
||||
|
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Interface that defines abstract access to the annotations of a specific |
||||
* class, in a form that does not require that class to be loaded yet. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author Mark Fisher |
||||
* @since 2.5 |
||||
* @see StandardAnnotationMetadata |
||||
* @see org.springframework.core.type.classreading.MetadataReader#getAnnotationMetadata() |
||||
*/ |
||||
public interface AnnotationMetadata extends ClassMetadata { |
||||
|
||||
/** |
||||
* Return the names of all annotation types defined on the underlying class. |
||||
* @return the annotation type names |
||||
*/ |
||||
Set<String> getAnnotationTypes(); |
||||
|
||||
/** |
||||
* Determine whether the underlying class has an annotation of the given |
||||
* type defined. |
||||
* @param annotationType the annotation type to look for |
||||
* @return whether a matching annotation is defined |
||||
*/ |
||||
boolean hasAnnotation(String annotationType); |
||||
|
||||
/** |
||||
* Return the names of all meta-annotation types defined on the |
||||
* given annotation type of the underlying class. |
||||
* @return the meta-annotation type names |
||||
*/ |
||||
Set<String> getMetaAnnotationTypes(String annotationType); |
||||
|
||||
/** |
||||
* Determine whether the underlying class has an annotation that |
||||
* is itself annotated with the meta-annotation of the given type. |
||||
* @param metaAnnotationType the meta-annotation type to look for |
||||
* @return whether a matching meta-annotation is defined |
||||
*/ |
||||
boolean hasMetaAnnotation(String metaAnnotationType); |
||||
|
||||
/** |
||||
* Retrieve the attributes of the annotation of the given type, |
||||
* if any (i.e. if defined on the underlying class). |
||||
* @param annotationType the annotation type to look for |
||||
* @return a Map of attributes, with the attribute name as key |
||||
* (e.g. "value") and the defined attribute value as Map value. |
||||
* This return value will be <code>null</code> if no matching |
||||
* annotation is defined. |
||||
*/ |
||||
Map<String, Object> getAnnotationAttributes(String annotationType); |
||||
|
||||
} |
||||
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type; |
||||
|
||||
/** |
||||
* Interface that defines abstract metadata of a specific class, |
||||
* in a form that does not require that class to be loaded yet. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
* @see StandardClassMetadata |
||||
* @see org.springframework.core.type.classreading.MetadataReader#getClassMetadata() |
||||
* @see AnnotationMetadata |
||||
*/ |
||||
public interface ClassMetadata { |
||||
|
||||
/** |
||||
* Return the name of the underlying class. |
||||
*/ |
||||
String getClassName(); |
||||
|
||||
/** |
||||
* Return whether the underlying class represents an interface. |
||||
*/ |
||||
boolean isInterface(); |
||||
|
||||
/** |
||||
* Return whether the underlying class is marked as abstract. |
||||
*/ |
||||
boolean isAbstract(); |
||||
|
||||
/** |
||||
* Return whether the underlying class represents a concrete class, |
||||
* i.e. neither an interface nor an abstract class. |
||||
*/ |
||||
boolean isConcrete(); |
||||
|
||||
/** |
||||
* Determine whether the underlying class is independent, |
||||
* i.e. whether it is a top-level class or a nested class
|
||||
* (static inner class) that can be constructed independent |
||||
* from an enclosing class. |
||||
*/ |
||||
boolean isIndependent(); |
||||
|
||||
/** |
||||
* Return whether the underlying class has an enclosing class
|
||||
* (i.e. the underlying class is an inner/nested class or |
||||
* a local class within a method). |
||||
* <p>If this method returns <code>false</code>, then the |
||||
* underlying class is a top-level class. |
||||
*/ |
||||
boolean hasEnclosingClass(); |
||||
|
||||
/** |
||||
* Return the name of the enclosing class of the underlying class, |
||||
* or <code>null</code> if the underlying class is a top-level class. |
||||
*/ |
||||
String getEnclosingClassName(); |
||||
|
||||
/** |
||||
* Return whether the underlying class has a super class. |
||||
*/ |
||||
boolean hasSuperClass(); |
||||
|
||||
/** |
||||
* Return the name of the super class of the underlying class, |
||||
* or <code>null</code> if there is no super class defined. |
||||
*/ |
||||
String getSuperClassName(); |
||||
|
||||
/** |
||||
* Return the name of all interfaces that the underlying class
|
||||
* implements, or an empty array if there are none. |
||||
*/ |
||||
String[] getInterfaceNames(); |
||||
|
||||
} |
||||
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils; |
||||
|
||||
/** |
||||
* {@link AnnotationMetadata} implementation that uses standard reflection |
||||
* to introspect a given <code>Class</code>. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author Mark Fisher |
||||
* @since 2.5 |
||||
*/ |
||||
public class StandardAnnotationMetadata extends StandardClassMetadata implements AnnotationMetadata { |
||||
|
||||
public StandardAnnotationMetadata(Class introspectedClass) { |
||||
super(introspectedClass); |
||||
} |
||||
|
||||
|
||||
public Set<String> getAnnotationTypes() { |
||||
Set<String> types = new HashSet<String>(); |
||||
Annotation[] anns = getIntrospectedClass().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
types.add(anns[i].annotationType().getName()); |
||||
} |
||||
return types; |
||||
} |
||||
|
||||
public boolean hasAnnotation(String annotationType) { |
||||
Annotation[] anns = getIntrospectedClass().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
if (anns[i].annotationType().getName().equals(annotationType)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public Set<String> getMetaAnnotationTypes(String annotationType) { |
||||
Annotation[] anns = getIntrospectedClass().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
if (anns[i].annotationType().getName().equals(annotationType)) { |
||||
Set<String> types = new HashSet<String>(); |
||||
Annotation[] metaAnns = anns[i].annotationType().getAnnotations(); |
||||
for (Annotation meta : metaAnns) { |
||||
types.add(meta.annotationType().getName()); |
||||
} |
||||
return types; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public boolean hasMetaAnnotation(String annotationType) { |
||||
Annotation[] anns = getIntrospectedClass().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
Annotation[] metaAnns = anns[i].annotationType().getAnnotations(); |
||||
for (Annotation meta : metaAnns) { |
||||
if (meta.annotationType().getName().equals(annotationType)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationType) { |
||||
Annotation[] anns = getIntrospectedClass().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
Annotation ann = anns[i]; |
||||
if (ann.annotationType().getName().equals(annotationType)) { |
||||
return AnnotationUtils.getAnnotationAttributes(ann); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type; |
||||
|
||||
import java.lang.reflect.Modifier; |
||||
|
||||
/** |
||||
* {@link ClassMetadata} implementation that uses standard reflection |
||||
* to introspect a given <code>Class</code>. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
public class StandardClassMetadata implements ClassMetadata { |
||||
|
||||
private final Class introspectedClass; |
||||
|
||||
|
||||
public StandardClassMetadata(Class introspectedClass) { |
||||
this.introspectedClass = introspectedClass; |
||||
} |
||||
|
||||
public final Class getIntrospectedClass() { |
||||
return this.introspectedClass; |
||||
} |
||||
|
||||
|
||||
public String getClassName() { |
||||
return getIntrospectedClass().getName(); |
||||
} |
||||
|
||||
public boolean isInterface() { |
||||
return getIntrospectedClass().isInterface(); |
||||
} |
||||
|
||||
public boolean isAbstract() { |
||||
return Modifier.isAbstract(getIntrospectedClass().getModifiers()); |
||||
} |
||||
|
||||
public boolean isConcrete() { |
||||
return !(isInterface() || isAbstract()); |
||||
} |
||||
|
||||
public boolean isIndependent() { |
||||
return (!hasEnclosingClass() || |
||||
(getIntrospectedClass().getDeclaringClass() != null && |
||||
Modifier.isStatic(getIntrospectedClass().getModifiers()))); |
||||
} |
||||
|
||||
public boolean hasEnclosingClass() { |
||||
return (getIntrospectedClass().getEnclosingClass() != null); |
||||
} |
||||
|
||||
public String getEnclosingClassName() { |
||||
Class enclosingClass = getIntrospectedClass().getEnclosingClass(); |
||||
return (enclosingClass != null ? enclosingClass.getName() : null); |
||||
} |
||||
|
||||
public boolean hasSuperClass() { |
||||
return (getIntrospectedClass().getSuperclass() != null); |
||||
} |
||||
|
||||
public String getSuperClassName() { |
||||
Class superClass = getIntrospectedClass().getSuperclass(); |
||||
return (superClass != null ? superClass.getName() : null); |
||||
} |
||||
|
||||
public String[] getInterfaceNames() { |
||||
Class[] ifcs = getIntrospectedClass().getInterfaces(); |
||||
String[] ifcNames = new String[ifcs.length]; |
||||
for (int i = 0; i < ifcs.length; i++) { |
||||
ifcNames[i] = ifcs[i].getName(); |
||||
} |
||||
return ifcNames; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.reflect.Method; |
||||
import java.util.Collection; |
||||
import java.util.HashSet; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.objectweb.asm.AnnotationVisitor; |
||||
import org.objectweb.asm.Type; |
||||
import org.objectweb.asm.commons.EmptyVisitor; |
||||
|
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
|
||||
/** |
||||
* ASM class visitor which looks for the class name and implemented types as |
||||
* well as for the annotations defined on the class, exposing them through |
||||
* the {@link org.springframework.core.type.AnnotationMetadata} interface. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @author Mark Fisher |
||||
* @since 2.5 |
||||
*/ |
||||
class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata { |
||||
|
||||
private final Map<String, Map<String, Object>> attributesMap = new LinkedHashMap<String, Map<String, Object>>(); |
||||
|
||||
private final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>(); |
||||
|
||||
|
||||
private final ClassLoader classLoader; |
||||
|
||||
|
||||
public AnnotationMetadataReadingVisitor(ClassLoader classLoader) { |
||||
this.classLoader = classLoader; |
||||
} |
||||
|
||||
|
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { |
||||
final String className = Type.getType(desc).getClassName(); |
||||
final Map<String, Object> attributes = new LinkedHashMap<String, Object>(); |
||||
return new EmptyVisitor() { |
||||
public void visit(String name, Object value) { |
||||
// Explicitly defined annotation attribute value.
|
||||
attributes.put(name, value); |
||||
} |
||||
public void visitEnd() { |
||||
try { |
||||
Class annotationClass = classLoader.loadClass(className); |
||||
// Check declared default values of attributes in the annotation type.
|
||||
Method[] annotationAttributes = annotationClass.getMethods(); |
||||
for (int i = 0; i < annotationAttributes.length; i++) { |
||||
Method annotationAttribute = annotationAttributes[i]; |
||||
String attributeName = annotationAttribute.getName(); |
||||
Object defaultValue = annotationAttribute.getDefaultValue(); |
||||
if (defaultValue != null && !attributes.containsKey(attributeName)) { |
||||
attributes.put(attributeName, defaultValue); |
||||
} |
||||
} |
||||
// Register annotations that the annotation type is annotated with.
|
||||
Annotation[] metaAnnotations = annotationClass.getAnnotations(); |
||||
Set<String> metaAnnotationTypeNames = new HashSet<String>(); |
||||
for (Annotation metaAnnotation : metaAnnotations) { |
||||
metaAnnotationTypeNames.add(metaAnnotation.annotationType().getName()); |
||||
} |
||||
metaAnnotationMap.put(className, metaAnnotationTypeNames); |
||||
} |
||||
catch (ClassNotFoundException ex) { |
||||
// Class not found - can't determine meta-annotations.
|
||||
} |
||||
attributesMap.put(className, attributes); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
|
||||
public Set<String> getAnnotationTypes() { |
||||
return this.attributesMap.keySet(); |
||||
} |
||||
|
||||
public boolean hasAnnotation(String annotationType) { |
||||
return this.attributesMap.containsKey(annotationType); |
||||
} |
||||
|
||||
public Set<String> getMetaAnnotationTypes(String annotationType) { |
||||
return this.metaAnnotationMap.get(annotationType); |
||||
} |
||||
|
||||
public boolean hasMetaAnnotation(String metaAnnotationType) { |
||||
Collection<Set<String>> allMetaTypes = this.metaAnnotationMap.values(); |
||||
for (Set<String> metaTypes : allMetaTypes) { |
||||
if (metaTypes.contains(metaAnnotationType)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationType) { |
||||
return this.attributesMap.get(annotationType); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.core.io.ResourceLoader; |
||||
|
||||
/** |
||||
* Caching implementation of the {@link MetadataReaderFactory} interface, |
||||
* caching an ASM {@link org.objectweb.asm.ClassReader} per Spring Resource handle |
||||
* (i.e. per ".class" file). |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory { |
||||
|
||||
private final Map<Resource, MetadataReader> classReaderCache = new HashMap<Resource, MetadataReader>(); |
||||
|
||||
|
||||
/** |
||||
* Create a new CachingMetadataReaderFactory for the default class loader. |
||||
*/ |
||||
public CachingMetadataReaderFactory() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Create a new CachingMetadataReaderFactory for the given resource loader. |
||||
* @param resourceLoader the Spring ResourceLoader to use |
||||
* (also determines the ClassLoader to use) |
||||
*/ |
||||
public CachingMetadataReaderFactory(ResourceLoader resourceLoader) { |
||||
super(resourceLoader); |
||||
} |
||||
|
||||
/** |
||||
* Create a new CachingMetadataReaderFactory for the given class loader. |
||||
* @param classLoader the ClassLoader to use |
||||
*/ |
||||
public CachingMetadataReaderFactory(ClassLoader classLoader) { |
||||
super(classLoader); |
||||
} |
||||
|
||||
|
||||
public MetadataReader getMetadataReader(Resource resource) throws IOException { |
||||
synchronized (this.classReaderCache) { |
||||
MetadataReader metadataReader = this.classReaderCache.get(resource); |
||||
if (metadataReader == null) { |
||||
metadataReader = super.getMetadataReader(resource); |
||||
this.classReaderCache.put(resource, metadataReader); |
||||
} |
||||
return metadataReader; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import org.objectweb.asm.Opcodes; |
||||
import org.objectweb.asm.commons.EmptyVisitor; |
||||
|
||||
import org.springframework.core.type.ClassMetadata; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
/** |
||||
* ASM class visitor which looks only for the class name and implemented types, |
||||
* exposing them through the {@link org.springframework.core.type.ClassMetadata} |
||||
* interface. |
||||
* |
||||
* @author Rod Johnson |
||||
* @author Costin Leau |
||||
* @author Mark Fisher |
||||
* @author Ramnivas Laddad |
||||
* @since 2.5 |
||||
*/ |
||||
class ClassMetadataReadingVisitor extends EmptyVisitor implements ClassMetadata { |
||||
|
||||
private String className; |
||||
|
||||
private boolean isInterface; |
||||
|
||||
private boolean isAbstract; |
||||
|
||||
private String enclosingClassName; |
||||
|
||||
private boolean independentInnerClass; |
||||
|
||||
private String superClassName; |
||||
|
||||
private String[] interfaces; |
||||
|
||||
|
||||
public void visit(int version, int access, String name, String signature, String supername, String[] interfaces) { |
||||
this.className = ClassUtils.convertResourcePathToClassName(name); |
||||
this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0); |
||||
this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0); |
||||
if (supername != null) { |
||||
this.superClassName = ClassUtils.convertResourcePathToClassName(supername); |
||||
} |
||||
this.interfaces = new String[interfaces.length]; |
||||
for (int i = 0; i < interfaces.length; i++) { |
||||
this.interfaces[i] = ClassUtils.convertResourcePathToClassName(interfaces[i]); |
||||
} |
||||
} |
||||
|
||||
public void visitOuterClass(String owner, String name, String desc) { |
||||
this.enclosingClassName = ClassUtils.convertResourcePathToClassName(owner); |
||||
} |
||||
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) { |
||||
if (outerName != null && this.className.equals(ClassUtils.convertResourcePathToClassName(name))) { |
||||
this.enclosingClassName = ClassUtils.convertResourcePathToClassName(outerName); |
||||
this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0); |
||||
} |
||||
} |
||||
|
||||
|
||||
public String getClassName() { |
||||
return this.className; |
||||
} |
||||
|
||||
public boolean isInterface() { |
||||
return this.isInterface; |
||||
} |
||||
|
||||
public boolean isAbstract() { |
||||
return this.isAbstract; |
||||
} |
||||
|
||||
public boolean isConcrete() { |
||||
return !(this.isInterface || this.isAbstract); |
||||
} |
||||
|
||||
public boolean isIndependent() { |
||||
return (this.enclosingClassName == null || this.independentInnerClass); |
||||
} |
||||
|
||||
public boolean hasEnclosingClass() { |
||||
return (this.enclosingClassName != null); |
||||
} |
||||
|
||||
public String getEnclosingClassName() { |
||||
return this.enclosingClassName; |
||||
} |
||||
|
||||
public boolean hasSuperClass() { |
||||
return (this.superClassName != null); |
||||
} |
||||
|
||||
public String getSuperClassName() { |
||||
return this.superClassName; |
||||
} |
||||
|
||||
public String[] getInterfaceNames() { |
||||
return this.interfaces; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
import org.springframework.core.type.ClassMetadata; |
||||
|
||||
/** |
||||
* Simple facade for accessing class metadata, |
||||
* as read by an ASM {@link org.objectweb.asm.ClassReader}. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
public interface MetadataReader { |
||||
|
||||
/** |
||||
* Read basic class metadata for the underlying class. |
||||
*/ |
||||
ClassMetadata getClassMetadata(); |
||||
|
||||
/** |
||||
* Read full annotation metadata for the underlying class. |
||||
*/ |
||||
AnnotationMetadata getAnnotationMetadata(); |
||||
|
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.springframework.core.io.Resource; |
||||
|
||||
/** |
||||
* Factory interface for {@link MetadataReader} instances. |
||||
* Allows for caching a MetadataReader per original resource. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
* @see SimpleMetadataReaderFactory |
||||
* @see CachingMetadataReaderFactory |
||||
*/ |
||||
public interface MetadataReaderFactory { |
||||
|
||||
/** |
||||
* Obtain a MetadataReader for the given class name. |
||||
* @param className the class name (to be resolved to a ".class" file) |
||||
* @return a holder for the ClassReader instance (never <code>null</code>) |
||||
* @throws IOException in case of I/O failure |
||||
*/ |
||||
MetadataReader getMetadataReader(String className) throws IOException; |
||||
|
||||
/** |
||||
* Obtain a MetadataReader for the given resource. |
||||
* @param resource the resource (pointing to a ".class" file) |
||||
* @return a holder for the ClassReader instance (never <code>null</code>) |
||||
* @throws IOException in case of I/O failure |
||||
*/ |
||||
MetadataReader getMetadataReader(Resource resource) throws IOException; |
||||
|
||||
} |
||||
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import org.objectweb.asm.ClassReader; |
||||
|
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
import org.springframework.core.type.ClassMetadata; |
||||
|
||||
/** |
||||
* {@link MetadataReader} implementation based on an ASM |
||||
* {@link org.objectweb.asm.ClassReader}. |
||||
* |
||||
* <p>Package-visible in order to allow for repackaging the ASM library |
||||
* without effect on users of the <code>core.type</code> package. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
class SimpleMetadataReader implements MetadataReader { |
||||
|
||||
private final ClassReader classReader; |
||||
|
||||
private final ClassLoader classLoader; |
||||
|
||||
|
||||
public SimpleMetadataReader(ClassReader classReader, ClassLoader classLoader) { |
||||
this.classReader = classReader; |
||||
this.classLoader = classLoader; |
||||
} |
||||
|
||||
|
||||
public ClassMetadata getClassMetadata() { |
||||
ClassMetadataReadingVisitor visitor = new ClassMetadataReadingVisitor(); |
||||
this.classReader.accept(visitor, true); |
||||
return visitor; |
||||
} |
||||
|
||||
public AnnotationMetadata getAnnotationMetadata() { |
||||
AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(this.classLoader); |
||||
this.classReader.accept(visitor, true); |
||||
return visitor; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import org.objectweb.asm.ClassReader; |
||||
|
||||
import org.springframework.core.io.DefaultResourceLoader; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.core.io.ResourceLoader; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
/** |
||||
* Simple implementation of the {@link MetadataReaderFactory} interface, |
||||
* creating a new ASM {@link org.objectweb.asm.ClassReader} for every request. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
public class SimpleMetadataReaderFactory implements MetadataReaderFactory { |
||||
|
||||
private final ResourceLoader resourceLoader; |
||||
|
||||
|
||||
/** |
||||
* Create a new SimpleMetadataReaderFactory for the default class loader. |
||||
*/ |
||||
public SimpleMetadataReaderFactory() { |
||||
this.resourceLoader = new DefaultResourceLoader(); |
||||
} |
||||
|
||||
/** |
||||
* Create a new SimpleMetadataReaderFactory for the given resource loader. |
||||
* @param resourceLoader the Spring ResourceLoader to use |
||||
* (also determines the ClassLoader to use) |
||||
*/ |
||||
public SimpleMetadataReaderFactory(ResourceLoader resourceLoader) { |
||||
this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader()); |
||||
} |
||||
|
||||
/** |
||||
* Create a new SimpleMetadataReaderFactory for the given class loader. |
||||
* @param classLoader the ClassLoader to use |
||||
*/ |
||||
public SimpleMetadataReaderFactory(ClassLoader classLoader) { |
||||
this.resourceLoader = |
||||
(classLoader != null ? new DefaultResourceLoader(classLoader) : new DefaultResourceLoader()); |
||||
} |
||||
|
||||
|
||||
public MetadataReader getMetadataReader(String className) throws IOException { |
||||
String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX + |
||||
ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX; |
||||
return getMetadataReader(this.resourceLoader.getResource(resourcePath)); |
||||
} |
||||
|
||||
public MetadataReader getMetadataReader(Resource resource) throws IOException { |
||||
InputStream is = resource.getInputStream(); |
||||
try { |
||||
return new SimpleMetadataReader(new ClassReader(is), this.resourceLoader.getClassLoader()); |
||||
} |
||||
finally { |
||||
is.close(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<html> |
||||
<body> |
||||
|
||||
Core support package for type introspection through ASM-based class reading. |
||||
|
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.filter; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.springframework.core.type.ClassMetadata; |
||||
import org.springframework.core.type.classreading.MetadataReaderFactory; |
||||
import org.springframework.core.type.classreading.MetadataReader; |
||||
|
||||
/** |
||||
* Type filter that exposes a |
||||
* {@link org.springframework.core.type.ClassMetadata} object |
||||
* to subclasses, for class testing purposes. |
||||
* |
||||
* @author Rod Johnson |
||||
* @author Costin Leau |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
* @see #match(org.springframework.core.type.ClassMetadata) |
||||
*/ |
||||
public abstract class AbstractClassTestingTypeFilter implements TypeFilter { |
||||
|
||||
public final boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) |
||||
throws IOException { |
||||
|
||||
return match(metadataReader.getClassMetadata()); |
||||
} |
||||
|
||||
/** |
||||
* Determine a match based on the given ClassMetadata object. |
||||
* @param metadata the ClassMetadata object |
||||
* @return whether this filter matches on the specified type |
||||
*/ |
||||
protected abstract boolean match(ClassMetadata metadata); |
||||
|
||||
} |
||||
@ -0,0 +1,138 @@
@@ -0,0 +1,138 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.filter; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.springframework.core.type.ClassMetadata; |
||||
import org.springframework.core.type.classreading.MetadataReaderFactory; |
||||
import org.springframework.core.type.classreading.MetadataReader; |
||||
|
||||
/** |
||||
* Type filter that is aware of traversing over hierarchy. |
||||
* |
||||
* <p>This filter is useful when matching needs to be made based on potentially the |
||||
* whole class/interface hierarchy. The algorithm employed uses succeed-fast |
||||
* strategy i.e. if at anytime a match is declared, no further processing is |
||||
* carried out. |
||||
* |
||||
* @author Ramnivas Laddad |
||||
* @author Mark Fisher |
||||
* @since 2.5 |
||||
*/ |
||||
public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilter { |
||||
|
||||
private final boolean considerInherited; |
||||
|
||||
private final boolean considerInterfaces; |
||||
|
||||
|
||||
protected AbstractTypeHierarchyTraversingFilter(boolean considerInherited, boolean considerInterfaces) { |
||||
this.considerInherited = considerInherited; |
||||
this.considerInterfaces = considerInterfaces; |
||||
} |
||||
|
||||
|
||||
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) |
||||
throws IOException { |
||||
|
||||
// This method optimizes avoiding unnecessary creation of ClassReaders
|
||||
// as well as visiting over those readers.
|
||||
if (matchSelf(metadataReader)) { |
||||
return true; |
||||
} |
||||
ClassMetadata metadata = metadataReader.getClassMetadata(); |
||||
if (matchClassName(metadata.getClassName())) { |
||||
return true; |
||||
} |
||||
|
||||
if (!this.considerInherited) { |
||||
return false; |
||||
} |
||||
if (metadata.hasSuperClass()) { |
||||
// Optimization to avoid creating ClassReader for super class.
|
||||
Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName()); |
||||
if (superClassMatch != null) { |
||||
if (superClassMatch.booleanValue()) { |
||||
return true; |
||||
} |
||||
} |
||||
else { |
||||
// Need to read super class to determine a match...
|
||||
if (match(metadata.getSuperClassName(), metadataReaderFactory)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!this.considerInterfaces) { |
||||
return false; |
||||
} |
||||
for (String ifc : metadata.getInterfaceNames()) { |
||||
// Optimization to avoid creating ClassReader for super class
|
||||
Boolean interfaceMatch = matchInterface(ifc); |
||||
if (interfaceMatch != null) { |
||||
if (interfaceMatch.booleanValue()) { |
||||
return true; |
||||
} |
||||
} |
||||
else { |
||||
// Need to read interface to determine a match...
|
||||
if (match(ifc, metadataReaderFactory)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
private boolean match(String className, MetadataReaderFactory metadataReaderFactory) throws IOException { |
||||
return match(metadataReaderFactory.getMetadataReader(className), metadataReaderFactory); |
||||
} |
||||
|
||||
/** |
||||
* Override this to match self characteristics alone. Typically, |
||||
* the implementation will use a visitor to extract information |
||||
* to perform matching. |
||||
*/ |
||||
protected boolean matchSelf(MetadataReader metadataReader) { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Override this to match on type name. |
||||
*/ |
||||
protected boolean matchClassName(String className) { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Override this to match on super type name. |
||||
*/ |
||||
protected Boolean matchSuperClass(String superClassName) { |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Override this to match on interface type name. |
||||
*/ |
||||
protected Boolean matchInterface(String interfaceNames) { |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.filter; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.annotation.Inherited; |
||||
|
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
import org.springframework.core.type.classreading.MetadataReader; |
||||
|
||||
/** |
||||
* A simple filter which matches classes with a given annotation, |
||||
* checking inherited annotations as well. |
||||
* |
||||
* <p>The matching logic mirrors that of <code>Class.isAnnotationPresent()</code>. |
||||
* |
||||
* @author Mark Fisher |
||||
* @author Ramnivas Laddad |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter { |
||||
|
||||
private final Class<? extends Annotation> annotationType; |
||||
|
||||
private final boolean considerMetaAnnotations; |
||||
|
||||
|
||||
/** |
||||
* Create a new AnnotationTypeFilter for the given annotation type. |
||||
* This filter will also match meta-annotations. To disable the |
||||
* meta-annotation matching, use the constructor that accepts a |
||||
* '<code>considerMetaAnnotations</code>' argument. |
||||
* @param annotationType the annotation type to match |
||||
*/ |
||||
public AnnotationTypeFilter(Class<? extends Annotation> annotationType) { |
||||
this(annotationType, true); |
||||
} |
||||
|
||||
/** |
||||
* Create a new AnnotationTypeFilter for the given annotation type. |
||||
* @param annotationType the annotation type to match |
||||
* @param considerMetaAnnotations whether to also match on meta-annotations |
||||
*/ |
||||
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) { |
||||
super(annotationType.isAnnotationPresent(Inherited.class), false); |
||||
this.annotationType = annotationType; |
||||
this.considerMetaAnnotations = considerMetaAnnotations; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected boolean matchSelf(MetadataReader metadataReader) { |
||||
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); |
||||
return metadata.hasAnnotation(this.annotationType.getName()) || |
||||
(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName())); |
||||
} |
||||
|
||||
@Override |
||||
protected Boolean matchSuperClass(String superClassName) { |
||||
if (Object.class.getName().equals(superClassName)) { |
||||
return Boolean.FALSE; |
||||
} |
||||
else if (superClassName.startsWith("java.")) { |
||||
try { |
||||
Class clazz = getClass().getClassLoader().loadClass(superClassName); |
||||
return Boolean.valueOf(clazz.getAnnotation(this.annotationType) != null); |
||||
} |
||||
catch (ClassNotFoundException ex) { |
||||
// Class not found - can't determine a match that way.
|
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.filter; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.aspectj.bridge.IMessageHandler; |
||||
import org.aspectj.weaver.ResolvedType; |
||||
import org.aspectj.weaver.World; |
||||
import org.aspectj.weaver.bcel.BcelWorld; |
||||
import org.aspectj.weaver.patterns.Bindings; |
||||
import org.aspectj.weaver.patterns.FormalBinding; |
||||
import org.aspectj.weaver.patterns.IScope; |
||||
import org.aspectj.weaver.patterns.PatternParser; |
||||
import org.aspectj.weaver.patterns.SimpleScope; |
||||
import org.aspectj.weaver.patterns.TypePattern; |
||||
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory; |
||||
import org.springframework.core.type.classreading.MetadataReader; |
||||
|
||||
/** |
||||
* Type filter that uses AspectJ type pattern for matching. |
||||
* |
||||
* <p>A critical implementation details of this type filter is that it does not |
||||
* load the class being examined to match with a type pattern. |
||||
* |
||||
* @author Ramnivas Laddad |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
public class AspectJTypeFilter implements TypeFilter { |
||||
|
||||
private final World world; |
||||
|
||||
private final TypePattern typePattern; |
||||
|
||||
|
||||
public AspectJTypeFilter(String typePatternExpression, ClassLoader classLoader) { |
||||
this.world = new BcelWorld(classLoader, IMessageHandler.THROW, null); |
||||
this.world.setBehaveInJava5Way(true); |
||||
PatternParser patternParser = new PatternParser(typePatternExpression); |
||||
TypePattern typePattern = patternParser.parseTypePattern(); |
||||
typePattern.resolve(this.world); |
||||
IScope scope = new SimpleScope(this.world, new FormalBinding[0]); |
||||
this.typePattern = typePattern.resolveBindings(scope, Bindings.NONE, false, false); |
||||
} |
||||
|
||||
|
||||
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) |
||||
throws IOException { |
||||
|
||||
String className = metadataReader.getClassMetadata().getClassName(); |
||||
ResolvedType resolvedType = this.world.resolve(className); |
||||
return this.typePattern.matchesStatically(resolvedType); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.filter; |
||||
|
||||
/** |
||||
* A simple filter which matches classes that are assignable to a given type. |
||||
* |
||||
* @author Rod Johnson |
||||
* @author Mark Fisher |
||||
* @author Ramnivas Laddad |
||||
* @since 2.5 |
||||
*/ |
||||
public class AssignableTypeFilter extends AbstractTypeHierarchyTraversingFilter { |
||||
|
||||
private final Class targetType; |
||||
|
||||
|
||||
/** |
||||
* Create a new AssignableTypeFilter for the given type. |
||||
* @param targetType the type to match |
||||
*/ |
||||
public AssignableTypeFilter(Class targetType) { |
||||
super(true, true); |
||||
this.targetType = targetType; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected boolean matchClassName(String className) { |
||||
return this.targetType.getName().equals(className); |
||||
} |
||||
|
||||
@Override |
||||
protected Boolean matchSuperClass(String superClassName) { |
||||
return matchTargetType(superClassName); |
||||
} |
||||
|
||||
@Override |
||||
protected Boolean matchInterface(String interfaceName) { |
||||
return matchTargetType(interfaceName); |
||||
} |
||||
|
||||
protected Boolean matchTargetType(String typeName) { |
||||
if (this.targetType.getName().equals(typeName)) { |
||||
return true; |
||||
} |
||||
else if (Object.class.getName().equals(typeName)) { |
||||
return Boolean.FALSE; |
||||
} |
||||
else if (typeName.startsWith("java.")) { |
||||
try { |
||||
Class clazz = getClass().getClassLoader().loadClass(typeName); |
||||
return Boolean.valueOf(this.targetType.isAssignableFrom(clazz)); |
||||
} |
||||
catch (ClassNotFoundException ex) { |
||||
// Class not found - can't determine a match that way.
|
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.filter; |
||||
|
||||
import java.util.regex.Pattern; |
||||
|
||||
import org.springframework.core.type.ClassMetadata; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* A simple filter for matching a fully-qualified class name with a regex {@link Pattern}. |
||||
* |
||||
* @author Mark Fisher |
||||
* @author Juergen Hoeller |
||||
* @since 2.5 |
||||
*/ |
||||
public class RegexPatternTypeFilter extends AbstractClassTestingTypeFilter { |
||||
|
||||
private final Pattern pattern; |
||||
|
||||
|
||||
public RegexPatternTypeFilter(Pattern pattern) { |
||||
Assert.notNull(pattern, "Pattern must not be null"); |
||||
this.pattern = pattern; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected boolean match(ClassMetadata metadata) { |
||||
return this.pattern.matcher(metadata.getClassName()).matches(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* Copyright 2002-2007 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.filter; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.springframework.core.type.classreading.MetadataReader; |
||||
import org.springframework.core.type.classreading.MetadataReaderFactory; |
||||
|
||||
/** |
||||
* Base interface for type filters using a |
||||
* {@link org.springframework.core.type.classreading.MetadataReader}. |
||||
* |
||||
* @author Costin Leau |
||||
* @author Juergen Hoeller |
||||
* @author Mark Fisher |
||||
* @since 2.5 |
||||
*/ |
||||
public interface TypeFilter { |
||||
|
||||
/** |
||||
* Determine whether this filter matches for the class described by |
||||
* the given metadata. |
||||
* @param metadataReader the metadata reader for the target class
|
||||
* @param metadataReaderFactory a factory for obtaining metadata readers |
||||
* for other classes (such as superclasses and interfaces) |
||||
* @return whether this filter matches |
||||
* @throws IOException in case of I/O failure when reading metadata |
||||
*/ |
||||
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) |
||||
throws IOException; |
||||
|
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<html> |
||||
<body> |
||||
|
||||
Core support package for type filtering (e.g. for classpath scanning). |
||||
|
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<html> |
||||
<body> |
||||
|
||||
Core support package for type introspection. |
||||
|
||||
</body> |
||||
</html> |
||||
Loading…
Reference in new issue