
org.apache.webbeans.component.creation.BeanAttributesBuilder Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.webbeans.component.creation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import javax.decorator.Decorator;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.NormalScope;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Specializes;
import javax.enterprise.inject.Typed;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMember;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.inject.Named;
import javax.inject.Scope;
import javax.interceptor.Interceptor;
import org.apache.webbeans.annotation.AnnotationManager;
import org.apache.webbeans.annotation.AnyLiteral;
import org.apache.webbeans.annotation.DefaultLiteral;
import org.apache.webbeans.annotation.NamedLiteral;
import org.apache.webbeans.component.BeanAttributesImpl;
import org.apache.webbeans.config.OWBLogConst;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.container.ExternalScope;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.logger.WebBeansLoggerFacade;
import org.apache.webbeans.portable.AbstractAnnotated;
import org.apache.webbeans.util.AnnotationUtil;
import org.apache.webbeans.util.Asserts;
import org.apache.webbeans.util.ClassUtil;
import org.apache.webbeans.util.WebBeansUtil;
/**
* Abstract implementation.
*
* @version $Rev$ $Date$
*
* @param bean class info
*/
public abstract class BeanAttributesBuilder
{
protected A annotated;
protected WebBeansContext webBeansContext;
protected Set types = new HashSet<>();
protected Set qualifiers = new HashSet<>();
protected Class extends Annotation> scope;
protected String name;
protected Set> stereotypes;
protected Boolean alternative;
public static BeanAttributesBuilderFactory forContext(WebBeansContext webBeansContext)
{
return new BeanAttributesBuilderFactory(webBeansContext);
}
/**
* Creates a bean instance.
*
* @param annotated
*/
protected BeanAttributesBuilder(WebBeansContext webBeansContext, A annotated)
{
this.annotated = annotated;
this.webBeansContext = webBeansContext;
}
public BeanAttributesBuilder alternative(boolean alternative)
{
this.alternative = alternative;
return this;
}
public BeanAttributesImpl build()
{
// we need to check the stereotypes first because we might need it to determine the scope
stereotypes = defineStereotypes(annotated);
defineScope();
if (scope == null)
{
// this indicates that we shall not use this AnnotatedType to create Beans from it.
return null;
}
defineTypes();
defineName();
defineQualifiers();
defineAlternative();
return new BeanAttributesImpl<>(types, qualifiers, scope, name, stereotypes, alternative);
}
protected A getAnnotated()
{
return annotated;
}
/**
* {@inheritDoc}
*/
protected void defineTypes()
{
Class> baseType = ClassUtil.getClass(annotated.getBaseType());
if (baseType.isArray())
{
// 3.3.1
types.add(Object.class);
types.add(baseType);
}
else
{
Typed beanTypes = annotated.getAnnotation(Typed.class);
if (beanTypes != null)
{
Class>[] typedTypes = beanTypes.value();
//New api types
Set newTypes = new HashSet<>();
for (Class> type : typedTypes)
{
Type foundType = null;
for (Type apiType : annotated.getTypeClosure())
{
if(ClassUtil.getClazz(apiType) == type)
{
foundType = apiType;
break;
}
}
if(foundType == null)
{
throw new WebBeansConfigurationException("@Type values must be in bean api types of class: " + baseType);
}
newTypes.add(foundType);
}
this.types.addAll(newTypes);
this.types.add(Object.class);
}
else
{
this.types.addAll(annotated.getTypeClosure());
}
Set ignored = webBeansContext.getOpenWebBeansConfiguration().getIgnoredInterfaces();
if (!ignored.isEmpty())
{
this.types.removeIf(t -> t instanceof Class && ignored.contains(((Class>) t).getName()));
}
}
}
/**
* {@inheritDoc}
*/
protected void
defineQualifiers()
{
HashSet> qualifiedTypes = new HashSet<>();
if (annotated.isAnnotationPresent(Specializes.class))
{
defineQualifiers(getSuperAnnotated(), qualifiedTypes);
}
defineQualifiers(annotated, qualifiedTypes);
}
private void defineQualifiers(Annotated annotated, Set> qualifiedTypes)
{
Annotation[] annotations = AnnotationUtil.asArray(annotated.getAnnotations());
AnnotationManager annotationManager = webBeansContext.getAnnotationManager();
for (Annotation annotation : annotations)
{
Class extends Annotation> type = annotation.annotationType();
if (annotationManager.isQualifierAnnotation(type))
{
annotationManager.checkQualifierConditions(annotation);
if (qualifiedTypes.contains(annotation.annotationType()) && !isRepetable(annotated, annotation))
{
continue;
}
else
{
qualifiedTypes.add(annotation.annotationType());
}
if (annotation.annotationType().equals(Named.class) && name != null)
{
qualifiers.add(new NamedLiteral(name));
}
else
{
qualifiers.add(annotation);
}
}
}
// No-binding annotation
if (qualifiers.isEmpty())
{
qualifiers.add(DefaultLiteral.INSTANCE);
}
else if (qualifiers.size() == 1)
{
// section 2.3.1
// If a bean does not explicitly declare a qualifier other than @Named or @Any,
// the bean has exactly one additional qualifier, of type @Default.
Annotation annot = qualifiers.iterator().next();
if(annot.annotationType().equals(Named.class) || annot.annotationType().equals(Any.class))
{
qualifiers.add(DefaultLiteral.INSTANCE);
}
}
else if (qualifiers.size() == 2)
{
Iterator qualiIt = qualifiers.iterator();
Class extends Annotation> q1 = qualiIt.next().annotationType();
Class extends Annotation> q2 = qualiIt.next().annotationType();
if (q1.equals(Named.class) && q2.equals(Any.class) ||
q2.equals(Named.class) && q1.equals(Any.class) )
{
qualifiers.add(DefaultLiteral.INSTANCE);
}
}
//Add @Any support
if(!hasAnyQualifier())
{
qualifiers.add(AnyLiteral.INSTANCE);
}
}
// we don't want to do the getRepeatableMethod() logic *again* if we can but we can need for custom AT
private boolean isRepetable(Annotated annotated, Annotation annotation)
{
return AbstractAnnotated.class.isInstance(annotated) ?
AbstractAnnotated.class.cast(annotated).getRepeatables().contains(annotation.annotationType()) :
webBeansContext.getAnnotationManager().getRepeatableMethod(annotation.annotationType()).isPresent();
}
/**
* Returns true if any binding exist
*
* @return true if any binding exist
*/
private boolean hasAnyQualifier()
{
return AnnotationUtil.getAnnotation(qualifiers, Any.class) != null;
}
protected abstract void defineScope();
protected void defineScope(String errorMessage)
{
defineScope(null, false, errorMessage);
}
protected void defineScope(Class> declaringClass, boolean onlyScopedBeans, String errorMessage)
{
Annotation[] annotations = AnnotationUtil.asArray(annotated.getAnnotations());
boolean found = false;
List additionalScopes = webBeansContext.getBeanManagerImpl().getAdditionalScopes();
for (Annotation annotation : annotations)
{
if (declaringClass != null && AnnotationUtil.getDeclaringClass(annotation, declaringClass) != null && !AnnotationUtil.isDeclaringClass(declaringClass, annotation))
{
continue;
}
Class extends Annotation> annotationType = annotation.annotationType();
if (!webBeansContext.getBeanManagerImpl().isScope(annotationType))
{
continue;
}
/*Normal scope*/
Annotation var = annotationType.getAnnotation(NormalScope.class);
/*Pseudo scope*/
Annotation pseudo = annotationType.getAnnotation(Scope.class);
if (var == null && pseudo == null)
{
// check for additional scopes registered via a CDI Extension
for (ExternalScope additionalScope : additionalScopes)
{
if (annotationType.equals(additionalScope.getScope()))
{
// create a proxy which implements the given annotation
Annotation scopeAnnotation = additionalScope.getScopeAnnotation();
if (additionalScope.isNormal())
{
var = scopeAnnotation;
}
else
{
pseudo = scopeAnnotation;
}
}
}
}
if (var != null)
{
if(pseudo != null)
{
throw new WebBeansConfigurationException("Not to define both @Scope and @NormalScope on bean : " + ClassUtil.getClass(annotated.getBaseType()).getName());
}
if (found)
{
throw new WebBeansConfigurationException(errorMessage);
}
found = true;
scope = annotation.annotationType();
}
else
{
if(pseudo != null)
{
if (found)
{
throw new WebBeansConfigurationException(errorMessage);
}
found = true;
scope = annotation.annotationType();
}
}
}
if (found && annotated.getAnnotation(Interceptor.class) != null && scope != Dependent.class)
{
throw new WebBeansConfigurationException("An Interceptor must declare any other Scope than @Dependent: " + ClassUtil.getClass(annotated.getBaseType()).getName());
}
if (found && annotated.getAnnotation(Decorator.class) != null && scope != Dependent.class)
{
throw new WebBeansConfigurationException("A Decorator must declare any other Scope than @Dependent: " + ClassUtil.getClass(annotated.getBaseType()).getName());
}
if (!found && declaringClass != null && !hasDeclaredNonInheritedScope(declaringClass))
{
defineScope(declaringClass.getSuperclass(), onlyScopedBeans, errorMessage);
}
else if (!found)
{
defineDefaultScope(errorMessage, onlyScopedBeans);
}
}
private void defineDefaultScope(String exceptionMessage, boolean onlyScopedBeans)
{
if (scope == null)
{
Set> stereos = stereotypes;
if (stereos != null && stereos.size() > 0)
{
Annotation defined = null;
Set> anns = stereotypes;
for (Class extends Annotation> stero : anns)
{
boolean containsNormal = AnnotationUtil.hasMetaAnnotation(stero.getDeclaredAnnotations(), NormalScope.class);
if (AnnotationUtil.hasMetaAnnotation(stero.getDeclaredAnnotations(), NormalScope.class) ||
AnnotationUtil.hasMetaAnnotation(stero.getDeclaredAnnotations(), Scope.class))
{
Annotation next;
if(containsNormal)
{
next = AnnotationUtil.getMetaAnnotations(stero.getDeclaredAnnotations(), NormalScope.class)[0];
}
else
{
next = AnnotationUtil.getMetaAnnotations(stero.getDeclaredAnnotations(), Scope.class)[0];
}
if (defined == null)
{
defined = next;
}
else
{
if (!defined.equals(next))
{
throw new WebBeansConfigurationException(exceptionMessage);
}
}
}
}
if (defined != null)
{
scope = defined.annotationType();
}
else
{
scope = Dependent.class;
}
}
if (scope == null)
{
if (annotated instanceof AnnotatedType)
{
Constructor
© 2015 - 2025 Weber Informatics LLC | Privacy Policy