All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.weld.introspector.jlr.WeldClassImpl Maven / Gradle / Ivy

There is a newer version: 6.0.0.Beta4
Show newest version
/*
 * 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.Multimap;
import com.google.common.collect.Multimaps;
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.collections.HashSetSupplier;
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
 * 

* This class is immutable, and therefore threadsafe * * @param the type of the class * @author Pete Muir * @author David Allen * @author Ales Justin * @author Marko Luksa */ public class WeldClassImpl extends AbstractWeldAnnotated> implements WeldClass { // Class attributes private final WeldClass superclass; // The set of abstracted fields private final Set> fields; // The map from annotation type to abstracted field with annotation private final ArrayListMultimap, WeldField> annotatedFields; // The set of abstracted fields private final ArraySet> declaredFields; // The map from annotation type to abstracted field with annotation private final ArrayListMultimap, WeldField> declaredAnnotatedFields; // The map from annotation type to abstracted field with meta-annotation private final ArrayListMultimap, WeldField> declaredMetaAnnotatedFields; // The set of abstracted methods private final Set> methods; // The map from annotation type to abstracted method with annotation private final ArrayListMultimap, WeldMethod> annotatedMethods; // The set of abstracted methods private final ArraySet> declaredMethods; // The Set of overridden methods private final Set> overriddenMethods; // The map from annotation type to abstracted method with annotation private final ArrayListMultimap, WeldMethod> declaredAnnotatedMethods; // The map from annotation type to method with a parameter with annotation private final ArrayListMultimap, WeldMethod> declaredMethodsByAnnotatedParameters; // The set of abstracted constructors private final ArraySet> constructors; private final Map> declaredConstructorsBySignature; // The meta-annotation map (annotation type -> set of annotations containing // meta-annotation) of the item private final ArraySetMultimap, Annotation> declaredMetaAnnotationMap; private final boolean discovered; private final boolean modified; public static WeldClass of(Class clazz, ClassTransformer classTransformer) { return new WeldClassImpl(clazz, clazz, null, new TypeClosureLazyValueHolder(clazz), buildAnnotationMap(clazz.getAnnotations()), buildAnnotationMap(clazz.getDeclaredAnnotations()), classTransformer); } public static WeldClass of(AnnotatedType annotatedType, ClassTransformer classTransformer) { return new WeldClassImpl(annotatedType.getJavaClass(), annotatedType.getBaseType(), annotatedType, new TypeClosureLazyValueHolder(annotatedType.getTypeClosure()), buildAnnotationMap(annotatedType.getAnnotations()), buildAnnotationMap(annotatedType.getAnnotations()), classTransformer); } public static WeldClass of(Class rawType, Type type, ClassTransformer classTransformer) { return new WeldClassImpl(rawType, type, null, new TypeClosureLazyValueHolder(type), buildAnnotationMap(rawType.getAnnotations()), buildAnnotationMap(rawType.getDeclaredAnnotations()), classTransformer); } protected WeldClassImpl(Class rawType, Type type, AnnotatedType annotatedType, LazyValueHolder> typeClosure, Map, Annotation> annotationMap, Map, Annotation> declaredAnnotationMap, ClassTransformer classTransformer) { super(annotationMap, declaredAnnotationMap, classTransformer, rawType, type, typeClosure); 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., WeldField>create(); this.declaredMetaAnnotatedFields = ArrayListMultimap., WeldField>create(); Set> fieldsTemp = null; ArrayList> declaredFieldsTemp = new ArrayList>(); if (annotatedType == null) { this.annotatedFields = null; if (rawType != Object.class) { for (Field field : SecureReflections.getDeclaredFields(rawType)) { WeldField annotatedField = WeldFieldImpl.of(field, this.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>(declaredFieldsTemp).trimToSize(); if ((superclass != null) && (superclass.getJavaClass() != Object.class)) { fieldsTemp = Sets.union(fieldsTemp, Reflections.>>cast(superclass.getFields())); } } this.declaredFields = new ArraySet>(declaredFieldsTemp); } else { this.annotatedFields = ArrayListMultimap., WeldField>create(); fieldsTemp = new HashSet>(); for (AnnotatedField annotatedField : annotatedType.getFields()) { WeldField 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>(declaredFieldsTemp); fieldsTemp = new ArraySet>(fieldsTemp).trimToSize(); this.annotatedFields.trimToSize(); } this.fields = fieldsTemp; this.declaredFields.trimToSize(); this.declaredAnnotatedFields.trimToSize(); this.declaredMetaAnnotatedFields.trimToSize(); // Assign constructor information this.constructors = new ArraySet>(); this.declaredConstructorsBySignature = new HashMap>(); if (annotatedType == null) { for (Constructor constructor : SecureReflections.getDeclaredConstructors(rawType)) { Constructor c = Reflections.cast(constructor); WeldConstructor annotatedConstructor = WeldConstructorImpl.of(c, this.getDeclaringWeldClass(c, classTransformer), classTransformer); this.constructors.add(annotatedConstructor); this.declaredConstructorsBySignature.put(annotatedConstructor.getSignature(), annotatedConstructor); } } else { for (AnnotatedConstructor constructor : annotatedType.getConstructors()) { WeldConstructor weldConstructor = WeldConstructorImpl.of(constructor, this, classTransformer); this.constructors.add(weldConstructor); List> parameterTypes = new ArrayList>(); for (AnnotatedParameter parameter : constructor.getParameters()) { parameterTypes.add(Reflections.getRawType(parameter.getBaseType())); } this.declaredConstructorsBySignature.put(weldConstructor.getSignature(), weldConstructor); } } this.constructors.trimToSize(); // Assign method information this.declaredAnnotatedMethods = ArrayListMultimap., WeldMethod>create(); this.declaredMethodsByAnnotatedParameters = ArrayListMultimap., WeldMethod>create(); Set> methodsTemp = null; ArrayList> declaredMethodsTemp = new ArrayList>(); if (annotatedType == null) { this.annotatedMethods = null; if (rawType != Object.class) { for (Method method : SecureReflections.getDeclaredMethods(rawType)) { WeldMethod weldMethod = WeldMethodImpl.of(method, this.getDeclaringWeldClass(method, classTransformer), classTransformer); declaredMethodsTemp.add(weldMethod); for (Annotation annotation : weldMethod.getAnnotations()) { this.declaredAnnotatedMethods.put(annotation.annotationType(), weldMethod); } for (Class annotationType : WeldMethod.MAPPED_PARAMETER_ANNOTATIONS) { if (weldMethod.getWeldParameters(annotationType).size() > 0) { this.declaredMethodsByAnnotatedParameters.put(annotationType, weldMethod); } } } methodsTemp = new ArraySet>(declaredMethodsTemp).trimToSize(); if (superclass != null) { WeldClass current = superclass; while (current.getJavaClass() != Object.class) { Set> superClassMethods = Reflections.cast(current.getDeclaredWeldMethods()); methodsTemp = Sets.union(methodsTemp, superClassMethods); current = current.getWeldSuperclass(); } } } this.declaredMethods = new ArraySet>(declaredMethodsTemp); } else { this.annotatedMethods = ArrayListMultimap., WeldMethod>create(); methodsTemp = new HashSet>(); for (AnnotatedMethod method : annotatedType.getMethods()) { WeldMethod 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 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>(declaredMethodsTemp); methodsTemp = new ArraySet>(methodsTemp).trimToSize(); this.annotatedMethods.trimToSize(); } this.methods = methodsTemp; this.declaredMethods.trimToSize(); this.declaredAnnotatedMethods.trimToSize(); this.declaredMethodsByAnnotatedParameters.trimToSize(); ArraySetMultimap, Annotation> declaredMetaAnnotationMap = new ArraySetMultimap, 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); this.overriddenMethods = getOverriddenMethods(this, this.methods); } protected Set> getOverriddenMethods(WeldClass annotatedType, Set> methods) { Set> overriddenMethods = new HashSet>(); Multimap seenMethods = Multimaps.newSetMultimap(new HashMap>(), HashSetSupplier.instance()); for (Class clazz = annotatedType.getJavaClass(); clazz != null && clazz != Object.class; clazz = clazz.getSuperclass()) { for (WeldMethod method : methods) { if (method.getJavaMember().getDeclaringClass().equals(clazz)) { if (isOverridden(method, seenMethods)) { overriddenMethods.add(method); } seenMethods.put(method.getSignature(), method.getPackage()); } } } return Collections.unmodifiableSet(overriddenMethods); } private static boolean isOverridden(WeldMethod method, Multimap seenMethods) { if (method.isPrivate()) { return false; } else if (method.isPackagePrivate() && seenMethods.containsKey(method.getSignature())) { return seenMethods.get(method.getSignature()).contains(method.getPackage()); } else { return seenMethods.containsKey(method.getSignature()); } } private WeldClass getDeclaringWeldClass(Member member, ClassTransformer transformer) { if (member.getDeclaringClass().equals(getJavaClass())) { return cast(this); } else { return transformer.loadClass(Reflections.>cast(member.getDeclaringClass())); } } /** * Gets the implementing class * * @return The class */ public Class getAnnotatedClass() { return getJavaClass(); } /** * Gets the delegate (class) * * @return The class */ @Override public Class getDelegate() { return getJavaClass(); } /** * Gets the abstracted fields of the class *

* Initializes the fields if they are null * * @return The set of abstracted fields */ public Collection> getWeldFields() { return Collections.unmodifiableCollection(fields); } public Collection> getDeclaredFields() { return Collections.unmodifiableCollection(declaredFields); } public WeldField getDeclaredWeldField(String fieldName) { for (WeldField field : declaredFields) { if (field.getName().equals(fieldName)) { return cast(field); } } return null; } public Collection> getDeclaredWeldFields(Class annotationType) { return Collections.unmodifiableCollection(declaredAnnotatedFields.get(annotationType)); } public WeldConstructor getDeclaredWeldConstructor(ConstructorSignature signature) { return cast(declaredConstructorsBySignature.get(signature)); } /** * Gets the abstracted field annotated with a specific annotation type *

* 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> getWeldFields(Class annotationType) { if (annotatedFields == null) { // Build collection from class hierarchy ArrayList> aggregatedFields = new ArrayList>(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 *

* 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> getWeldMethods(Class annotationType) { if (annotatedMethods == null) { ArrayList> aggregateMethods = new ArrayList>(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> getDeclaredWeldMethods(Class 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> getWeldConstructors(Class annotationType) { Set> ret = new HashSet>(); for (WeldConstructor constructor : constructors) { if (constructor.isAnnotationPresent(annotationType)) { ret.add(constructor); } } return ret; } public WeldConstructor getNoArgsWeldConstructor() { for (WeldConstructor constructor : constructors) { if (constructor.getJavaMember().getParameterTypes().length == 0) { return constructor; } } return null; } public Collection> getDeclaredWeldMethodsWithAnnotatedParameters(Class annotationType) { return Collections.unmodifiableCollection(declaredMethodsByAnnotatedParameters.get(annotationType)); } public WeldMethod getWeldMethod(Method methodDescriptor) { // TODO Should be cached for (WeldMethod annotatedMethod : getWeldMethods()) { if(!annotatedMethod.getJavaMember().isBridge()) { if (annotatedMethod.getName().equals(methodDescriptor.getName()) && Arrays.equals(annotatedMethod.getParameterTypesAsArray(), methodDescriptor.getParameterTypes())) { return annotatedMethod; } } } return null; } public Collection> 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> getDeclaredWeldMethods() { return Collections.unmodifiableSet(declaredMethods); } public WeldMethod getDeclaredWeldMethod(MethodSignature signature) { for (WeldMethod method : declaredMethods) { if (method.getSignature().equals(signature)) { return cast(method); } } return null; } public WeldMethod getWeldMethod(MethodSignature signature) { WeldMethod 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 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 WeldClass asWeldSubclass(WeldClass clazz) { return cast(this); } public S cast(Object object) { return Reflections.cast(object); } public Set> getConstructors() { return Collections.unmodifiableSet(Reflections.>>cast(constructors)); } public Set> getFields() { return cast(fields); } public Set> getMethods() { return cast(methods); } public Set getDeclaredMetaAnnotations(Class metaAnnotationType) { return Collections.unmodifiableSet(new ArraySet(declaredMetaAnnotationMap.get(metaAnnotationType))); } public boolean isDiscovered() { return discovered; } public boolean isModified() { return modified; } @Override public boolean isMethodOverridden(WeldMethod method) { return overriddenMethods.contains(method); } }