org.jboss.weld.resources.ClassTransformer Maven / Gradle / Ivy
/*
* 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 com.google.common.base.Function;
import com.google.common.collect.ComputationException;
import com.google.common.collect.MapMaker;
import org.jboss.weld.bootstrap.api.Service;
import org.jboss.weld.introspector.ForwardingAnnotatedType;
import org.jboss.weld.introspector.WeldAnnotation;
import org.jboss.weld.introspector.WeldClass;
import org.jboss.weld.introspector.jlr.WeldAnnotationImpl;
import org.jboss.weld.introspector.jlr.WeldClassImpl;
import org.jboss.weld.metadata.TypeStore;
import org.jboss.weld.resources.spi.ResourceLoadingException;
import javax.enterprise.inject.spi.AnnotatedType;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentMap;
import static org.jboss.weld.util.reflection.Reflections.cast;
public class ClassTransformer implements Service {
private static class TransformTypeToWeldClass implements Function, WeldClass>> {
private final ClassTransformer classTransformer;
private TransformTypeToWeldClass(ClassTransformer classTransformer) {
this.classTransformer = classTransformer;
}
public WeldClass> apply(TypeHolder> from) {
return WeldClassImpl.of(from.getRawType(), from.getBaseType(), classTransformer);
}
}
private static class TransformClassToWeldAnnotation implements Function, WeldAnnotation>> {
private final ClassTransformer classTransformer;
private TransformClassToWeldAnnotation(ClassTransformer classTransformer) {
this.classTransformer = classTransformer;
}
public WeldAnnotation> apply(Class extends Annotation> from) {
return WeldAnnotationImpl.of(from, classTransformer);
}
}
private static class TransformAnnotatedTypeToWeldClass implements Function, WeldClass>> {
private final ClassTransformer classTransformer;
private TransformAnnotatedTypeToWeldClass(ClassTransformer classTransformer) {
super();
this.classTransformer = classTransformer;
}
public WeldClass> apply(AnnotatedType> from) {
return WeldClassImpl.of(from, classTransformer);
}
}
private static final class TypeHolder {
private final Class rawType;
private final Type baseType;
private TypeHolder(Class rawType, Type baseType) {
this.rawType = rawType;
this.baseType = baseType;
}
public Type getBaseType() {
return baseType;
}
public Class getRawType() {
return rawType;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TypeHolder>) {
TypeHolder> that = (TypeHolder>) obj;
return this.getBaseType().equals(that.getBaseType());
} else {
return false;
}
}
@Override
public int hashCode() {
return getBaseType().hashCode();
}
@Override
public String toString() {
return getBaseType().toString();
}
}
private final ConcurrentMap, WeldClass>> classes;
private final ConcurrentMap, WeldClass>> annotatedTypes;
private final ConcurrentMap, WeldAnnotation>> annotations;
private final TypeStore typeStore;
public ClassTransformer(TypeStore typeStore) {
MapMaker maker = new MapMaker();
this.classes = maker.makeComputingMap(new TransformTypeToWeldClass(this));
this.annotatedTypes = maker.makeComputingMap(new TransformAnnotatedTypeToWeldClass(this));
this.annotations = maker.makeComputingMap(new TransformClassToWeldAnnotation(this));
this.typeStore = typeStore;
}
@SuppressWarnings("unchecked")
public WeldClass loadClass(final Class rawType, final Type baseType) {
try {
return (WeldClass) classes.get(new TypeHolder(rawType, baseType));
} catch (ComputationException e) {
if (e.getCause() instanceof NoClassDefFoundError || e.getCause() instanceof TypeNotPresentException || e.getCause() instanceof ResourceLoadingException || e.getCause() instanceof LinkageError) {
throw new ResourceLoadingException("Error loading class " + rawType.getName(), e.getCause());
} else {
throw e;
}
}
}
public WeldClass loadClass(final Class clazz) {
try {
return cast(classes.get(new TypeHolder(clazz, clazz)));
} catch (ComputationException e) {
if (e.getCause() instanceof NoClassDefFoundError || e.getCause() instanceof TypeNotPresentException || e.getCause() instanceof ResourceLoadingException || e.getCause() instanceof LinkageError) {
throw new ResourceLoadingException("Error loading class " + clazz.getName(), e.getCause());
} else {
throw e;
}
}
}
public void clearAnnotationData(Class extends Annotation> annotationClass) {
annotations.remove(annotationClass);
}
@SuppressWarnings("unchecked")
public WeldClass loadClass(final AnnotatedType clazz) {
// don't wrap existing weld class, dup instances!
if (clazz instanceof WeldClass) {
return (WeldClass) clazz;
} else if (clazz instanceof ForwardingAnnotatedType && ((ForwardingAnnotatedType) clazz).delegate() instanceof WeldClass) {
ForwardingAnnotatedType fat = (ForwardingAnnotatedType) clazz;
return (WeldClass) fat.delegate();
} else {
return (WeldClass) annotatedTypes.get(clazz);
}
}
@SuppressWarnings("unchecked")
public WeldAnnotation loadAnnotation(final Class clazz) {
return (WeldAnnotation) annotations.get(clazz);
}
public TypeStore getTypeStore() {
return typeStore;
}
public void cleanup() {
this.annotatedTypes.clear();
this.annotations.clear();
this.classes.clear();
}
}