Added tiger classes of core bundle
This commit is contained in:
parent
4bc407fef8
commit
684a4f28c2
|
|
@ -23,6 +23,8 @@
|
||||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->runtime" />
|
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->runtime" />
|
||||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="optional->runtime" />
|
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="optional->runtime" />
|
||||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.collections" rev="3.2.0" conf="optional->compile" />
|
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.collections" rev="3.2.0" conf="optional->compile" />
|
||||||
|
<!--<dependency org="org.aspectj" name="com.springsource.org.aspectj.runtime" rev="1.6.2.RELEASE" conf="optional->compile" />-->
|
||||||
|
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="1.6.2.RELEASE" conf="optional->compile" />
|
||||||
<!-- These should be replaced with the internal repackaging of ASM -->
|
<!-- These should be replaced with the internal repackaging of ASM -->
|
||||||
<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm" rev="2.2.3" conf="optional->compile" />
|
<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm" rev="2.2.3" conf="optional->compile" />
|
||||||
<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm.commons" rev="2.2.3" conf="optional->compile" />
|
<dependency org="org.objectweb.asm" name="com.springsource.org.objectweb.asm.commons" rev="2.2.3" conf="optional->compile" />
|
||||||
|
|
|
||||||
|
|
@ -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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
Core support package for Java 5 annotations.
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
Core support package for type introspection through ASM-based class reading.
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
Core support package for type filtering (e.g. for classpath scanning).
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
Core support package for type introspection.
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -8,6 +8,7 @@ Import-Template:
|
||||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||||
org.objectweb.asm.*;version="[2.2.3, 3.0.0)";resolution:=optional,
|
org.objectweb.asm.*;version="[2.2.3, 3.0.0)";resolution:=optional,
|
||||||
org.apache.log4j.*;version="[1.2.15, 2.0.0)";resolution:=optional,
|
org.apache.log4j.*;version="[1.2.15, 2.0.0)";resolution:=optional,
|
||||||
|
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional
|
||||||
Unversioned-Imports:
|
Unversioned-Imports:
|
||||||
javax.xml.transform.*,
|
javax.xml.transform.*,
|
||||||
org.w3c.dom.*,
|
org.w3c.dom.*,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue