Package org.jboss.weld.resources

Source Code of org.jboss.weld.resources.ClassTransformer$TypeHolder

/*
* 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.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;

import javax.enterprise.inject.spi.AnnotatedType;

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.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<Class<? extends Annotation>, EnhancedAnnotation<?>> {
        @Override
        public EnhancedAnnotation<?> apply(Class<? extends Annotation> from) {

            SlimAnnotatedType<? extends Annotation> slimAnnotatedType = syntheticAnnotationsAnnotatedTypes.get(from);

            if (slimAnnotatedType == null) {
                /*
                 * TODO: 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<TypeHolder<?>, 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());
            return updateLookupTable(type);
        }
    }

    private class TransformSlimAnnotatedTypeToEnhancedAnnotatedType implements Function<SlimAnnotatedType<?>, EnhancedAnnotatedType<?>> {
        @Override
        public EnhancedAnnotatedType<?> apply(SlimAnnotatedType<?> annotatedType) {
            return EnhancedAnnotatedTypeImpl.of(annotatedType, ClassTransformer.this);
        }
    }

    private static final class TypeHolder<T> {

        private final String bdaId;
        private final Class<T> rawType;
        private final Type baseType;

        private TypeHolder(Class<T> rawType, Type baseType, String bdaId) {
            this.rawType = rawType;
            this.baseType = baseType;
            this.bdaId = bdaId;
        }

        public Type getBaseType() {
            return baseType;
        }

        public Class<T> getRawType() {
            return rawType;
        }

        public String getBdaId() {
            return bdaId;
        }

        @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());
            }
            return false;
        }

        @Override
        public int hashCode() {
            return Objects.hash(this.getBaseType(), this.getBdaId());
        }

        @Override
        public String toString() {
            return getBaseType() + " from " + getBdaId();
        }
    }

    // The synthetic annotations map (annotation type -> annotated type)
    private final ConcurrentMap<Class<? extends Annotation>, UnbackedAnnotatedType<? extends Annotation>> syntheticAnnotationsAnnotatedTypes = new ConcurrentHashMap<Class<? extends Annotation>, UnbackedAnnotatedType<? extends Annotation>>();

    private final ConcurrentMap<AnnotatedTypeIdentifier, SlimAnnotatedType<?>> slimAnnotatedTypesById;

    private final ComputingCache<TypeHolder<?>, BackedAnnotatedType<?>> backedAnnotatedTypes;
    private final ComputingCache<SlimAnnotatedType<?>, EnhancedAnnotatedType<?>> enhancedAnnotatedTypes;
    private final ComputingCache<Class<? extends Annotation>, 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;

        ComputingCacheBuilder defaultBuilder = ComputingCacheBuilder.newBuilder();
        // if an AnnotatedType reference is not retained by a Bean we are not going to need it at runtime and can therefore drop
        // it immediately
        this.backedAnnotatedTypes = ComputingCacheBuilder.newBuilder().setWeakValues().build(new TransformClassToBackedAnnotatedType());
        this.enhancedAnnotatedTypes = ComputingCacheBuilder.newBuilder().buildReentrant(new TransformSlimAnnotatedTypeToEnhancedAnnotatedType());
        this.annotations = defaultBuilder.build(new TransformClassToWeldAnnotation());
        this.typeStore = typeStore;
        this.cache = cache;
        this.reflectionCache = reflectionCache;
        this.slimAnnotatedTypesById = new ConcurrentHashMap<AnnotatedTypeIdentifier, SlimAnnotatedType<?>>();
    }

    // Slim AnnotatedTypes

    public <T> BackedAnnotatedType<T> getBackedAnnotatedType(final Class<T> rawType, final Type baseType, final String bdaId) {
        try {
            return backedAnnotatedTypes.getCastValue(new TypeHolder<T>(rawType, baseType, bdaId));
        } 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 <T> BackedAnnotatedType<T> getBackedAnnotatedType(final Class<T> rawType, final String bdaId) {
        return getBackedAnnotatedType(rawType, rawType, bdaId);
    }

    public <T> SlimAnnotatedType<T> getSlimAnnotatedTypeById(AnnotatedTypeIdentifier id) {
        return cast(slimAnnotatedTypesById.get(id));
    }

    public <T> UnbackedAnnotatedType<T> getUnbackedAnnotatedType(AnnotatedType<T> source, String bdaId, String suffix) {
        UnbackedAnnotatedType<T> type = UnbackedAnnotatedType.additionalAnnotatedType(contextId, source, bdaId, suffix, cache);
        return updateLookupTable(type);
    }

    public <T> UnbackedAnnotatedType<T> getUnbackedAnnotatedType(SlimAnnotatedType<T> originalType, AnnotatedType<T> source) {
        UnbackedAnnotatedType<T> type = UnbackedAnnotatedType.modifiedAnnotatedType(originalType, source, cache);
        return updateLookupTable(type);
    }

    public UnbackedAnnotatedType<? extends Annotation> getSyntheticAnnotationAnnotatedType(
            Class<? extends Annotation> annotationType) {
        return syntheticAnnotationsAnnotatedTypes.get(annotationType);
    }

    private <T, S extends SlimAnnotatedType<T>> S updateLookupTable(S annotatedType) {
        SlimAnnotatedType<?> previousValue = slimAnnotatedTypesById.putIfAbsent(annotatedType.getIdentifier(), annotatedType);
        if (previousValue == null) {
            return annotatedType;
        } else {
            return cast(previousValue);
        }
    }

    // Enhanced AnnotatedTypes

    public <T> EnhancedAnnotatedType<T> getEnhancedAnnotatedType(Class<T> rawType, String bdaId) {
        return getEnhancedAnnotatedType(getBackedAnnotatedType(rawType, bdaId));
    }

    public <T> EnhancedAnnotatedType<T> getEnhancedAnnotatedType(Class<T> rawType, Type baseType, String bdaId) {
        return getEnhancedAnnotatedType(getBackedAnnotatedType(rawType, baseType, bdaId));
    }

    public <T> EnhancedAnnotatedType<T> getEnhancedAnnotatedType(AnnotatedType<T> 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 <T> EnhancedAnnotatedType<T> getEnhancedAnnotatedType(SlimAnnotatedType<T> annotatedType) {
        return cast(enhancedAnnotatedTypes.getValue(annotatedType));
    }

    public <T extends Annotation> EnhancedAnnotation<T> getEnhancedAnnotation(final Class<T> 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());
    }

    @Override
    public void cleanupAfterBoot() {
        this.enhancedAnnotatedTypes.clear();
        this.annotations.clear();
        for (BackedAnnotatedType<?> annotatedType : backedAnnotatedTypes.getAllPresent().values()) {
            annotatedType.clear();
        }
        this.backedAnnotatedTypes.clear();
    }

    @Override
    public void cleanup() {
        cleanupAfterBoot();
        slimAnnotatedTypesById.clear();
        syntheticAnnotationsAnnotatedTypes.clear();
    }
}
TOP

Related Classes of org.jboss.weld.resources.ClassTransformer$TypeHolder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
unction(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');