Package com.caucho.config.inject

Source Code of com.caucho.config.inject.AbstractIntrospectedBean$AnnotationComparator

/*
* 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.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.context.Dependent;
import javax.enterprise.context.NormalScope;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Stereotype;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.PassivationCapable;
import javax.inject.Named;
import javax.inject.Qualifier;
import javax.inject.Scope;

import com.caucho.config.ConfigException;
import com.caucho.config.Names;
import com.caucho.config.reflect.BaseType;
import com.caucho.inject.Module;
import com.caucho.util.L10N;

/**
* Common bean introspection for Produces and ManagedBean.
*/
//  implements ObjectProxy
@Module
public class AbstractIntrospectedBean<T> extends AbstractBean<T>
  implements PassivationCapable, PassivationSetter
{
  private static final L10N L = new L10N(AbstractIntrospectedBean.class);
  private static final Logger log
    = Logger.getLogger(AbstractIntrospectedBean.class.getName());

  private static final HashSet<Class<?>> _reservedTypes
    = new HashSet<Class<?>>();

  public static final Annotation []CURRENT_ANN
    = new Annotation[] { CurrentLiteral.CURRENT };

  // AnnotatedType for ManagedBean, AnnotatedMethod for produces
  private Annotated _annotated;

  private BaseType _baseType;

  private Set<BaseType> _types;

  private Set<Type> _typeClasses;

  private ArrayList<Annotation> _qualifiers
    = new ArrayList<Annotation>();

  private Class<? extends Annotation> _scope;

  private ArrayList<Annotation> _stereotypes
    = new ArrayList<Annotation>();

  private String _name;

  private String _passivationId;

  public AbstractIntrospectedBean(InjectManager manager,
                                  Type type,
                                  Annotated annotated)
  {
    super(manager);
    _annotated = annotated;
   
    if (type instanceof Class<?>) {
      // ioc/024d
      _baseType = manager.createClassBaseType((Class<?>) type);
    }
    else
      _baseType = manager.createBaseType(type);
   
    _typeClasses = _baseType.getTypeClosure(manager);
  }

  public BaseType getBaseType()
  {
    return _baseType;
  }

  public Class<?> getBeanClass()
  {
    return _baseType.getRawClass();
  }

  public Type getTargetType()
  {
    return _baseType.toType();
  }

  public String getTargetSimpleName()
  {
    return _baseType.getSimpleName();
  }

  public String getTargetName()
  {
    return _baseType.toString();
  }

  public Class<?> getTargetClass()
  {
    return _baseType.getRawClass();
  }

  @Override
  public Annotated getAnnotated()
  {
    return _annotated;
  }

  /*
  protected AnnotatedType getAnnotatedType()
  {
    return  new BeanTypeImpl(getTargetType(), getIntrospectionClass());
  }
  */

  protected Class<?> getIntrospectionClass()
  {
    return getTargetClass();
  }

  /**
   * Gets the bean's EL qualifier name.
   */
  public String getName()
  {
    return _name;
  }

  /**
   * Returns the bean's qualifier types
   */
  public Set<Annotation> getQualifiers()
  {
    Set<Annotation> set = new LinkedHashSet<Annotation>();

    for (Annotation qualifier : _qualifiers) {
      set.add(qualifier);
    }

    return set;
  }

  public String getId()
  {
    if (_passivationId == null)
      _passivationId = calculatePassivationId();

    return _passivationId;
  }

  public void setPassivationId(String passivationId)
  {
    _passivationId = passivationId;
  }

  /**
   * Returns the bean's stereotypes
   */
  public Set<Class<? extends Annotation>> getStereotypes()
  {
    Set<Class<? extends Annotation>> set
      = new LinkedHashSet<Class<? extends Annotation>>();

    for (Annotation stereotype : _stereotypes) {
      set.add(stereotype.annotationType());
    }

    return set;
  }

  /**
   * Returns an array of the qualifier annotations
   */
  public Annotation []getQualifierArray()
  {
    if (_qualifiers == null || _qualifiers.size() == 0)
      return new Annotation[] { CurrentLiteral.CURRENT };

    Annotation []qualifiers = new Annotation[_qualifiers.size()];
    _qualifiers.toArray(qualifiers);

    return qualifiers;
  }

  /**
   * Returns the scope
   */
  @Override
  public Class<? extends Annotation> getScope()
  {
    return _scope;
  }

  /**
   * Returns the types that the bean implements
   */
  public Set<Type> getTypes()
  {
    return _typeClasses;
  }

  /**
   * Returns the types that the bean implements
   */
  public Set<BaseType> getGenericTypes()
  {
    return _types;
  }

  /**
   * Introspects all the types implemented by the class
   */
  protected void introspectTypes(Type type)
  {
    introspectTypes(type, null);
  }

  /**
   * Introspects all the types implemented by the class
   */
  private void introspectTypes(Type type, HashMap<String,BaseType> paramMap)
  {
    if (type == null || _reservedTypes.contains(type))
      return;
   
    BaseType baseType = addType(type, paramMap);

    if (baseType == null)
      return;

    HashMap<String,BaseType> newParamMap = baseType.getParamMap();
    Class<?> cl = baseType.getRawClass();

    introspectTypes(cl.getGenericSuperclass(), newParamMap);

    for (Type iface : cl.getGenericInterfaces()) {
      introspectTypes(iface, newParamMap);
    }
  }

  protected BaseType addType(Type type, HashMap<String,BaseType> paramMap)
  {
    BaseType baseType = BaseType.create(type, paramMap);

    if (baseType == null)
      return null;

    if (_types.contains(baseType))
      return null;

    _types.add(baseType);

    /*
    if (! _typeClasses.contains(baseType.getRawClass()))
      _typeClasses.add(baseType.getRawClass());
    */
    if (! _typeClasses.contains(baseType.toType()))
      _typeClasses.add(baseType.toType());

    return baseType;
  }

  public void introspect()
  {
    super.introspect();

    introspect(getIntrospectedAnnotated());
  }

  protected Annotated getIntrospectedAnnotated()
  {
    return _annotated;
  }

  protected void introspect(Annotated annotated)
  {
    introspectScope(annotated);
    introspectQualifiers(annotated);
    introspectName(annotated);
    introspectStereotypes(annotated);

    introspectDefault();
  }

  /**
   * Called for implicit introspection.
   */
  protected void introspectScope(Annotated annotated)
  {
    if (_scope != null)
      return;

    BeanManager inject = getBeanManager();

    for (Annotation ann : annotated.getAnnotations()) {
      if (inject.isScope(ann.annotationType())) {
        if (_scope != null && _scope != ann.annotationType())
          throw new ConfigException(L.l("{0}: @Scope annotation @{1} conflicts with @{2}.  Java Injection components may only have a single @Scope.",
                                        getTargetName(),
                                        _scope.getName(),
                                        ann.annotationType().getName()));

        _scope = ann.annotationType();
      }
    }
  }

  /**
   * Introspects the qualifier annotations
   */
  protected void introspectQualifiers(Annotated annotated)
  {
    if (_qualifiers.size() > 0)
      return;

    BeanManager inject = getBeanManager();

    for (Annotation ann : annotated.getAnnotations()) {
      if (inject.isQualifier(ann.annotationType())) {
        if (ann.annotationType().equals(Named.class)) {
          String namedValue = getNamedValue(ann);

          if ("".equals(namedValue)) {
            ann = Names.create(getDefaultName());
          }
        }

        _qualifiers.add(ann);
      }
    }
  }

  /**
   * Introspects the qualifier annotations
   */
  protected void introspectName(Annotated annotated)
  {
    if (_name != null)
      return;

    Annotation ann = annotated.getAnnotation(Named.class);

    if (ann != null) {
      String value = getNamedValue(ann);

      if (value == null)
        value = "";

      _name = value;
    }
  }

  /**
   * Adds the stereotypes from the bean's annotations
   */
  protected void introspectStereotypes(Annotated annotated)
  {
    Class<? extends Annotation> scope = null;

    for (Annotation stereotype : annotated.getAnnotations()) {
      Class<?> stereotypeType = stereotype.annotationType();

      if (stereotypeType.isAnnotationPresent(Stereotype.class))
        _stereotypes.add(stereotype);

      for (Annotation ann : stereotypeType.getDeclaredAnnotations()) {
        Class<? extends Annotation> annType = ann.annotationType();

        if (annType.isAnnotationPresent(Scope.class)
            || annType.isAnnotationPresent(NormalScope.class)) {
          if (_scope == null && scope != null && ! scope.equals(annType)) {
            throw new ConfigException(L.l("'{0}' is an invalid @Scope because a scope '{1}' has already been defined.  Only one @Scope or @NormalScope is allowed on a bean.",
                                          scope.getName(), annType.getName()));
          }

          scope = annType;
        }

        if (annType.equals(Named.class) && _name == null) {
          String namedValue = getNamedValue(ann);
          _name = "";

          if (! "".equals(namedValue))
            throw new ConfigException(L.l("@Named must not have a value in a @Stereotype definition, because @Stereotypes are used with multiple beans."));
        }

        if (annType.isAnnotationPresent(Qualifier.class)
            && ! annType.equals(Named.class)) {
          throw new ConfigException(L.l("'{0}' is not allowed on @Stereotype '{1}' because stereotypes may not have @Qualifier annotations",
                                        ann, stereotype));
        }
      }
    }

    if (_scope == null)
      _scope = scope;
}

  protected void introspectDefault()
  {
    // if (_qualifiers.size() == 0)
   
    // _qualifiers.add(AnyLiteral.ANY);
    boolean isQualifier = false;
    for (Annotation ann : _qualifiers) {
      if (! Named.class.equals(ann.annotationType())
          && ! Any.class.equals(ann.annotationType())) {
        isQualifier = true;
      }
    }
   
    if (! isQualifier)
      _qualifiers.add(DefaultLiteral.DEFAULT);
     
    _qualifiers.add(AnyLiteral.ANY);

    if (_scope == null)
      _scope = Dependent.class;

    if ("".equals(_name))
      _name = getDefaultName();
  }

  protected String getDefaultName()
  {
    String name = getTargetSimpleName();
   
    if ("".equals(name)) {
      log.info("TYPE:" + name + " " + this + " " + _baseType);
    }

    return Character.toLowerCase(name.charAt(0)) + name.substring(1);
  }

  protected void bind()
  {
  }

  /**
   * Returns true if the bean can be null
   */
  public boolean isNullable()
  {
    return false;
  }

  /**
   * Returns true if the bean is serializable
   */
  public boolean isPassivationCapable()
  {
    return Serializable.class.isAssignableFrom(getTargetClass());
  }

  /**
   * Instantiate the bean.
   */
  public T create(CreationalContext<T> env)
  {
    throw new UnsupportedOperationException(getClass().getName());
  }

  /**
   * Call destroy
   */
  @Override
  public void destroy(T instance, CreationalContext<T> env)
  {
  }

  /**
   * Call destroy
   */
  /*
  public void destroy(T instance)
  {
  }
  */

  /**
   * Inject the bean.
   */
/*
  public void inject(T instance)
  {
  }
*/

  /**
   * Call post-construct
   */
/*
  public void postConstruct(T instance)
  {
  }
*/

  /**
   * Call pre-destroy
   */
/*
  public void preDestroy(T instance)
  {
  }
*/

  public void dispose(T instance)
  {
  }

  /**
   * Returns the set of injection points, for validation.
   */
  public Set<InjectionPoint> getInjectionPoints()
  {
    return new HashSet<InjectionPoint>();
  }

  protected String getNamedValue(Annotation ann)
  {
    try {
      if (ann instanceof Named) {
        return ((Named) ann).value();
      }

      Method method = ann.getClass().getMethod("value");
      method.setAccessible(true);

      return (String) method.invoke(ann);
    } catch (NoSuchMethodException e) {
      // ioc/0m04
      log.log(Level.FINE, e.toString(), e);

      return "";
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

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

    sb.append(getTargetSimpleName());
    sb.append("[");

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

    for (Annotation qualifier : _qualifiers) {
      sb.append(",");
      sb.append(qualifier);
    }

    if (_scope != null && _scope != Dependent.class) {
      sb.append(", @");
      sb.append(_scope.getSimpleName());
    }

    sb.append("]");

    return sb.toString();
  }

  static class MethodNameComparator implements Comparator<AnnotatedMethod<?>> {
    public int compare(AnnotatedMethod<?> a, AnnotatedMethod<?> b)
    {
      return a.getJavaMember().getName().compareTo(b.getJavaMember().getName());
    }
  }

  static class AnnotationComparator implements Comparator<Annotation> {
    public int compare(Annotation a, Annotation b)
    {
      Class<?> annTypeA = a.annotationType();
      Class<?> annTypeB = b.annotationType();

      return annTypeA.getName().compareTo(annTypeB.getName());
    }
  }

  static {
    _reservedTypes.add(java.io.Closeable.class);
    _reservedTypes.add(java.io.Serializable.class);
    _reservedTypes.add(Cloneable.class);
    _reservedTypes.add(Object.class);
    _reservedTypes.add(Comparable.class);

    Method namedValueMethod = null;

    try {
      namedValueMethod = Named.class.getMethod("value");
      namedValueMethod.setAccessible(true);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
TOP

Related Classes of com.caucho.config.inject.AbstractIntrospectedBean$AnnotationComparator

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.