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

org.jboss.weld.resources.ClassTransformer Maven / Gradle / Ivy

There is a newer version: 3.0.0.Alpha1
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.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 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 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();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy