Java tutorial
/* * JBoss, Home of Professional Open Source * Copyright 2008, Red Hat, Inc., and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * 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.jboss.weld.introspector.jlr; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Sets; import org.jboss.weld.introspector.ConstructorSignature; import org.jboss.weld.introspector.DiscoveredExternalAnnotatedType; import org.jboss.weld.introspector.ExternalAnnotatedType; import org.jboss.weld.introspector.MethodSignature; import org.jboss.weld.introspector.TypeClosureLazyValueHolder; import org.jboss.weld.introspector.WeldClass; import org.jboss.weld.introspector.WeldConstructor; import org.jboss.weld.introspector.WeldField; import org.jboss.weld.introspector.WeldMethod; import org.jboss.weld.resources.ClassTransformer; import org.jboss.weld.resources.SharedObjectFacade; import org.jboss.weld.util.LazyValueHolder; import org.jboss.weld.util.collections.ArraySet; import org.jboss.weld.util.collections.ArraySetMultimap; import org.jboss.weld.util.reflection.Formats; import org.jboss.weld.util.reflection.Reflections; import org.jboss.weld.util.reflection.SecureReflections; import javax.enterprise.inject.spi.AnnotatedConstructor; import javax.enterprise.inject.spi.AnnotatedField; import javax.enterprise.inject.spi.AnnotatedMethod; import javax.enterprise.inject.spi.AnnotatedParameter; import javax.enterprise.inject.spi.AnnotatedType; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Represents an annotated class * <p/> * This class is immutable, and therefore threadsafe * * @param <T> the type of the class * @author Pete Muir * @author David Allen * @author Ales Justin */ public class WeldClassImpl<T> extends AbstractWeldAnnotated<T, Class<T>> implements WeldClass<T> { // Class attributes private final WeldClass<? super T> superclass; // The set of abstracted fields private final Set<WeldField<?, ?>> fields; // The map from annotation type to abstracted field with annotation private final ArrayListMultimap<Class<? extends Annotation>, WeldField<?, ?>> annotatedFields; // The set of abstracted fields private final ArraySet<WeldField<?, ?>> declaredFields; // The map from annotation type to abstracted field with annotation private final ArrayListMultimap<Class<? extends Annotation>, WeldField<?, ? super T>> declaredAnnotatedFields; // The map from annotation type to abstracted field with meta-annotation private final ArrayListMultimap<Class<? extends Annotation>, WeldField<?, ?>> declaredMetaAnnotatedFields; // The set of abstracted methods private final Set<WeldMethod<?, ? super T>> methods; // The map from annotation type to abstracted method with annotation private final ArrayListMultimap<Class<? extends Annotation>, WeldMethod<?, ?>> annotatedMethods; // The set of abstracted methods private final ArraySet<WeldMethod<?, ? super T>> declaredMethods; // The map from annotation type to abstracted method with annotation private final ArrayListMultimap<Class<? extends Annotation>, WeldMethod<?, ? super T>> declaredAnnotatedMethods; // The map from annotation type to method with a parameter with annotation private final ArrayListMultimap<Class<? extends Annotation>, WeldMethod<?, ? super T>> declaredMethodsByAnnotatedParameters; // The set of abstracted constructors private final ArraySet<WeldConstructor<T>> constructors; private final Map<ConstructorSignature, WeldConstructor<?>> declaredConstructorsBySignature; // The meta-annotation map (annotation type -> set of annotations containing // meta-annotation) of the item private final ArraySetMultimap<Class<? extends Annotation>, Annotation> declaredMetaAnnotationMap; private final boolean discovered; public static <T> WeldClass<T> of(Class<T> clazz, ClassTransformer classTransformer) { return new WeldClassImpl<T>(clazz, clazz, null, new TypeClosureLazyValueHolder(clazz), buildAnnotationMap(clazz.getAnnotations()), buildAnnotationMap(clazz.getDeclaredAnnotations()), classTransformer); } public static <T> WeldClass<T> of(AnnotatedType<T> annotatedType, ClassTransformer classTransformer) { return new WeldClassImpl<T>(annotatedType.getJavaClass(), annotatedType.getBaseType(), annotatedType, new TypeClosureLazyValueHolder(annotatedType.getTypeClosure()), buildAnnotationMap(annotatedType.getAnnotations()), buildAnnotationMap(annotatedType.getAnnotations()), classTransformer); } public static <T> WeldClass<T> of(Class<T> rawType, Type type, ClassTransformer classTransformer) { return new WeldClassImpl<T>(rawType, type, null, new TypeClosureLazyValueHolder(type), buildAnnotationMap(rawType.getAnnotations()), buildAnnotationMap(rawType.getDeclaredAnnotations()), classTransformer); } protected WeldClassImpl(Class<T> rawType, Type type, AnnotatedType<T> annotatedType, LazyValueHolder<Set<Type>> typeClosure, Map<Class<? extends Annotation>, Annotation> annotationMap, Map<Class<? extends Annotation>, Annotation> declaredAnnotationMap, ClassTransformer classTransformer) { super(annotationMap, declaredAnnotationMap, classTransformer, rawType, type, typeClosure); boolean modified; if (annotatedType instanceof DiscoveredExternalAnnotatedType) { discovered = true; modified = DiscoveredExternalAnnotatedType.class.cast(annotatedType).isModifed(); } else if (annotatedType instanceof ExternalAnnotatedType) { discovered = false; modified = false; } else { discovered = true; modified = false; } if (modified) { this.superclass = classTransformer.loadClass(Object.class); } else if (rawType.getSuperclass() != null) { this.superclass = classTransformer.loadClass(rawType.getSuperclass()); } else { this.superclass = null; } // Assign class field information this.declaredAnnotatedFields = ArrayListMultimap .<Class<? extends Annotation>, WeldField<?, ? super T>>create(); this.declaredMetaAnnotatedFields = ArrayListMultimap.<Class<? extends Annotation>, WeldField<?, ?>>create(); Set<WeldField<?, ?>> fieldsTemp = null; ArrayList<WeldField<?, ?>> declaredFieldsTemp = new ArrayList<WeldField<?, ?>>(); if (annotatedType == null) { this.annotatedFields = null; if (rawType != Object.class) { for (Field field : SecureReflections.getDeclaredFields(rawType)) { WeldField<?, T> annotatedField = WeldFieldImpl.of(field, this.<T>getDeclaringWeldClass(field, classTransformer), classTransformer); declaredFieldsTemp.add(annotatedField); for (Annotation annotation : annotatedField.getAnnotations()) { this.declaredAnnotatedFields.put(annotation.annotationType(), annotatedField); for (Annotation metaAnnotation : annotation.annotationType().getAnnotations()) { this.declaredMetaAnnotatedFields.put(metaAnnotation.annotationType(), annotatedField); } } } fieldsTemp = new ArraySet<WeldField<?, ?>>(declaredFieldsTemp).trimToSize(); if ((superclass != null) && (superclass.getJavaClass() != Object.class)) { fieldsTemp = Sets.union(fieldsTemp, Reflections.<Set<WeldField<?, ?>>>cast(superclass.getFields())); } } this.declaredFields = new ArraySet<WeldField<?, ?>>(declaredFieldsTemp); } else { this.annotatedFields = ArrayListMultimap.<Class<? extends Annotation>, WeldField<?, ?>>create(); fieldsTemp = new HashSet<WeldField<?, ?>>(); for (AnnotatedField<? super T> annotatedField : annotatedType.getFields()) { WeldField<?, ? super T> weldField = WeldFieldImpl.of(annotatedField, this, classTransformer); fieldsTemp.add(weldField); if (annotatedField.getDeclaringType().getJavaClass() == rawType) { declaredFieldsTemp.add(weldField); } for (Annotation annotation : weldField.getAnnotations()) { this.annotatedFields.put(annotation.annotationType(), weldField); if (annotatedField.getDeclaringType().getJavaClass() == rawType) { this.declaredAnnotatedFields.put(annotation.annotationType(), weldField); for (Annotation metaAnnotation : annotation.annotationType().getAnnotations()) { this.declaredMetaAnnotatedFields.put(metaAnnotation.annotationType(), weldField); } } } } this.declaredFields = new ArraySet<WeldField<?, ?>>(declaredFieldsTemp); fieldsTemp = new ArraySet<WeldField<?, ?>>(fieldsTemp).trimToSize(); this.annotatedFields.trimToSize(); } this.fields = fieldsTemp; this.declaredFields.trimToSize(); this.declaredAnnotatedFields.trimToSize(); this.declaredMetaAnnotatedFields.trimToSize(); // Assign constructor information this.constructors = new ArraySet<WeldConstructor<T>>(); this.declaredConstructorsBySignature = new HashMap<ConstructorSignature, WeldConstructor<?>>(); if (annotatedType == null) { for (Constructor<?> constructor : SecureReflections.getDeclaredConstructors(rawType)) { Constructor<T> c = Reflections.cast(constructor); WeldConstructor<T> annotatedConstructor = WeldConstructorImpl.of(c, this.<T>getDeclaringWeldClass(c, classTransformer), classTransformer); this.constructors.add(annotatedConstructor); this.declaredConstructorsBySignature.put(annotatedConstructor.getSignature(), annotatedConstructor); } } else { for (AnnotatedConstructor<T> constructor : annotatedType.getConstructors()) { WeldConstructor<T> weldConstructor = WeldConstructorImpl.of(constructor, this, classTransformer); this.constructors.add(weldConstructor); List<Class<?>> parameterTypes = new ArrayList<Class<?>>(); for (AnnotatedParameter<T> parameter : constructor.getParameters()) { parameterTypes.add(Reflections.getRawType(parameter.getBaseType())); } this.declaredConstructorsBySignature.put(weldConstructor.getSignature(), weldConstructor); } } this.constructors.trimToSize(); // Assign method information this.declaredAnnotatedMethods = ArrayListMultimap .<Class<? extends Annotation>, WeldMethod<?, ? super T>>create(); this.declaredMethodsByAnnotatedParameters = ArrayListMultimap .<Class<? extends Annotation>, WeldMethod<?, ? super T>>create(); Set<WeldMethod<?, ? super T>> methodsTemp = null; ArrayList<WeldMethod<?, ? super T>> declaredMethodsTemp = new ArrayList<WeldMethod<?, ? super T>>(); if (annotatedType == null) { this.annotatedMethods = null; if (rawType != Object.class) { for (Method method : SecureReflections.getDeclaredMethods(rawType)) { WeldMethod<?, T> weldMethod = WeldMethodImpl.of(method, this.<T>getDeclaringWeldClass(method, classTransformer), classTransformer); declaredMethodsTemp.add(weldMethod); for (Annotation annotation : weldMethod.getAnnotations()) { this.declaredAnnotatedMethods.put(annotation.annotationType(), weldMethod); } for (Class<? extends Annotation> annotationType : WeldMethod.MAPPED_PARAMETER_ANNOTATIONS) { if (weldMethod.getWeldParameters(annotationType).size() > 0) { this.declaredMethodsByAnnotatedParameters.put(annotationType, weldMethod); } } } methodsTemp = new ArraySet<WeldMethod<?, ? super T>>(declaredMethodsTemp).trimToSize(); if (superclass != null) { WeldClass<?> current = superclass; while (current.getJavaClass() != Object.class) { Set<WeldMethod<?, ? super T>> superClassMethods = Reflections .cast(current.getDeclaredWeldMethods()); methodsTemp = Sets.union(methodsTemp, superClassMethods); current = current.getWeldSuperclass(); } } } this.declaredMethods = new ArraySet<WeldMethod<?, ? super T>>(declaredMethodsTemp); } else { this.annotatedMethods = ArrayListMultimap.<Class<? extends Annotation>, WeldMethod<?, ?>>create(); methodsTemp = new HashSet<WeldMethod<?, ? super T>>(); for (AnnotatedMethod<? super T> method : annotatedType.getMethods()) { WeldMethod<?, ? super T> weldMethod = WeldMethodImpl.of(method, this, classTransformer); methodsTemp.add(weldMethod); if (method.getDeclaringType().getJavaClass() == rawType) { declaredMethodsTemp.add(weldMethod); } for (Annotation annotation : weldMethod.getAnnotations()) { annotatedMethods.put(annotation.annotationType(), weldMethod); if (method.getDeclaringType().getJavaClass() == rawType) { this.declaredAnnotatedMethods.put(annotation.annotationType(), weldMethod); } } for (Class<? extends Annotation> annotationType : WeldMethod.MAPPED_PARAMETER_ANNOTATIONS) { if (weldMethod.getWeldParameters(annotationType).size() > 0) { if (method.getDeclaringType().getJavaClass() == rawType) { this.declaredMethodsByAnnotatedParameters.put(annotationType, weldMethod); } } } } this.declaredMethods = new ArraySet<WeldMethod<?, ? super T>>(declaredMethodsTemp); methodsTemp = new ArraySet<WeldMethod<?, ? super T>>(methodsTemp).trimToSize(); this.annotatedMethods.trimToSize(); } this.methods = methodsTemp; this.declaredMethods.trimToSize(); this.declaredAnnotatedMethods.trimToSize(); this.declaredMethodsByAnnotatedParameters.trimToSize(); ArraySetMultimap<Class<? extends Annotation>, Annotation> declaredMetaAnnotationMap = new ArraySetMultimap<Class<? extends Annotation>, Annotation>(); for (Annotation declaredAnnotation : declaredAnnotationMap.values()) { addMetaAnnotations(declaredMetaAnnotationMap, declaredAnnotation, declaredAnnotation.annotationType().getAnnotations(), true); addMetaAnnotations(declaredMetaAnnotationMap, declaredAnnotation, classTransformer.getTypeStore().get(declaredAnnotation.annotationType()), true); declaredMetaAnnotationMap.putSingleElement(declaredAnnotation.annotationType(), declaredAnnotation); } declaredMetaAnnotationMap.trimToSize(); this.declaredMetaAnnotationMap = SharedObjectFacade.wrap(declaredMetaAnnotationMap); } private <X> WeldClass<X> getDeclaringWeldClass(Member member, ClassTransformer transformer) { if (member.getDeclaringClass().equals(getJavaClass())) { return cast(this); } else { return transformer.loadClass(Reflections.<Class<X>>cast(member.getDeclaringClass())); } } /** * Gets the implementing class * * @return The class */ public Class<? extends T> getAnnotatedClass() { return getJavaClass(); } /** * Gets the delegate (class) * * @return The class */ @Override public Class<T> getDelegate() { return getJavaClass(); } /** * Gets the abstracted fields of the class * <p/> * Initializes the fields if they are null * * @return The set of abstracted fields */ public Collection<WeldField<?, ?>> getWeldFields() { return Collections.unmodifiableCollection(fields); } public Collection<WeldField<?, ?>> getDeclaredFields() { return Collections.unmodifiableCollection(declaredFields); } public <F> WeldField<F, ?> getDeclaredWeldField(String fieldName) { for (WeldField<?, ?> field : declaredFields) { if (field.getName().equals(fieldName)) { return cast(field); } } return null; } public Collection<WeldField<?, ? super T>> getDeclaredWeldFields(Class<? extends Annotation> annotationType) { return Collections.unmodifiableCollection(declaredAnnotatedFields.get(annotationType)); } public WeldConstructor<T> getDeclaredWeldConstructor(ConstructorSignature signature) { return cast(declaredConstructorsBySignature.get(signature)); } /** * Gets the abstracted field annotated with a specific annotation type * <p/> * If the fields map is null, initialize it first * * @param annotationType The annotation type to match * @return A set of matching abstracted fields, null if none are found. */ public Collection<WeldField<?, ?>> getWeldFields(Class<? extends Annotation> annotationType) { if (annotatedFields == null) { // Build collection from class hierarchy ArrayList<WeldField<?, ?>> aggregatedFields = new ArrayList<WeldField<?, ?>>( this.declaredAnnotatedFields.get(annotationType)); if ((superclass != null) && (superclass.getJavaClass() != Object.class)) { aggregatedFields.addAll(superclass.getWeldFields(annotationType)); } return Collections.unmodifiableCollection(aggregatedFields); } else { // Return results collected directly from AnnotatedType return Collections.unmodifiableCollection(annotatedFields.get(annotationType)); } } public boolean isLocalClass() { return getJavaClass().isLocalClass(); } public boolean isAnonymousClass() { return getJavaClass().isAnonymousClass(); } public boolean isMemberClass() { return getJavaClass().isMemberClass(); } public boolean isAbstract() { return Modifier.isAbstract(getJavaClass().getModifiers()); } public boolean isEnum() { return getJavaClass().isEnum(); } public boolean isSerializable() { return Reflections.isSerializable(getJavaClass()); } /** * Gets the abstracted methods that have a certain annotation type present * <p/> * If the annotated methods map is null, initialize it first * * @param annotationType The annotation type to match * @return A set of matching method abstractions. Returns an empty set if no * matches are found. * @see org.jboss.weld.introspector.WeldClass#getWeldMethods(Class) */ public Collection<WeldMethod<?, ?>> getWeldMethods(Class<? extends Annotation> annotationType) { if (annotatedMethods == null) { ArrayList<WeldMethod<?, ?>> aggregateMethods = new ArrayList<WeldMethod<?, ?>>( this.declaredAnnotatedMethods.get(annotationType)); if ((superclass != null) && (superclass.getJavaClass() != Object.class)) { aggregateMethods.addAll(superclass.getDeclaredWeldMethods(annotationType)); } return Collections.unmodifiableCollection(aggregateMethods); } else { return Collections.unmodifiableCollection(annotatedMethods.get(annotationType)); } } public Collection<WeldMethod<?, ? super T>> getDeclaredWeldMethods(Class<? extends Annotation> annotationType) { return Collections.unmodifiableCollection(declaredAnnotatedMethods.get(annotationType)); } /** * Gets constructors with given annotation type * * @param annotationType The annotation type to match * @return A set of abstracted constructors with given annotation type. If * the constructors set is empty, initialize it first. Returns an * empty set if there are no matches. * @see org.jboss.weld.introspector.WeldClass#getWeldConstructors(Class) */ public Collection<WeldConstructor<T>> getWeldConstructors(Class<? extends Annotation> annotationType) { Set<WeldConstructor<T>> ret = new HashSet<WeldConstructor<T>>(); for (WeldConstructor<T> constructor : constructors) { if (constructor.isAnnotationPresent(annotationType)) { ret.add(constructor); } } return ret; } public WeldConstructor<T> getNoArgsWeldConstructor() { for (WeldConstructor<T> constructor : constructors) { if (constructor.getJavaMember().getParameterTypes().length == 0) { return constructor; } } return null; } public Collection<WeldMethod<?, ? super T>> getDeclaredWeldMethodsWithAnnotatedParameters( Class<? extends Annotation> annotationType) { return Collections.unmodifiableCollection(declaredMethodsByAnnotatedParameters.get(annotationType)); } public WeldMethod<?, ?> getWeldMethod(Method methodDescriptor) { // TODO Should be cached for (WeldMethod<?, ?> annotatedMethod : getWeldMethods()) { if (annotatedMethod.getName().equals(methodDescriptor.getName()) && Arrays .equals(annotatedMethod.getParameterTypesAsArray(), methodDescriptor.getParameterTypes())) { return annotatedMethod; } } return null; } public Collection<WeldMethod<?, ? super T>> getWeldMethods() { return Collections.unmodifiableSet(methods); } public WeldMethod<?, ?> getDeclaredWeldMethod(Method method) { // TODO Should be cached for (WeldMethod<?, ?> annotatedMethod : declaredMethods) { if (annotatedMethod.getName().equals(method.getName()) && Arrays.equals(annotatedMethod.getParameterTypesAsArray(), method.getParameterTypes())) { return annotatedMethod; } } return null; } public Collection<WeldMethod<?, ? super T>> getDeclaredWeldMethods() { return Collections.unmodifiableSet(declaredMethods); } public <M> WeldMethod<M, ?> getDeclaredWeldMethod(MethodSignature signature) { for (WeldMethod<?, ? super T> method : declaredMethods) { if (method.getSignature().equals(signature)) { return cast(method); } } return null; } public <M> WeldMethod<M, ?> getWeldMethod(MethodSignature signature) { WeldMethod<M, ?> method = cast(getDeclaredWeldMethod(signature)); if ((method == null) && (superclass != null) && (superclass.getJavaClass() != Object.class)) { method = superclass.getWeldMethod(signature); } return method; } /** * Gets a string representation of the class * * @return A string representation */ @Override public String toString() { return Formats.formatModifiers(getJavaClass().getModifiers()) + Formats.formatAnnotations(getAnnotations()) + " class " + getName() + Formats.formatActualTypeArguments(getActualTypeArguments()); } public String getSimpleName() { return getJavaClass().getSimpleName(); } /** * Indicates if the type is static * * @return True if static, false otherwise * @see org.jboss.weld.introspector.WeldAnnotated#isStatic() */ public boolean isStatic() { return Reflections.isStatic(getDelegate()); } /** * Indicates if the type if final * * @return True if final, false otherwise * @see org.jboss.weld.introspector.WeldAnnotated#isFinal() */ public boolean isFinal() { return Reflections.isFinal(getDelegate()); } public boolean isPublic() { return Modifier.isFinal(getJavaClass().getModifiers()); } public boolean isGeneric() { return getJavaClass().getTypeParameters().length > 0; } /** * Gets the name of the type * * @returns The name * @see org.jboss.weld.introspector.WeldAnnotated#getName() */ public String getName() { return getJavaClass().getName(); } /** * Gets the superclass abstraction of the type * * @return The superclass abstraction */ public WeldClass<? super T> getWeldSuperclass() { return superclass; } public boolean isEquivalent(Class<?> clazz) { return getDelegate().equals(clazz); } public boolean isPrivate() { return Modifier.isPrivate(getJavaClass().getModifiers()); } public boolean isPackagePrivate() { return Reflections.isPackagePrivate(getJavaClass().getModifiers()); } public Package getPackage() { return getJavaClass().getPackage(); } public <U> WeldClass<? extends U> asWeldSubclass(WeldClass<U> clazz) { return cast(this); } public <S> S cast(Object object) { return Reflections.<S>cast(object); } public Set<AnnotatedConstructor<T>> getConstructors() { return Collections.unmodifiableSet(Reflections.<Set<AnnotatedConstructor<T>>>cast(constructors)); } public Set<AnnotatedField<? super T>> getFields() { return cast(fields); } public Set<AnnotatedMethod<? super T>> getMethods() { return cast(methods); } public Set<Annotation> getDeclaredMetaAnnotations(Class<? extends Annotation> metaAnnotationType) { return Collections .unmodifiableSet(new ArraySet<Annotation>(declaredMetaAnnotationMap.get(metaAnnotationType))); } public boolean isDiscovered() { return discovered; } }