com.caucho.config.inject.ProducesBuilder Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.config.inject;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Logger;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.Specializes;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Qualifier;
import com.caucho.config.ConfigException;
import com.caucho.config.Names;
import com.caucho.config.program.Arg;
import com.caucho.config.program.BeanArg;
import com.caucho.config.reflect.AnnotatedTypeUtil;
import com.caucho.config.reflect.BaseType;
import com.caucho.inject.Module;
import com.caucho.util.L10N;
/**
* Builder for produces beans.
*/
@Module
public class ProducesBuilder {
private static final Logger log = Logger.getLogger(ProducesBuilder.class.getName());
private static final L10N L = new L10N(ProducesBuilder.class);
private InjectManager _manager;
public ProducesBuilder(InjectManager manager)
{
_manager = manager;
}
/**
* Introspects the methods for any @Produces
*/
public void introspectProduces(Bean bean,
AnnotatedType beanType)
{
HashSet> disposesSet
= new HashSet>();
for (AnnotatedMethod super X> beanMethod : beanType.getMethods()) {
if (beanMethod.isAnnotationPresent(Produces.class)) {
AnnotatedMethod super X> disposesMethod
= findDisposesMethod(beanType,
beanMethod.getBaseType(),
getQualifiers(beanMethod));
addProducesMethod(bean, beanType, beanMethod, disposesMethod);
if (disposesMethod != null)
disposesSet.add(disposesMethod);
}
}
for (AnnotatedField super X> beanField : beanType.getFields()) {
if (beanField.isAnnotationPresent(Produces.class)) {
AnnotatedMethod> disposesMethod
= findDisposesMethod(beanType, beanField.getBaseType(),
getQualifiers(beanField));
addProduces(bean, beanType, beanField);
if (disposesMethod != null)
disposesSet.add(disposesMethod);
}
}
for (AnnotatedMethod super X> beanMethod : beanType.getMethods()) {
if (isDisposes(beanMethod)
&& ! disposesSet.contains(beanMethod))
throw new ConfigException(L.l("{0}.{1} is an invalid disposes method because it doesn't match a @Produces method",
beanMethod.getJavaMember().getDeclaringClass().getName(),
beanMethod.getJavaMember().getName()));
}
}
protected void addProducesMethod(Bean bean,
AnnotatedType beanType,
AnnotatedMethod super X> producesMethod,
AnnotatedMethod super X> disposesMethod)
{
// ioc/07g2 vs ioc/07d0
/*
//
if (producesMethod.getJavaMember().getDeclaringClass() != beanType.getJavaClass()
&& ! beanType.isAnnotationPresent(Specializes.class)) {
return;
}
*/
Arg super X> []producesArgs = introspectArguments(bean, producesMethod);
Arg super X> []disposesArgs = null;
if (disposesMethod != null)
disposesArgs = introspectDisposesArgs(disposesMethod,
disposesMethod.getParameters());
ProducesMethodBean producesBean
= ProducesMethodBean.create(_manager, bean,
producesMethod, producesArgs,
disposesMethod, disposesArgs);
if (producesBean.isAlternative()
&& ! _manager.isEnabled(producesBean)) {
return;
}
// bean.init();
// _manager.addBean(producesBean);
_manager.addProducesBean(producesBean);
}
protected void addProduces(Bean bean,
AnnotatedType beanType,
AnnotatedField> beanField)
{
Class> beanClass = beanType.getJavaClass();
if (beanField.getJavaMember().getDeclaringClass() != beanClass
&& ! beanClass.isAnnotationPresent(Specializes.class))
return;
AnnotatedMethod super X> disposesMethod
= findDisposesMethod(beanType, beanField.getBaseType(),
getQualifiers(beanField));
Arg super X> []disposesArgs = null;
if (disposesMethod != null)
disposesArgs = introspectDisposesArgs(disposesMethod, disposesMethod.getParameters());
ProducesFieldBean producesFieldBean
= ProducesFieldBean.create(_manager, bean, beanField,
disposesMethod, disposesArgs);
// bean.init();
_manager.addProducesFieldBean(producesFieldBean);
}
private AnnotatedMethod super X>
findDisposesMethod(AnnotatedType beanType,
Type producesBaseType,
Annotation []qualifiers)
{
for (AnnotatedMethod super X> beanMethod : beanType.getMethods()) {
List> params = (List) beanMethod.getParameters();
if (params.size() == 0)
continue;
AnnotatedParameter> param = params.get(0);
if (! param.isAnnotationPresent(Disposes.class))
continue;
if (! producesBaseType.equals(param.getBaseType()))
continue;
Annotation []testQualifiers = getQualifiers(param);
if (! isQualifierMatch(qualifiers, testQualifiers))
continue;
// XXX: check @Qualifiers
Method javaMethod = beanMethod.getJavaMember();
if (beanMethod.isAnnotationPresent(Inject.class))
throw new ConfigException(L.l("{0}.{1} is an invalid @Disposes method because it has an @Inject annotation",
javaMethod.getDeclaringClass().getName(),
javaMethod.getName()));
return beanMethod;
}
return null;
}
protected Arg []introspectArguments(Bean bean,
AnnotatedMethod method)
{
List> params = method.getParameters();
Method javaMethod = method.getJavaMember();
Arg []args = new Arg[params.size()];
for (int i = 0; i < args.length; i++) {
AnnotatedParameter> param = params.get(i);
if (param.isAnnotationPresent(Disposes.class))
throw new ConfigException(L.l("'{0}.{1}' is an invalid producer method because a parameter is annotated with @Disposes",
javaMethod.getDeclaringClass().getName(),
javaMethod.getName()));
InjectionPoint ip = new InjectionPointImpl(_manager,
bean,
param);
if (InjectionPoint.class.equals(param.getBaseType()))
args[i] = new InjectionPointArg();
else
args[i] = new BeanArg(_manager,
param.getBaseType(),
getQualifiers(param),
ip);
}
return args;
}
protected Arg []introspectDisposesArgs(AnnotatedMethod> method,
List> params)
{
Arg []args = new Arg[params.size()];
boolean hasDisposes = false;
for (int i = 0; i < args.length; i++) {
AnnotatedParameter param = params.get(i);
InjectionPoint ip = null;
if (param.isAnnotationPresent(Disposes.class)) {
if (hasDisposes)
throw new ConfigException(L.l("{0}.{1} is an invalid @Disposes method because two parameters are marked @Disposes",
method.getJavaMember().getDeclaringClass().getName(),
method.getJavaMember().getName()));
hasDisposes = true;
args[i] = null;
}
else
args[i] = new BeanArg(_manager,
param.getBaseType(),
getQualifiers(param),
ip);
}
return args;
}
protected boolean isDisposes(AnnotatedMethod> method)
{
List> params = (List) method.getParameters();
for (int i = 0; i < params.size(); i++) {
AnnotatedParameter> param = params.get(i);
if (param.isAnnotationPresent(Disposes.class))
return true;
}
return false;
}
private boolean isQualifierMatch(Annotation []aList, Annotation []bList)
{
for (Annotation a : aList) {
if (! isQualifierPresent(a, bList))
return false;
}
return true;
}
private boolean isQualifierPresent(Annotation a, Annotation []list)
{
for (Annotation ann : list) {
if (! ann.annotationType().equals(a.annotationType()))
continue;
return true;
}
return false;
}
private Annotation []getQualifiers(Annotated annotated)
{
ArrayList qualifierList = new ArrayList();
for (Annotation ann : annotated.getAnnotations()) {
if (ann.annotationType().equals(Named.class)) {
Named named = (Named) ann;
String namedValue = named.value();
if ("".equals(namedValue)) {
BaseType baseType = AnnotatedTypeUtil.getBaseType(annotated);
String name = baseType.getRawClass().getSimpleName();
ann = Names.create(name);
}
qualifierList.add(ann);
}
else if (ann.annotationType().isAnnotationPresent(Qualifier.class)) {
qualifierList.add(ann);
}
}
if (qualifierList.size() == 0)
qualifierList.add(CurrentLiteral.CURRENT);
Annotation []qualifiers = new Annotation[qualifierList.size()];
qualifierList.toArray(qualifiers);
return qualifiers;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy