org.jboss.weld.resources.ClassTransformer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weld-servlet-shaded Show documentation
Show all versions of weld-servlet-shaded Show documentation
This jar bundles all the bits of Weld and CDI required for running in a Servlet container.
/*
* 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.resources;
import static org.jboss.weld.util.reflection.Reflections.cast;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotation;
import org.jboss.weld.annotated.enhanced.jlr.EnhancedAnnotatedTypeImpl;
import org.jboss.weld.annotated.enhanced.jlr.EnhancedAnnotationImpl;
import org.jboss.weld.annotated.slim.AnnotatedTypeIdentifier;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.annotated.slim.backed.BackedAnnotatedType;
import org.jboss.weld.annotated.slim.unbacked.UnbackedAnnotatedType;
import org.jboss.weld.bean.AbstractClassBean;
import org.jboss.weld.bootstrap.api.BootstrapService;
import org.jboss.weld.logging.BootstrapLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.metadata.TypeStore;
import org.jboss.weld.resources.spi.ResourceLoadingException;
import org.jboss.weld.util.AnnotatedTypes;
import org.jboss.weld.util.cache.ComputingCache;
import org.jboss.weld.util.cache.ComputingCacheBuilder;
import org.jboss.weld.util.reflection.Reflections;
/**
* @author Pete Muir
* @author Stuart Douglas
* @author JBoss Weld Community
* @author Ales Justin
*/
public class ClassTransformer implements BootstrapService {
public static ClassTransformer instance(BeanManagerImpl manager) {
return manager.getServices().get(ClassTransformer.class);
}
private class TransformClassToWeldAnnotation implements Function, EnhancedAnnotation>> {
@Override
public EnhancedAnnotation> apply(Class extends Annotation> from) {
SlimAnnotatedType extends Annotation> slimAnnotatedType = syntheticAnnotationsAnnotatedTypes.get(from);
if (slimAnnotatedType == null) {
// We do not recognize the BDA that defined the annotation This could in theory cause problem is two
// annotations with the same name but different definition are defined within the same application (different
// BDAs)
slimAnnotatedType = getBackedAnnotatedType(from, AnnotatedTypeIdentifier.NULL_BDA_ID);
}
return EnhancedAnnotationImpl.create(slimAnnotatedType, ClassTransformer.this);
}
}
private class TransformClassToBackedAnnotatedType implements Function, BackedAnnotatedType>> {
@Override
public BackedAnnotatedType> apply(TypeHolder> typeHolder) {
// make sure declaring class (if any) is loadable before loading this class
Reflections.checkDeclaringClassLoadable(typeHolder.getRawType());
BackedAnnotatedType> type = BackedAnnotatedType.of(typeHolder.getRawType(), typeHolder.getBaseType(), cache,
reflectionCache, contextId, typeHolder.getBdaId(), typeHolder.getSuffix());
return updateLookupTable(type);
}
}
private class TransformSlimAnnotatedTypeToEnhancedAnnotatedType implements Function, EnhancedAnnotatedType>> {
@Override
public EnhancedAnnotatedType> apply(SlimAnnotatedType> annotatedType) {
return EnhancedAnnotatedTypeImpl.of(annotatedType, ClassTransformer.this);
}
}
private static final class TypeHolder {
private final String bdaId;
private final Class rawType;
private final Type baseType;
private final String suffix;
private TypeHolder(Class rawType, Type baseType, String bdaId, String suffix) {
this.rawType = rawType;
this.baseType = baseType;
this.bdaId = bdaId;
this.suffix = suffix;
}
Type getBaseType() {
return baseType;
}
Class getRawType() {
return rawType;
}
String getBdaId() {
return bdaId;
}
String getSuffix() {
return suffix;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TypeHolder>) {
TypeHolder> that = (TypeHolder>) obj;
return Objects.equals(this.getBaseType(), that.getBaseType()) && Objects.equals(this.getBdaId(), that.getBdaId()) && Objects.equals(this.getSuffix(), that.getSuffix());
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(this.getBaseType(), this.getBdaId(), this.getSuffix());
}
@Override
public String toString() {
return "TypeHolder [bdaId=" + bdaId + ", rawType=" + rawType + ", baseType=" + baseType + ", suffix=" + suffix + "]";
}
}
// The synthetic annotations map (annotation type -> annotated type)
private final ConcurrentMap, UnbackedAnnotatedType extends Annotation>> syntheticAnnotationsAnnotatedTypes = new ConcurrentHashMap, UnbackedAnnotatedType extends Annotation>>();
private final ConcurrentMap> slimAnnotatedTypesById;
private final ComputingCache, BackedAnnotatedType>> backedAnnotatedTypes;
private final ComputingCache, EnhancedAnnotatedType>> enhancedAnnotatedTypes;
private final ComputingCache, EnhancedAnnotation>> annotations;
private final TypeStore typeStore;
private final SharedObjectCache cache;
private final ReflectionCache reflectionCache;
private final String contextId;
public ClassTransformer(TypeStore typeStore, SharedObjectCache cache, ReflectionCache reflectionCache, String contextId) {
this.contextId = contextId;
this.backedAnnotatedTypes = ComputingCacheBuilder.newBuilder().setWeakValues().build(new TransformClassToBackedAnnotatedType());
this.enhancedAnnotatedTypes = ComputingCacheBuilder.newBuilder().build(new TransformSlimAnnotatedTypeToEnhancedAnnotatedType());
this.annotations = ComputingCacheBuilder.newBuilder().build(new TransformClassToWeldAnnotation());
this.typeStore = typeStore;
this.cache = cache;
this.reflectionCache = reflectionCache;
this.slimAnnotatedTypesById = new ConcurrentHashMap>();
}
// Slim AnnotatedTypes
public BackedAnnotatedType getBackedAnnotatedType(final Class rawType, final Type baseType, final String bdaId, final String suffix) {
try {
return backedAnnotatedTypes.getCastValue(new TypeHolder(rawType, baseType, bdaId, suffix));
} catch (RuntimeException e) {
if (e instanceof TypeNotPresentException || e instanceof ResourceLoadingException) {
BootstrapLogger.LOG.exceptionWhileLoadingClass(rawType.getName(), e);
throw new ResourceLoadingException("Exception while loading class " + rawType.getName(), e);
}
throw e;
} catch (Error e) {
if(e instanceof NoClassDefFoundError || e instanceof LinkageError) {
throw new ResourceLoadingException("Error while loading class " + rawType.getName(), e);
}
BootstrapLogger.LOG.errorWhileLoadingClass(rawType.getName(), e);
throw e;
}
}
public BackedAnnotatedType getBackedAnnotatedType(final Class rawType, final String bdaId) {
return getBackedAnnotatedType(rawType, rawType, bdaId, null);
}
public BackedAnnotatedType getBackedAnnotatedType(Class rawType, String bdaId, String suffix) {
return getBackedAnnotatedType(rawType, rawType, bdaId, suffix);
}
public SlimAnnotatedType getSlimAnnotatedTypeById(AnnotatedTypeIdentifier id) {
return cast(slimAnnotatedTypesById.get(id));
}
public UnbackedAnnotatedType getUnbackedAnnotatedType(AnnotatedType source, String bdaId, String suffix) {
UnbackedAnnotatedType type = UnbackedAnnotatedType.additionalAnnotatedType(contextId, source, bdaId, suffix, cache);
return updateLookupTable(type);
}
public UnbackedAnnotatedType getUnbackedAnnotatedType(SlimAnnotatedType originalType, AnnotatedType source) {
UnbackedAnnotatedType type = UnbackedAnnotatedType.modifiedAnnotatedType(originalType, source, cache);
return updateLookupTable(type);
}
public UnbackedAnnotatedType extends Annotation> getSyntheticAnnotationAnnotatedType(
Class extends Annotation> annotationType) {
return syntheticAnnotationsAnnotatedTypes.get(annotationType);
}
private > S updateLookupTable(S annotatedType) {
SlimAnnotatedType> previousValue = slimAnnotatedTypesById.putIfAbsent(annotatedType.getIdentifier(), annotatedType);
if (previousValue == null) {
return annotatedType;
} else {
return cast(previousValue);
}
}
// Enhanced AnnotatedTypes
public EnhancedAnnotatedType getEnhancedAnnotatedType(Class rawType, String bdaId) {
return getEnhancedAnnotatedType(getBackedAnnotatedType(rawType, bdaId));
}
public EnhancedAnnotatedType getEnhancedAnnotatedType(Class rawType, Type baseType, String bdaId) {
return getEnhancedAnnotatedType(getBackedAnnotatedType(rawType, baseType, bdaId, null));
}
public EnhancedAnnotatedType getEnhancedAnnotatedType(AnnotatedType annotatedType, String bdaId) {
if (annotatedType instanceof EnhancedAnnotatedType>) {
return cast(annotatedType);
}
if (annotatedType instanceof SlimAnnotatedType>) {
return cast(getEnhancedAnnotatedType((SlimAnnotatedType>) annotatedType));
}
return getEnhancedAnnotatedType(getUnbackedAnnotatedType(annotatedType, bdaId,
AnnotatedTypes.createTypeId(annotatedType)));
}
public EnhancedAnnotatedType getEnhancedAnnotatedType(SlimAnnotatedType annotatedType) {
return cast(enhancedAnnotatedTypes.getValue(annotatedType));
}
public EnhancedAnnotation getEnhancedAnnotation(final Class clazz) {
return annotations.getCastValue(clazz);
}
public void clearAnnotationData(Class extends Annotation> annotationClass) {
annotations.invalidate(annotationClass);
}
public TypeStore getTypeStore() {
return typeStore;
}
public SharedObjectCache getSharedObjectCache() {
return cache;
}
public ReflectionCache getReflectionCache() {
return reflectionCache;
}
/**
*
* @param annotation
*/
public void addSyntheticAnnotation(AnnotatedType extends Annotation> annotation, String bdaId) {
syntheticAnnotationsAnnotatedTypes.put(annotation.getJavaClass(),
getUnbackedAnnotatedType(annotation, bdaId, AnnotatedTypeIdentifier.SYNTHETIC_ANNOTATION_SUFFIX));
clearAnnotationData(annotation.getJavaClass());
}
public void disposeBackedAnnotatedType(Class rawType, String bdaId, String suffix) {
TypeHolder typeHolder = new TypeHolder<>(rawType, rawType, bdaId, suffix);
BackedAnnotatedType annotatedType = cast(this.backedAnnotatedTypes.getValueIfPresent(typeHolder));
if (annotatedType != null) {
this.backedAnnotatedTypes.invalidate(typeHolder);
this.slimAnnotatedTypesById.remove(annotatedType.getIdentifier());
this.enhancedAnnotatedTypes.invalidate(annotatedType);
}
}
@Override
public void cleanupAfterBoot() {
this.enhancedAnnotatedTypes.clear();
this.annotations.clear();
backedAnnotatedTypes.forEachValue((BackedAnnotatedType::clear));
this.backedAnnotatedTypes.clear();
}
@Override
public void cleanup() {
cleanupAfterBoot();
slimAnnotatedTypesById.clear();
syntheticAnnotationsAnnotatedTypes.clear();
}
public void removeAll(Set> removable) {
for (Bean> bean : removable) {
if (bean instanceof AbstractClassBean) {
slimAnnotatedTypesById.remove(((AbstractClassBean>) bean).getAnnotated().getIdentifier());
}
}
}
}