org.jboss.weld.metadata.cache.MetaAnnotationStore 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.metadata.cache;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import javax.enterprise.inject.spi.Bean;
import javax.inject.Named;
import org.jboss.weld.bean.RIBean;
import org.jboss.weld.bootstrap.api.Service;
import org.jboss.weld.resolution.QualifierInstance;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.resources.SharedObjectCache;
import org.jboss.weld.util.cache.ComputingCache;
import org.jboss.weld.util.cache.ComputingCacheBuilder;
import org.jboss.weld.util.collections.ImmutableSet;
/**
* Metadata singleton for holding EJB metadata, scope models etc.
*
* @author Pete Muir
*/
public class MetaAnnotationStore implements Service {
private abstract static class AbstractMetaAnnotationFunction> implements
Function, M> {
private final ClassTransformer classTransformer;
private AbstractMetaAnnotationFunction(ClassTransformer classTransformer) {
this.classTransformer = classTransformer;
}
public ClassTransformer getClassTransformer() {
return classTransformer;
}
}
private static class StereotypeFunction extends AbstractMetaAnnotationFunction> {
public StereotypeFunction(ClassTransformer classTransformer) {
super(classTransformer);
}
@Override
public StereotypeModel apply(Class from) {
return new StereotypeModel(getClassTransformer().getEnhancedAnnotation(from));
}
}
private static class ScopeFunction extends AbstractMetaAnnotationFunction> {
public ScopeFunction(ClassTransformer classTransformer) {
super(classTransformer);
}
@Override
public ScopeModel apply(Class from) {
return new ScopeModel(getClassTransformer().getEnhancedAnnotation(from));
}
}
private static class QualifierFunction extends AbstractMetaAnnotationFunction> {
public QualifierFunction(ClassTransformer classTransformer) {
super(classTransformer);
}
@Override
public QualifierModel apply(Class from) {
return new QualifierModel(getClassTransformer().getEnhancedAnnotation(from));
}
}
private static class InterceptorBindingFunction extends AbstractMetaAnnotationFunction> {
public InterceptorBindingFunction(ClassTransformer classTransformer) {
super(classTransformer);
}
@Override
public InterceptorBindingModel apply(Class from) {
return new InterceptorBindingModel(getClassTransformer().getEnhancedAnnotation(from));
}
}
private static class QualifierInstanceFunction implements Function {
private final MetaAnnotationStore metaAnnotationStore;
private QualifierInstanceFunction(MetaAnnotationStore metaAnnotationStore) {
super();
this.metaAnnotationStore = metaAnnotationStore;
}
@Override
public QualifierInstance apply(Annotation key) {
return QualifierInstance.of(key, metaAnnotationStore);
}
}
// The stereotype models
private final ComputingCache, StereotypeModel> stereotypes;
// The scope models
private final ComputingCache, ScopeModel> scopes;
// The binding type models
private final ComputingCache, QualifierModel> qualifiers;
// the interceptor bindings
private final ComputingCache, InterceptorBindingModel> interceptorBindings;
private final ComputingCache qualifierInstanceCache;
private final SharedObjectCache sharedObjectCache;
public MetaAnnotationStore(ClassTransformer classTransformer) {
ComputingCacheBuilder cacheBuilder = ComputingCacheBuilder.newBuilder();
this.stereotypes = cacheBuilder.build(new StereotypeFunction(classTransformer));
this.scopes = cacheBuilder.build(new ScopeFunction(classTransformer));
this.qualifiers = cacheBuilder.build(new QualifierFunction(classTransformer));
this.interceptorBindings = cacheBuilder.build(new InterceptorBindingFunction(classTransformer));
this.qualifierInstanceCache = cacheBuilder.build(new QualifierInstanceFunction(this));
this.sharedObjectCache = classTransformer.getSharedObjectCache();
}
/**
* removes all data for an annotation class. This should be called after an
* annotation has been modified through the SPI
*/
public void clearAnnotationData(Class extends Annotation> annotationClass) {
stereotypes.invalidate(annotationClass);
scopes.invalidate(annotationClass);
qualifiers.invalidate(annotationClass);
interceptorBindings.invalidate(annotationClass);
}
/**
* Gets a stereotype model
*
* Adds the model if it is not present.
*
* @param The type
* @param stereotype The stereotype
* @return The stereotype model
*/
public StereotypeModel getStereotype(final Class stereotype) {
return stereotypes.getCastValue(stereotype);
}
/**
* Gets a scope model
*
* Adds the model if it is not present.
*
* @param The type
* @param scope The scope type
* @return The scope type model
*/
public ScopeModel getScopeModel(final Class scope) {
return scopes.getCastValue(scope);
}
/**
* Gets a binding type model.
*
* Adds the model if it is not present.
*
* @param The type
* @param bindingType The binding type
* @return The binding type model
*/
public QualifierModel getBindingTypeModel(final Class bindingType) {
return qualifiers.getCastValue(bindingType);
}
/**
*
* @param interceptorBinding
* @return
*/
public InterceptorBindingModel getInterceptorBindingModel(final Class interceptorBinding) {
return interceptorBindings.getCastValue(interceptorBinding);
}
/**
*
* @param annotation
* @return the qualifier instance for the given annotation, uses cache if possible
*/
public QualifierInstance getQualifierInstance(final Annotation annotation) {
return isCacheAllowed(annotation) ? qualifierInstanceCache.getValue(annotation) : QualifierInstance.of(annotation, this);
}
/**
*
* @param bean
* @return the set of qualifier instances for the given bean, uses caches if possible
*/
public Set getQualifierInstances(final Bean> bean) {
if (bean instanceof RIBean) {
return ((RIBean>) bean).getQualifierInstances();
}
return getQualifierInstances(bean.getQualifiers());
}
/**
*
* @param annotations
* @return the set of qualifier instances, uses caches if possible
*/
public Set getQualifierInstances(final Set annotations) {
if (annotations == null || annotations.isEmpty()) {
return Collections.emptySet();
}
ImmutableSet.Builder builder = ImmutableSet.builder();
boolean useSharedCache = true;
for (Annotation annotation : annotations) {
if (isCacheAllowed(annotation)) {
builder.add(qualifierInstanceCache.getValue(annotation));
} else {
builder.add(QualifierInstance.of(annotation, this));
// Don't use shared object cache if there's some qualifier instance which should not be cached
useSharedCache = false;
}
}
return useSharedCache ? sharedObjectCache.getSharedSet(builder.build()) : builder.build();
}
/**
* Gets a string representation
*
* @return A string representation
*/
@Override
public String toString() {
final String newLine = "\n";
StringBuilder buffer = new StringBuilder();
buffer.append("Metadata cache").append(newLine);
buffer.append("Registered binding type models: ").append(qualifiers.size()).append(newLine);
buffer.append("Registered scope type models: ").append(scopes.size()).append(newLine);
buffer.append("Registered stereotype models: ").append(stereotypes.size()).append(newLine);
buffer.append("Registered interceptor binding models: ").append(interceptorBindings.size()).append(newLine);
buffer.append("Cached qualifier instances: ").append(qualifierInstanceCache.size()).append(newLine);
return buffer.toString();
}
@Override
public void cleanup() {
this.qualifiers.clear();
this.scopes.clear();
this.stereotypes.clear();
this.interceptorBindings.clear();
this.qualifierInstanceCache.clear();
}
private static boolean isCacheAllowed(Annotation annotation) {
if (annotation.annotationType().equals(Named.class)) {
// Don't cache @Named with non-default value.
Named named = (Named) annotation;
return named.value().equals("");
}
return true;
}
}