org.jboss.weld.resolution.ResolvableBuilder 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.resolution;
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.reflect.Executable;
import java.lang.reflect.Member;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.New;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InterceptionFactory;
import javax.enterprise.inject.spi.Interceptor;
import javax.inject.Named;
import javax.inject.Provider;
import org.jboss.weld.events.WeldEvent;
import org.jboss.weld.inject.WeldInstance;
import org.jboss.weld.literal.NamedLiteral;
import org.jboss.weld.logging.BeanManagerLogger;
import org.jboss.weld.logging.ResolutionLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.metadata.cache.MetaAnnotationStore;
import org.jboss.weld.util.reflection.Reflections;
public class ResolvableBuilder {
private static final Class>[] FACADE_TYPES = new Class>[] { Event.class, Instance.class, WeldEvent.class,
WeldInstance.class, Provider.class, InterceptionFactory.class };
private static final Class>[] METADATA_TYPES = new Class>[] { Interceptor.class, Decorator.class, Bean.class };
private static final Set ANY_SINGLETON = Collections.singleton(QualifierInstance.ANY);
protected Class> rawType;
protected final Set types;
protected final Set qualifierInstances;
protected Bean> declaringBean;
private final MetaAnnotationStore store;
protected boolean delegate;
public ResolvableBuilder(final MetaAnnotationStore store) {
this.store = store;
this.types = new HashSet();
this.qualifierInstances = new HashSet();
}
public ResolvableBuilder(BeanManagerImpl manager) {
this(manager.getServices().get(MetaAnnotationStore.class));
}
public ResolvableBuilder(Type type, final BeanManagerImpl beanManager) {
this(beanManager);
if (type != null) {
this.rawType = Reflections.getRawType(type);
if (rawType == null || type instanceof TypeVariable>) {
throw ResolutionLogger.LOG.cannotExtractRawType(type);
}
this.types.add(type);
}
}
public ResolvableBuilder(InjectionPoint injectionPoint, final BeanManagerImpl manager) {
this(injectionPoint.getType(), manager);
addQualifiers(injectionPoint.getQualifiers(), injectionPoint);
setDeclaringBean(injectionPoint.getBean());
this.delegate = injectionPoint.isDelegate();
}
public ResolvableBuilder setDeclaringBean(Bean> declaringBean) {
this.declaringBean = declaringBean;
return this;
}
public ResolvableBuilder addType(Type type) {
this.types.add(type);
return this;
}
public ResolvableBuilder addTypes(Set types) {
this.types.addAll(types);
return this;
}
public boolean isDelegate() {
return delegate;
}
public void setDelegate(boolean delegate) {
this.delegate = delegate;
}
public Resolvable create() {
if (qualifierInstances.isEmpty()) {
this.qualifierInstances.add(QualifierInstance.DEFAULT);
}
for (Type type : types) {
Class> rawType = Reflections.getRawType(type);
for (Class> facadeType : FACADE_TYPES) {
if (facadeType.equals(rawType)) {
return createFacade(facadeType);
}
}
for (Class> metadataType : METADATA_TYPES) {
if (metadataType.equals(rawType)) {
return createMetadataProvider(metadataType);
}
}
}
return new ResolvableImpl(rawType, types, declaringBean, qualifierInstances, delegate);
}
private Resolvable createFacade(Class> rawType) {
Set types = Collections.singleton(rawType);
return new ResolvableImpl(rawType, types, declaringBean, ANY_SINGLETON, delegate);
}
// just as facade but we keep the qualifiers so that we can recognize Bean from @Intercepted Bean.
private Resolvable createMetadataProvider(Class> rawType) {
Set types = Collections.singleton(rawType);
return new ResolvableImpl(rawType, types, declaringBean, qualifierInstances, delegate);
}
public ResolvableBuilder addQualifier(Annotation qualifier) {
return addQualifier(qualifier, null);
}
private ResolvableBuilder addQualifier(Annotation qualifier, InjectionPoint injectionPoint) {
QualifierInstance qualifierInstance = QualifierInstance.of(qualifier, store);
final Class extends Annotation> annotationType = qualifierInstance.getAnnotationClass();
// Handle the @New qualifier special case
if (annotationType.equals(New.class)) {
New newQualifier = New.class.cast(qualifier);
if (newQualifier.value().equals(New.class) && rawType == null) {
throw new IllegalStateException("Cannot transform @New when there is no known raw type");
} else if (newQualifier.value().equals(New.class)) {
qualifier = New.Literal.of(rawType);
qualifierInstance = QualifierInstance.of(qualifier, store);
}
} else if (injectionPoint != null && annotationType.equals(Named.class)) {
Named named = (Named) qualifier;
if (named.value().equals("")) {
// WELD-1739
// This is an injection point with an @Named qualifier, with no value specified, we need to assume the name of the field or parameter is the
// value
Member member = injectionPoint.getMember();
if (member instanceof Executable) {
// Method or constructor injection
Executable executable = (Executable) member;
AnnotatedParameter> annotatedParameter = (AnnotatedParameter>) injectionPoint.getAnnotated();
Parameter parameter = executable.getParameters()[annotatedParameter.getPosition()];
named = new NamedLiteral(parameter.getName());
} else {
named = new NamedLiteral(injectionPoint.getMember().getName());
}
qualifier = named;
qualifierInstance = QualifierInstance.of(named, store);
}
}
checkQualifier(qualifier, qualifierInstance, annotationType);
this.qualifierInstances.add(qualifierInstance);
return this;
}
/**
* Adds a given qualifier without any checks. This method should be used with care.
*/
public ResolvableBuilder addQualifierUnchecked(QualifierInstance qualifier) {
this.qualifierInstances.add(qualifier);
return this;
}
public ResolvableBuilder addQualifiers(Annotation[] qualifiers) {
for (Annotation qualifier : qualifiers) {
addQualifier(qualifier);
}
return this;
}
public ResolvableBuilder addQualifiers(Collection qualifiers) {
return addQualifiers(qualifiers, null);
}
private ResolvableBuilder addQualifiers(Collection qualifiers, InjectionPoint injectionPoint) {
for (Annotation qualifier : qualifiers) {
addQualifier(qualifier, injectionPoint);
}
return this;
}
protected void checkQualifier(Annotation qualifier, final QualifierInstance qualifierInstance, Class extends Annotation> annotationType) {
if (!store.getBindingTypeModel(annotationType).isValid()) {
throw BeanManagerLogger.LOG.invalidQualifier(qualifierInstance);
}
if (!annotationType.isAnnotationPresent(Repeatable.class)) {
for (QualifierInstance checkedQualifier : qualifierInstances) {
if (annotationType.equals(checkedQualifier.getAnnotationClass())) {
throw BeanManagerLogger.LOG.duplicateQualifiers(qualifierInstances);
}
}
}
}
protected static class ResolvableImpl implements Resolvable {
private final Set qualifierInstances;
private final Set typeClosure;
private final Class> rawType;
private final Bean> declaringBean;
private final boolean delegate;
private final int hashCode;
protected ResolvableImpl(Class> rawType, Set typeClosure, Bean> declaringBean, final Set qualifierInstances, boolean delegate) {
this.typeClosure = typeClosure;
this.rawType = rawType;
this.declaringBean = declaringBean;
this.qualifierInstances = qualifierInstances;
this.delegate = delegate;
this.hashCode = calculateHashCode();
}
@SuppressWarnings("checkstyle:magicnumber")
private int calculateHashCode() {
int hashCode = 17;
hashCode = 31 * hashCode + this.getTypes().hashCode();
return 31 * hashCode + this.qualifierInstances.hashCode();
}
@Override
public Set getQualifiers() {
return qualifierInstances;
}
@Override
public Set getTypes() {
return typeClosure;
}
@Override
public Class> getJavaClass() {
return rawType;
}
@Override
public Bean> getDeclaringBean() {
return declaringBean;
}
@Override
public String toString() {
return "Types: " + getTypes() + "; Bindings: " + getQualifiers();
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof ResolvableImpl) {
ResolvableImpl r = (ResolvableImpl) o;
return this.getTypes().equals(r.getTypes()) && this.qualifierInstances.equals(r.qualifierInstances);
}
return false;
}
@Override
public boolean isDelegate() {
return delegate;
}
}
protected MetaAnnotationStore getMetaAnnotationStore() {
return store;
}
}