Package com.caucho.config.inject

Source Code of com.caucho.config.inject.ProducesBean

/*
* Copyright (c) 1998-2010 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.InvocationTargetException;
import java.lang.reflect.Method;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.NormalScope;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.CreationException;
import javax.enterprise.inject.IllegalProductException;
import javax.enterprise.inject.spi.AnnotatedMember;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.Producer;

import com.caucho.config.bytecode.ScopeAdapter;
import com.caucho.config.program.Arg;
import com.caucho.inject.Module;
import com.caucho.util.L10N;

/*
* Configuration for a @Produces method
*/
@Module
public class ProducesBean<X,T> extends AbstractIntrospectedBean<T>
  implements InjectionTarget<T>, ScopeAdapterBean<X>
{
  private static final L10N L = new L10N(ProducesBean.class);

  private static final Object []NULL_ARGS = new Object[0];

  private final Bean<X> _producerBean;
  private final AnnotatedMethod<X> _producesMethod;
  private final AnnotatedMethod<X> _disposesMethod;

  private Producer<T> _producer;

  // XXX: needs to be InjectionPoint
  private Arg []_args;

  private boolean _isBound;

  private Object _scopeAdapter;

  protected ProducesBean(InjectManager manager,
                         Bean<X> producerBean,
                         AnnotatedMethod<X> producesMethod,
                         Arg<?> []args,
                         AnnotatedMethod<X> disposesMethod)
  {
    super(manager, producesMethod.getBaseType(), producesMethod);

    _producerBean = producerBean;
    _producesMethod = producesMethod;
    _disposesMethod = disposesMethod;
   
    if (producesMethod != null)
      producesMethod.getJavaMember().setAccessible(true);
   
    if (disposesMethod != null)
      disposesMethod.getJavaMember().setAccessible(true);

    _args = args;

    if (producesMethod == null)
      throw new NullPointerException();

    if (args == null)
      throw new NullPointerException();
  }

  public static <X,T> ProducesBean<X,T>
  create(InjectManager manager,
         Bean<X> producer,
         AnnotatedMethod<X> producesMethod,
         Arg<?> []args,
         AnnotatedMethod<X> disposesMethod)
  {
    ProducesBean<X,T> bean = new ProducesBean<X,T>(manager, producer,
                                                   producesMethod, args,
                                                   disposesMethod);
    bean.introspect();
    bean.introspect(producesMethod);

    return bean;
  }

  public Producer<T> getProducer()
  {
    return _producer;
  }

  public void setProducer(Producer<T> producer)
  {
    _producer = producer;
  }

  /*
  protected AnnotatedMethod<T> getMethod()
  {
    return _producesMethod;
  }
  */

  /*
  protected Annotation []getAnnotationList()
  {
    return _annotationList;
  }

  protected void initDefault()
  {
    if (getDeploymentType() == null
        && _producer.getDeploymentType() != null) {
      setDeploymentType(_producer.getDeploymentType());
    }

    super.initDefault();
  }
  */

  /*
  protected Class getDefaultDeploymentType()
  {
    if (_producerBean.getDeploymentType() != null)
      return _producerBean.getDeploymentType();

    return null;// super.getDefaultDeploymentType();
  }
  */

  @Override
  protected String getDefaultName()
  {
    String methodName = _producesMethod.getJavaMember().getName();

    if (methodName.startsWith("get") && methodName.length() > 3) {
      return (Character.toLowerCase(methodName.charAt(3))
              + methodName.substring(4));
    }
    else
      return methodName;
  }

  public boolean isInjectionPoint()
  {
    for (Class<?> paramType : _producesMethod.getJavaMember().getParameterTypes()) {
      if (InjectionPoint.class.equals(paramType))
        return true;
    }

    return false;
  }

  /**
   * Returns the declaring bean
   */
  public Bean<X> getParentBean()
  {
    return _producerBean;
  }

  public T create(CreationalContext<T> createEnv)
  {
    return produce(createEnv);
  }

  public InjectionTarget<T> getInjectionTarget()
  {
    return this;
  }

  /**
   * Produces a new bean instance
   */
  public T produce(CreationalContext<T> cxt)
  {
    Class<?> type = _producerBean.getBeanClass();

    X factory = (X) getBeanManager().getReference(_producerBean, type, cxt);

    if (factory == null) {
      throw new IllegalStateException(L.l("{0}: unexpected null factory for {1}",
                                          this, _producerBean));
    }
   
    CreationalContextImpl<T> env = (CreationalContextImpl<T>) cxt;

    return produce(factory, env.getInjectionPoint());
  }

  /**
   * Produces a new bean instance
   */
  private T produce(X bean, InjectionPoint ij)
  {
    try {
      Object []args;

      if (_args.length > 0) {
        args = new Object[_args.length];

        InjectManager inject = getBeanManager();

        CreationalContext<?> env = inject.createCreationalContext(_producerBean);

        for (int i = 0; i < args.length; i++) {
          if (_args[i] instanceof InjectionPointArg<?>)
            args[i] = ij;
          else
            args[i] = _args[i].eval(env);
        }
      }
      else
        args = NULL_ARGS;

      // ioc/0084
      _producesMethod.getJavaMember().setAccessible(true);
     
      T value = (T) _producesMethod.getJavaMember().invoke(bean, args);
     
      if (value != null)
        return value;
     
      if (Dependent.class.equals(getScope()))
        return null;
     
      throw new IllegalProductException(L.l("producer {0} returned null, which is not allowed by the CDI spec.",
                                            this));
    } catch (RuntimeException e) {
      throw e;
    } catch (InvocationTargetException e) {
      if (e.getCause() instanceof RuntimeException)
        throw (RuntimeException) e.getCause();
      else
        throw new CreationException(e.getCause());
    } catch (Exception e) {
      throw new CreationException(e);
    }
  }

  /*
  @Override
  public X instantiate()
  {
    return createNew(null, null);
  }
  */

  @Override
  public X getScopeAdapter(Bean<?> topBean, CreationalContext<X> cxt)
  {
    NormalScope scopeType = getScope().getAnnotation(NormalScope.class);

    // ioc/0520
    if (scopeType != null
        && ! getScope().equals(ApplicationScoped.class)) {
      // && scopeType.normal()
      //  && ! env.canInject(getScope())) {

      Object value = _scopeAdapter;

      if (value == null) {
        ScopeAdapter scopeAdapter = ScopeAdapter.create(getBaseType().getRawClass());
        _scopeAdapter = scopeAdapter.wrap(getBeanManager(), topBean);
        value = _scopeAdapter;
      }

      return (X) value;
    }

    return null;
  }
 
  public void inject(T instance, CreationalContext<T> cxt)
  {
  }

  public void postConstruct(T instance)
  {
  }

  @Override
  public void bind()
  {
    synchronized (this) {
      if (_isBound)
        return;

      _isBound = true;

      Method method = _producesMethod.getJavaMember();

      String loc = InjectManager.location(method);

      // Annotation [][]paramAnn = _method.getParameterAnnotations();
      // List<AnnotatedParameter<T>> beanParams = _producesMethod.getParameters();

      /*
      _args = new Arg[param.length];

      for (int i = 0; i < param.length; i++) {
        _args[i] = bindParameter(loc, param[i], beanParams.get(i).getAnnotations());

        if (_args[i] != null) {
        }
        else if (InjectionPoint.class.equals(param[i])) {
          _args[i] = createInjectionPointBean(getManager());
        }
        else {
          throw error(_beanMethod.getJavaMember(),
                      L.l("Type '{0}' for method parameter #{1} has no matching component.",
                          getSimpleName(param[i]), i));
        }
      }
      */
    }
  }

  public Bean bindInjectionPoint(InjectionPoint ij)
  {
    return new ProducesInjectionPointBean(this, ij);
  }

  /**
   * Call destroy
   */
  @Override
  public void destroy(T instance, CreationalContext<T> cxt)
  {
    if (_disposesMethod != null) {
      try {
        CreationalContextImpl env = (CreationalContextImpl) cxt;
       
        Object producer = null;
       
        if (env != null)
          producer = env.get(_producerBean);
        else
          Thread.dumpStack();
       
        if (producer == null)
          producer = getBeanManager().getReference(_producerBean, _producerBean.getBeanClass(), cxt);
      
        _disposesMethod.getJavaMember().invoke(producer, instance);
      } catch (Exception e) {
        throw new RuntimeException(_disposesMethod.getJavaMember() + ":" + e, e);
      }
    }
  }

  /**
   * Disposes a bean instance
   */
  @Override
  public void preDestroy(T instance)
  {
  }

  /**
   * Returns the owning producer
   */
  public AnnotatedMember<X> getProducerMember()
  {
    throw new UnsupportedOperationException(getClass().getName());
  }

  /**
   * Returns the owning disposer
   */
  public AnnotatedMethod<X> getAnnotatedDisposer()
  {
    throw new UnsupportedOperationException(getClass().getName());
  }

  public AnnotatedParameter<X> getDisposedParameter()
  {
    throw new UnsupportedOperationException(getClass().getName());
  }

  public String toString()
  {
    StringBuilder sb = new StringBuilder();

    sb.append(getClass().getSimpleName());
    sb.append("[");

    Method method = _producesMethod.getJavaMember();

    sb.append(getTargetSimpleName());
    sb.append(", ");
    sb.append(method.getDeclaringClass().getSimpleName());
    sb.append(".");
    sb.append(method.getName());
    sb.append("()");

    sb.append(", {");

    boolean isFirst = true;
    for (Annotation ann : getQualifiers()) {
      if (! isFirst)
        sb.append(", ");

      sb.append(ann);

      isFirst = false;
    }

    sb.append("}");

    if (getName() != null) {
      sb.append(", name=");
      sb.append(getName());
    }

    sb.append("]");

    return sb.toString();
  }

}
TOP

Related Classes of com.caucho.config.inject.ProducesBean

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.