Added tiger classes of core bundle

This commit is contained in:
Arjen Poutsma 2008-10-22 15:48:39 +00:00
parent 4bc407fef8
commit 684a4f28c2
27 changed files with 1893 additions and 0 deletions

View File

@ -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.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.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 -->
<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" />

View File

@ -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;
}
}

View File

@ -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 &quot;annotation inheritance&quot;). 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
* &#064;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>&quot;value&quot;</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>&quot;value&quot;</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>&quot;value&quot;</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;
}
}
}

View File

@ -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;
}

View File

@ -0,0 +1,7 @@
<html>
<body>
Core support package for Java 5 annotations.
</body>
</html>

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -0,0 +1,7 @@
<html>
<body>
Core support package for type introspection through ASM-based class reading.
</body>
</html>

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -0,0 +1,7 @@
<html>
<body>
Core support package for type filtering (e.g. for classpath scanning).
</body>
</html>

View File

@ -0,0 +1,7 @@
<html>
<body>
Core support package for type introspection.
</body>
</html>

View File

@ -8,6 +8,7 @@ Import-Template:
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
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.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional
Unversioned-Imports:
javax.xml.transform.*,
org.w3c.dom.*,