Package org.aspectj.internal.lang.reflect

Source Code of org.aspectj.internal.lang.reflect.AjTypeImpl

/* *******************************************************************
* Copyright (c) 2005 Contributors.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://eclipse.org/legal/epl-v10.html
* Contributors:
*   Adrian Colyer      Initial implementation
* ******************************************************************/
package org.aspectj.internal.lang.reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

import org.aspectj.internal.lang.annotation.ajcDeclareAnnotation;
import org.aspectj.internal.lang.annotation.ajcDeclareEoW;
import org.aspectj.internal.lang.annotation.ajcDeclareParents;
import org.aspectj.internal.lang.annotation.ajcDeclarePrecedence;
import org.aspectj.internal.lang.annotation.ajcDeclareSoft;
import org.aspectj.internal.lang.annotation.ajcITD;
import org.aspectj.internal.lang.annotation.ajcPrivileged;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareError;
import org.aspectj.lang.annotation.DeclareWarning;
import org.aspectj.lang.reflect.Advice;
import org.aspectj.lang.reflect.AdviceKind;
import org.aspectj.lang.reflect.AjType;
import org.aspectj.lang.reflect.AjTypeSystem;
import org.aspectj.lang.reflect.DeclareAnnotation;
import org.aspectj.lang.reflect.DeclareErrorOrWarning;
import org.aspectj.lang.reflect.DeclareParents;
import org.aspectj.lang.reflect.DeclarePrecedence;
import org.aspectj.lang.reflect.DeclareSoft;
import org.aspectj.lang.reflect.InterTypeConstructorDeclaration;
import org.aspectj.lang.reflect.InterTypeFieldDeclaration;
import org.aspectj.lang.reflect.InterTypeMethodDeclaration;
import org.aspectj.lang.reflect.NoSuchAdviceException;
import org.aspectj.lang.reflect.NoSuchPointcutException;
import org.aspectj.lang.reflect.PerClause;
import org.aspectj.lang.reflect.PerClauseKind;
import org.aspectj.lang.reflect.Pointcut;


/**
* @author colyer
*
*/
public class AjTypeImpl<T> implements AjType<T> {
 
  private static final String ajcMagic = "ajc$";
 
  private Class<T> clazz;
  private Pointcut[] declaredPointcuts = null;
  private Pointcut[] pointcuts = null;
  private Advice[] declaredAdvice = null;
  private Advice[] advice = null;
  private InterTypeMethodDeclaration[] declaredITDMethods = null;
  private InterTypeMethodDeclaration[] itdMethods = null;
  private InterTypeFieldDeclaration[] declaredITDFields = null;
  private InterTypeFieldDeclaration[] itdFields = null;
  private InterTypeConstructorDeclaration[] itdCons = null;
  private InterTypeConstructorDeclaration[] declaredITDCons = null;
 
  public AjTypeImpl(Class<T> fromClass) {
    this.clazz = fromClass;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getName()
   */
  public String getName() {
    return clazz.getName();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getPackage()
   */
  public Package getPackage() {
    return clazz.getPackage();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getInterfaces()
   */
  public AjType<?>[] getInterfaces() {
    Class<?>[] baseInterfaces = clazz.getInterfaces();
    return toAjTypeArray(baseInterfaces);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getModifiers()
   */
  public int getModifiers() {
    return clazz.getModifiers();
  }
 
  public Class<T> getJavaClass() {
    return clazz;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getSupertype()
   */
  public AjType<? super T> getSupertype() {
    Class<? super T> superclass = clazz.getSuperclass();
    return superclass==null ? null : (AjType<? super T>) new AjTypeImpl(superclass);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getGenericSupertype()
   */
  public Type getGenericSupertype() {
    return clazz.getGenericSuperclass();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getEnclosingMethod()
   */
  public Method getEnclosingMethod() {
    return clazz.getEnclosingMethod();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getEnclosingConstructor()
   */
  public Constructor getEnclosingConstructor() {
    return clazz.getEnclosingConstructor();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getEnclosingType()
   */
  public AjType<?> getEnclosingType() {
    Class<?> enc = clazz.getEnclosingClass();
    return enc != null ? new AjTypeImpl(enc) : null;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaringType()
   */
  public AjType<?> getDeclaringType() {
    Class dec = clazz.getDeclaringClass();
    return dec != null ? new AjTypeImpl(dec) : null;
  }
 
  public PerClause getPerClause() {
    if (isAspect()) {
      Aspect aspectAnn = clazz.getAnnotation(Aspect.class);
      String perClause = aspectAnn.value();
      if (perClause.equals("")) {
        if (getSupertype().isAspect()) {
          return getSupertype().getPerClause();
        }
        return new PerClauseImpl(PerClauseKind.SINGLETON);
      } else if (perClause.startsWith("perthis(")) {
        return new PointcutBasedPerClauseImpl(PerClauseKind.PERTHIS,perClause.substring("perthis(".length(),perClause.length() - 1));
      } else if (perClause.startsWith("pertarget(")) {
        return new PointcutBasedPerClauseImpl(PerClauseKind.PERTARGET,perClause.substring("pertarget(".length(),perClause.length() - 1));       
      } else if (perClause.startsWith("percflow(")) {
        return new PointcutBasedPerClauseImpl(PerClauseKind.PERCFLOW,perClause.substring("percflow(".length(),perClause.length() - 1));               
      } else if (perClause.startsWith("percflowbelow(")) {
        return new PointcutBasedPerClauseImpl(PerClauseKind.PERCFLOWBELOW,perClause.substring("percflowbelow(".length(),perClause.length() - 1));
      } else if (perClause.startsWith("pertypewithin")) {
        return new TypePatternBasedPerClauseImpl(PerClauseKind.PERTYPEWITHIN,perClause.substring("pertypewithin(".length(),perClause.length() - 1));       
      } else {
        throw new IllegalStateException("Per-clause not recognized: " + perClause);
      }
    } else {
      return null;
    }
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isAnnotationPresent(java.lang.Class)
   */
  public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
    return clazz.isAnnotationPresent(annotationType);
  }

  public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
    return clazz.getAnnotation(annotationType);
  }
 
  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getAnnotations()
   */
  public Annotation[] getAnnotations() {
    return clazz.getAnnotations();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredAnnotations()
   */
  public Annotation[] getDeclaredAnnotations() {
    return clazz.getDeclaredAnnotations();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getAspects()
   */
  public AjType<?>[] getAjTypes() {
    Class[] classes = clazz.getClasses();
    return toAjTypeArray(classes);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredAspects()
   */
  public AjType<?>[] getDeclaredAjTypes() {
    Class[] classes = clazz.getDeclaredClasses();
    return toAjTypeArray(classes);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getConstructor(java.lang.Class...)
   */
  public Constructor getConstructor(AjType<?>... parameterTypes) throws NoSuchMethodException {
    return clazz.getConstructor(toClassArray(parameterTypes));
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getConstructors()
   */
  public Constructor[] getConstructors() {
    return clazz.getConstructors();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredConstructor(java.lang.Class...)
   */
  public Constructor getDeclaredConstructor(AjType<?>... parameterTypes) throws NoSuchMethodException {
    return clazz.getDeclaredConstructor(toClassArray(parameterTypes));
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredConstructors()
   */
  public Constructor[] getDeclaredConstructors() {
    return clazz.getDeclaredConstructors();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredField(java.lang.String)
   */
  public Field getDeclaredField(String name) throws NoSuchFieldException {
    Field f =  clazz.getDeclaredField(name);
    if (f.getName().startsWith(ajcMagic)) throw new NoSuchFieldException(name);
    return f;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredFields()
   */
  public Field[] getDeclaredFields() {
    Field[] fields = clazz.getDeclaredFields();
    List<Field> filteredFields = new ArrayList<Field>();
    for (Field field : fields)
      if (!field.getName().startsWith(ajcMagic)
        && !field.isAnnotationPresent(DeclareWarning.class)
        && !field.isAnnotationPresent(DeclareError.class)) {
        filteredFields.add(field);
      }
    Field[] ret = new Field[filteredFields.size()];
    filteredFields.toArray(ret);
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getField(java.lang.String)
   */
  public Field getField(String namethrows NoSuchFieldException {
    Field f =  clazz.getField(name);
    if (f.getName().startsWith(ajcMagic)) throw new NoSuchFieldException(name);
    return f;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getFields()
   */
  public Field[] getFields() {
    Field[] fields = clazz.getFields();
    List<Field> filteredFields = new ArrayList<Field>();
    for (Field field : fields)
      if (!field.getName().startsWith(ajcMagic)
          && !field.isAnnotationPresent(DeclareWarning.class)
          && !field.isAnnotationPresent(DeclareError.class)) {
          filteredFields.add(field);
        }
    Field[] ret = new Field[filteredFields.size()];
    filteredFields.toArray(ret);
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredMethod(java.lang.String, java.lang.Class...)
   */
  public Method getDeclaredMethod(String name, AjType<?>... parameterTypes) throws NoSuchMethodException {
    Method m =  clazz.getDeclaredMethod(name,toClassArray(parameterTypes));
    if (!isReallyAMethod(m)) throw new NoSuchMethodException(name);
    return m;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getMethod(java.lang.String, java.lang.Class...)
   */
  public Method getMethod(String name, AjType<?>... parameterTypes) throws NoSuchMethodException {
    Method m =  clazz.getMethod(name,toClassArray(parameterTypes));
    if (!isReallyAMethod(m)) throw new NoSuchMethodException(name);
    return m;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredMethods()
   */
  public Method[] getDeclaredMethods() {
    Method[] methods = clazz.getDeclaredMethods();
    List<Method> filteredMethods = new ArrayList<Method>();
    for (Method method : methods) {
      if (isReallyAMethod(method)) filteredMethods.add(method);
    }
    Method[] ret = new Method[filteredMethods.size()];
    filteredMethods.toArray(ret);
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getMethods()
   */
  public Method[] getMethods() {
    Method[] methods = clazz.getMethods();
    List<Method> filteredMethods = new ArrayList<Method>();
    for (Method method : methods) {
      if (isReallyAMethod(method)) filteredMethods.add(method);
    }
    Method[] ret = new Method[filteredMethods.size()];
    filteredMethods.toArray(ret);
    return ret;
  }

  private boolean isReallyAMethod(Method method) {
    if (method.getName().startsWith(ajcMagic)) return false;
    if (method.getAnnotations().length==0) return true;
    if (method.isAnnotationPresent(org.aspectj.lang.annotation.Pointcut.class)) return false;
    if (method.isAnnotationPresent(Before.class)) return false;
    if (method.isAnnotationPresent(After.class)) return false;
    if (method.isAnnotationPresent(AfterReturning.class)) return false;
    if (method.isAnnotationPresent(AfterThrowing.class)) return false;
    if (method.isAnnotationPresent(Around.class)) return false;
    return true;
  }
 
  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredPointcut(java.lang.String)
   */
  public Pointcut getDeclaredPointcut(String name) throws NoSuchPointcutException {
    Pointcut[] pcs = getDeclaredPointcuts();
    for (Pointcut pc : pcs)
      if (pc.getName().equals(name)) return pc;
    throw new NoSuchPointcutException(name);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getPointcut(java.lang.String)
   */
  public Pointcut getPointcut(String name) throws NoSuchPointcutException {
    Pointcut[] pcs = getPointcuts();
    for (Pointcut pc : pcs)
      if (pc.getName().equals(name)) return pc;
    throw new NoSuchPointcutException(name);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredPointcuts()
   */
  public Pointcut[] getDeclaredPointcuts() {
    if (declaredPointcuts != null) return declaredPointcuts;
    List<Pointcut> pointcuts = new ArrayList<Pointcut>();
    Method[] methods = clazz.getDeclaredMethods();
    for (Method method : methods) {
      Pointcut pc = asPointcut(method);
      if (pc != null) pointcuts.add(pc);
    }
    Pointcut[] ret = new Pointcut[pointcuts.size()];
    pointcuts.toArray(ret);
    declaredPointcuts = ret;
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getPointcuts()
   */
  public Pointcut[] getPointcuts() {
    if (pointcuts != null) return pointcuts;
    List<Pointcut> pcuts = new ArrayList<Pointcut>();
    Method[] methods = clazz.getMethods();
    for (Method method : methods) {
      Pointcut pc = asPointcut(method);
      if (pc != null) pcuts.add(pc);
    }
    Pointcut[] ret = new Pointcut[pcuts.size()];
    pcuts.toArray(ret);
    pointcuts  = ret;
    return ret;
  }

  private Pointcut asPointcut(Method method) {
    org.aspectj.lang.annotation.Pointcut pcAnn = method.getAnnotation(org.aspectj.lang.annotation.Pointcut.class);
    if (pcAnn != null) {
      String name = method.getName();
      if (name.startsWith(ajcMagic)) {
        // extract real name
        int nameStart = name.indexOf("$$");
        name = name.substring(nameStart +2,name.length());
        int nextDollar = name.indexOf("$");
        if (nextDollar != -1) name = name.substring(0,nextDollar);
      }
      return new PointcutImpl(name,pcAnn.value(),method,AjTypeSystem.getAjType(method.getDeclaringClass()),pcAnn.argNames());
    } else {
      return null;
    }
  }
 
 
  public Advice[] getDeclaredAdvice(AdviceKind... ofType) {
    Set<AdviceKind> types;
    if (ofType.length == 0) {
      types = EnumSet.allOf(AdviceKind.class);
    } else {
      types = EnumSet.noneOf(AdviceKind.class);
      types.addAll(Arrays.asList(ofType));
    }
    return getDeclaredAdvice(types);
  }
 
  public Advice[] getAdvice(AdviceKind... ofType) {
    Set<AdviceKind> types;
    if (ofType.length == 0) {
      types = EnumSet.allOf(AdviceKind.class);
    } else {
      types = EnumSet.noneOf(AdviceKind.class);
      types.addAll(Arrays.asList(ofType));
    }
    return getAdvice(types);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredAdvice(org.aspectj.lang.reflect.AdviceType)
   */
  private Advice[] getDeclaredAdvice(Set ofAdviceTypes) {
    if (declaredAdvice == null) initDeclaredAdvice();
    List<Advice> adviceList = new ArrayList<Advice>();
    for (Advice a : declaredAdvice) {
      if (ofAdviceTypes.contains(a.getKind())) adviceList.add(a);
    }
    Advice[] ret = new Advice[adviceList.size()];
    adviceList.toArray(ret);
    return ret;
  }

  private void initDeclaredAdvice() {
    Method[] methods = clazz.getDeclaredMethods();
    List<Advice> adviceList = new ArrayList<Advice>();
    for (Method method : methods) {
      Advice advice = asAdvice(method);
      if (advice != null) adviceList.add(advice);
    }
    declaredAdvice = new Advice[adviceList.size()];
    adviceList.toArray(declaredAdvice);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredAdvice(org.aspectj.lang.reflect.AdviceType)
   */
  private Advice[] getAdvice(Set ofAdviceTypes) {
    if (advice == null) initAdvice();
    List<Advice> adviceList = new ArrayList<Advice>();
    for (Advice a : advice) {
      if (ofAdviceTypes.contains(a.getKind())) adviceList.add(a);
    }
    Advice[] ret = new Advice[adviceList.size()];
    adviceList.toArray(ret);
    return ret;
  }

  private void initAdvice() {
    Method[] methods = clazz.getMethods();
    List<Advice> adviceList = new ArrayList<Advice>();
    for (Method method : methods) {
      Advice advice = asAdvice(method);
      if (advice != null) adviceList.add(advice);
    }
    advice = new Advice[adviceList.size()];
    adviceList.toArray(advice);
  }


  public Advice getAdvice(String name) throws NoSuchAdviceException {
    if (name.equals("")) throw new IllegalArgumentException("use getAdvice(AdviceType...) instead for un-named advice");
    if (advice == null) initAdvice();
    for (Advice a : advice) {
      if (a.getName().equals(name)) return a;
    }
    throw new NoSuchAdviceException(name);
  }
 
  public Advice getDeclaredAdvice(String name) throws NoSuchAdviceException {
    if (name.equals("")) throw new IllegalArgumentException("use getAdvice(AdviceType...) instead for un-named advice");
    if (declaredAdvice == null) initDeclaredAdvice();
    for (Advice a : declaredAdvice) {
      if (a.getName().equals(name)) return a;
    }
    throw new NoSuchAdviceException(name);
  }
 
  private Advice asAdvice(Method method) {
    if (method.getAnnotations().length == 0) return null;
    Before beforeAnn = method.getAnnotation(Before.class);
    if (beforeAnn != null) return new AdviceImpl(method,beforeAnn.value(),AdviceKind.BEFORE);
    After afterAnn = method.getAnnotation(After.class);
    if (afterAnn != null) return new AdviceImpl(method,afterAnn.value(),AdviceKind.AFTER);
    AfterReturning afterReturningAnn = method.getAnnotation(AfterReturning.class);
    if (afterReturningAnn != null) {
      String pcExpr = afterReturningAnn.pointcut();
      if (pcExpr.equals("")) pcExpr = afterReturningAnn.value();
      return new AdviceImpl(method,pcExpr,AdviceKind.AFTER_RETURNING,afterReturningAnn.returning());
    }
    AfterThrowing afterThrowingAnn = method.getAnnotation(AfterThrowing.class);
    if (afterThrowingAnn != null) {
      String pcExpr = afterThrowingAnn.pointcut();
      if (pcExpr == null) pcExpr = afterThrowingAnn.value();
      return new AdviceImpl(method,pcExpr,AdviceKind.AFTER_THROWING,afterThrowingAnn.throwing());
    }
    Around aroundAnn = method.getAnnotation(Around.class);
    if (aroundAnn != null) return new AdviceImpl(method,aroundAnn.value(),AdviceKind.AROUND);
    return null;
  }
 
  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredITDMethod(java.lang.String, java.lang.Class, java.lang.Class...)
   */
  public InterTypeMethodDeclaration getDeclaredITDMethod(String name,
      AjType<?> target, AjType<?>... parameterTypes) throws NoSuchMethodException {
    InterTypeMethodDeclaration[] itdms = getDeclaredITDMethods();
    outer: for (InterTypeMethodDeclaration itdm : itdms) {
      try {
        if (!itdm.getName().equals(name)) continue;
        AjType<?> itdTarget = itdm.getTargetType();
        if (itdTarget.equals(target)) {
          AjType<?>[] ptypes = itdm.getParameterTypes();
          if (ptypes.length == parameterTypes.length) {
            for (int i = 0; i < ptypes.length; i++) {
              if (!ptypes[i].equals(parameterTypes[i]))
                continue outer;
            }
            return itdm;
          }
        }
      } catch (ClassNotFoundException cnf) {
        // just move on to the next one
      }
    }
    throw new NoSuchMethodException(name);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredITDMethods()
   */
  public InterTypeMethodDeclaration[] getDeclaredITDMethods() {
    if (this.declaredITDMethods == null) {
      List<InterTypeMethodDeclaration> itdms = new ArrayList<InterTypeMethodDeclaration>();
      Method[] baseMethods = clazz.getDeclaredMethods();
      for (Method m : baseMethods) {
        if (!m.getName().contains("ajc$interMethodDispatch1$")) continue;
        if (m.isAnnotationPresent(ajcITD.class)) {
          ajcITD ann = m.getAnnotation(ajcITD.class);
          InterTypeMethodDeclaration itdm =
            new InterTypeMethodDeclarationImpl(
                this,ann.targetType(),ann.modifiers(),
                ann.name(),m);
          itdms.add(itdm);
        }       
      }
      addAnnotationStyleITDMethods(itdms,false);
      this.declaredITDMethods = new InterTypeMethodDeclaration[itdms.size()];
      itdms.toArray(this.declaredITDMethods);
    }
    return this.declaredITDMethods;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getITDMethod(java.lang.String, java.lang.Class, java.lang.Class...)
   */
  public InterTypeMethodDeclaration getITDMethod(String name, AjType<?> target,
      AjType<?>... parameterTypes)
  throws NoSuchMethodException {
    InterTypeMethodDeclaration[] itdms = getITDMethods();
    outer: for (InterTypeMethodDeclaration itdm : itdms) {
      try {
        if (!itdm.getName().equals(name)) continue;
        AjType<?> itdTarget = itdm.getTargetType();
        if (itdTarget.equals(target)) {
          AjType<?>[] ptypes = itdm.getParameterTypes();
          if (ptypes.length == parameterTypes.length) {
            for (int i = 0; i < ptypes.length; i++) {
              if (!ptypes[i].equals(parameterTypes[i]))
                continue outer;
            }
            return itdm;
          }
        }
      } catch (ClassNotFoundException cnf) {
        // just move on to the next one
      }
    }
    throw new NoSuchMethodException(name);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getITDMethods()
   */
  public InterTypeMethodDeclaration[] getITDMethods() {
    if (this.itdMethods == null) {
      List<InterTypeMethodDeclaration> itdms = new ArrayList<InterTypeMethodDeclaration>();
      Method[] baseMethods = clazz.getDeclaredMethods();
      for (Method m : baseMethods) {
        if (!m.getName().contains("ajc$interMethod$")) continue;
        if (m.isAnnotationPresent(ajcITD.class)) {
          ajcITD ann = m.getAnnotation(ajcITD.class);
          if (!Modifier.isPublic(ann.modifiers())) continue;
          InterTypeMethodDeclaration itdm =
            new InterTypeMethodDeclarationImpl(
                this,ann.targetType(),ann.modifiers(),
                ann.name(),m);
          itdms.add(itdm);
        }       
      }
      addAnnotationStyleITDMethods(itdms,true);
      this.itdMethods = new InterTypeMethodDeclaration[itdms.size()];
      itdms.toArray(this.itdMethods);
    }
    return this.itdMethods;
  }
 
  private void addAnnotationStyleITDMethods(List<InterTypeMethodDeclaration> toList, boolean publicOnly) {
    if (isAspect()) {
            for (Field f : clazz.getDeclaredFields()) {
                if (!f.getType().isInterface()) continue;
                if (f.isAnnotationPresent(org.aspectj.lang.annotation.DeclareParents.class)) {
                  Class<org.aspectj.lang.annotation.DeclareParents> decPAnnClass = org.aspectj.lang.annotation.DeclareParents.class;
                  org.aspectj.lang.annotation.DeclareParents decPAnn = f.getAnnotation(decPAnnClass);
                     if (decPAnn.defaultImpl() == decPAnnClass) continue; // doesn't contribute members...
                    for (Method itdM : f.getType().getDeclaredMethods()) {
                        if (!Modifier.isPublic(itdM.getModifiers()) && publicOnly) continue;
                        InterTypeMethodDeclaration itdm = new InterTypeMethodDeclarationImpl(
                                    this, AjTypeSystem.getAjType(f.getType()), itdM,
                                    Modifier.PUBLIC
                        );
                        toList.add(itdm);
                    }
                }
            }
    }
  }

  private void addAnnotationStyleITDFields(List<InterTypeFieldDeclaration> toList, boolean publicOnly) {
        //AV: I think it is meaningless
        //@AJ decp is interface driven ie no field
    return;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredITDConstructor(java.lang.Class, java.lang.Class...)
   */
  public InterTypeConstructorDeclaration getDeclaredITDConstructor(
      AjType<?> target, AjType<?>... parameterTypes) throws NoSuchMethodException {
    InterTypeConstructorDeclaration[] itdcs = getDeclaredITDConstructors();
    outer: for (InterTypeConstructorDeclaration itdc : itdcs) {
      try {
        AjType<?> itdTarget = itdc.getTargetType();
        if (itdTarget.equals(target)) {
          AjType<?>[] ptypes = itdc.getParameterTypes();
          if (ptypes.length == parameterTypes.length) {
            for (int i = 0; i < ptypes.length; i++) {
              if (!ptypes[i].equals(parameterTypes[i]))
                continue outer;
            }
            return itdc;
          }
        }
      } catch (ClassNotFoundException cnf) {
        // just move on to the next one
      }
    }
    throw new NoSuchMethodException();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredITDConstructors()
   */
  public InterTypeConstructorDeclaration[] getDeclaredITDConstructors() {
    if (this.declaredITDCons == null) {
      List<InterTypeConstructorDeclaration> itdcs = new ArrayList<InterTypeConstructorDeclaration>();
      Method[] baseMethods = clazz.getDeclaredMethods();
      for (Method m : baseMethods) {
        if (!m.getName().contains("ajc$postInterConstructor")) continue;
        if (m.isAnnotationPresent(ajcITD.class)) {
          ajcITD ann = m.getAnnotation(ajcITD.class);
          InterTypeConstructorDeclaration itdc =
            new InterTypeConstructorDeclarationImpl(this,ann.targetType(),ann.modifiers(),m);
          itdcs.add(itdc);
        }       
      }
      this.declaredITDCons = new InterTypeConstructorDeclaration[itdcs.size()];
      itdcs.toArray(this.declaredITDCons);
    }
    return this.declaredITDCons;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getITDConstructor(java.lang.Class, java.lang.Class...)
   */
  public InterTypeConstructorDeclaration getITDConstructor(AjType<?> target,
      AjType<?>... parameterTypes) throws NoSuchMethodException {
    InterTypeConstructorDeclaration[] itdcs = getITDConstructors();
    outer: for (InterTypeConstructorDeclaration itdc : itdcs) {
      try {
        AjType<?> itdTarget = itdc.getTargetType();
        if (itdTarget.equals(target)) {
          AjType<?>[] ptypes = itdc.getParameterTypes();
          if (ptypes.length == parameterTypes.length) {
            for (int i = 0; i < ptypes.length; i++) {
              if (!ptypes[i].equals(parameterTypes[i]))
                continue outer;
            }
            return itdc;
          }
        }
      } catch (ClassNotFoundException cnf) {
        // just move on to the next one
      }
    }
    throw new NoSuchMethodException();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getITDConstructors()
   */
  public InterTypeConstructorDeclaration[] getITDConstructors() {
    if (this.itdCons == null) {
      List<InterTypeConstructorDeclaration> itdcs = new ArrayList<InterTypeConstructorDeclaration>();
      Method[] baseMethods = clazz.getMethods();
      for (Method m : baseMethods) {
        if (!m.getName().contains("ajc$postInterConstructor")) continue;
        if (m.isAnnotationPresent(ajcITD.class)) {
          ajcITD ann = m.getAnnotation(ajcITD.class);
          if (!Modifier.isPublic(ann.modifiers())) continue;
          InterTypeConstructorDeclaration itdc =
            new InterTypeConstructorDeclarationImpl(this,ann.targetType(),ann.modifiers(),m);
          itdcs.add(itdc);
        }       
      }
      this.itdCons = new InterTypeConstructorDeclaration[itdcs.size()];
      itdcs.toArray(this.itdCons);
    }
    return this.itdCons;  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredITDField(java.lang.String, java.lang.Class)
   */
  public InterTypeFieldDeclaration getDeclaredITDField(String name,
      AjType<?> target) throws NoSuchFieldException {
    InterTypeFieldDeclaration[] itdfs = getDeclaredITDFields();
    for (InterTypeFieldDeclaration itdf : itdfs) {
      if (itdf.getName().equals(name)) {
        try {
          AjType<?> itdTarget = itdf.getTargetType();
          if (itdTarget.equals(target)) return itdf;
        } catch (ClassNotFoundException cnfEx) {
          // move on to next field
        }       
      }
    }
    throw new NoSuchFieldException(name);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclaredITDFields()
   */
  public InterTypeFieldDeclaration[] getDeclaredITDFields() {
    List<InterTypeFieldDeclaration> itdfs = new ArrayList<InterTypeFieldDeclaration>();
    if (this.declaredITDFields == null) {
      Method[] baseMethods = clazz.getDeclaredMethods();
      for(Method m : baseMethods) {
        if (m.isAnnotationPresent(ajcITD.class)) {
          if (!m.getName().contains("ajc$interFieldInit")) continue;
          ajcITD ann = m.getAnnotation(ajcITD.class);
          String interFieldInitMethodName = m.getName();
          String interFieldGetDispatchMethodName =
            interFieldInitMethodName.replace("FieldInit","FieldGetDispatch");
          try {
            Method dispatch = clazz.getDeclaredMethod(interFieldGetDispatchMethodName, m.getParameterTypes());
            InterTypeFieldDeclaration itdf = new InterTypeFieldDeclarationImpl(
                this,ann.targetType(),ann.modifiers(),ann.name(),
                AjTypeSystem.getAjType(dispatch.getReturnType()),
                dispatch.getGenericReturnType());
            itdfs.add(itdf);
          } catch (NoSuchMethodException nsmEx) {
            throw new IllegalStateException("Can't find field get dispatch method for " + m.getName());
          }
        }
      }
      addAnnotationStyleITDFields(itdfs, false);
      this.declaredITDFields = new InterTypeFieldDeclaration[itdfs.size()];
      itdfs.toArray(this.declaredITDFields);
    }
    return this.declaredITDFields;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getITDField(java.lang.String, java.lang.Class)
   */
  public InterTypeFieldDeclaration getITDField(String name, AjType<?> target)
  throws NoSuchFieldException {
    InterTypeFieldDeclaration[] itdfs = getITDFields();
    for (InterTypeFieldDeclaration itdf : itdfs) {
      if (itdf.getName().equals(name)) {
        try {
          AjType<?> itdTarget = itdf.getTargetType();
          if (itdTarget.equals(target)) return itdf;
        } catch (ClassNotFoundException cnfEx) {
          // move on to next field
        }       
      }
    }
    throw new NoSuchFieldException(name);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getITDFields()
   */
  public InterTypeFieldDeclaration[] getITDFields() {
    List<InterTypeFieldDeclaration> itdfs = new ArrayList<InterTypeFieldDeclaration>();
    if (this.itdFields == null) {
      Method[] baseMethods = clazz.getMethods();
      for(Method m : baseMethods) {
        if (m.isAnnotationPresent(ajcITD.class)) {
          ajcITD ann = m.getAnnotation(ajcITD.class);
          if (!m.getName().contains("ajc$interFieldInit")) continue;
          if (!Modifier.isPublic(ann.modifiers())) continue;
          String interFieldInitMethodName = m.getName();
          String interFieldGetDispatchMethodName =
            interFieldInitMethodName.replace("FieldInit","FieldGetDispatch");
          try {
            Method dispatch = m.getDeclaringClass().getDeclaredMethod(interFieldGetDispatchMethodName, m.getParameterTypes());
            InterTypeFieldDeclaration itdf = new InterTypeFieldDeclarationImpl(
                this,ann.targetType(),ann.modifiers(),ann.name(),
                AjTypeSystem.getAjType(dispatch.getReturnType()),
                dispatch.getGenericReturnType());
            itdfs.add(itdf);
          } catch (NoSuchMethodException nsmEx) {
            throw new IllegalStateException("Can't find field get dispatch method for " + m.getName());
          }
        }
      }
      addAnnotationStyleITDFields(itdfs, true);
      this.itdFields = new InterTypeFieldDeclaration[itdfs.size()];
      itdfs.toArray(this.itdFields);
    }
    return this.itdFields;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclareErrorOrWarnings()
   */
  public DeclareErrorOrWarning[] getDeclareErrorOrWarnings() {
    List<DeclareErrorOrWarning> deows = new ArrayList<DeclareErrorOrWarning>();
    for (Field field : clazz.getDeclaredFields()) {
      try {
        if (field.isAnnotationPresent(DeclareWarning.class)) {
           DeclareWarning dw = field.getAnnotation(DeclareWarning.class);
           if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
             String message = (String) field.get(null);
             DeclareErrorOrWarningImpl deow = new DeclareErrorOrWarningImpl(dw.value(),message,false,this);
             deows.add(deow);
           }
        } else if (field.isAnnotationPresent(DeclareError.class)) {
           DeclareError de = field.getAnnotation(DeclareError.class);
           if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
             String message = (String) field.get(null);
             DeclareErrorOrWarningImpl deow = new DeclareErrorOrWarningImpl(de.value(),message,true,this);
             deows.add(deow);
           }        
        }
      } catch (IllegalArgumentException e) {
        // just move on to the next field
      } catch (IllegalAccessException e) {
        // just move on to the next field
      }
    }
    for (Method method : clazz.getDeclaredMethods()) {
      if (method.isAnnotationPresent(ajcDeclareEoW.class)) {
        ajcDeclareEoW deowAnn = method.getAnnotation(ajcDeclareEoW.class);
        DeclareErrorOrWarning deow = new DeclareErrorOrWarningImpl(deowAnn.pointcut(),deowAnn.message(),deowAnn.isError(),this);
        deows.add(deow);
      }
    }
    DeclareErrorOrWarning[] ret = new DeclareErrorOrWarning[deows.size()];
    deows.toArray(ret);
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclareParents()
   */
  public DeclareParents[] getDeclareParents() {
    List<DeclareParents> decps = new ArrayList<DeclareParents>();
    for (Method method : clazz.getDeclaredMethods()) {
      if (method.isAnnotationPresent(ajcDeclareParents.class)) {
        ajcDeclareParents decPAnn = method.getAnnotation(ajcDeclareParents.class);
        DeclareParentsImpl decp = new DeclareParentsImpl(
            decPAnn.targetTypePattern(),
            decPAnn.parentTypes(),
            decPAnn.isExtends(),
            this
            );
        decps.add(decp);
      }
    }
    addAnnotationStyleDeclareParents(decps);
    if (getSupertype().isAspect()) {
      decps.addAll(Arrays.asList(getSupertype().getDeclareParents()));
    }
    DeclareParents[] ret = new DeclareParents[decps.size()];
    decps.toArray(ret);
    return ret;
  }
 
  private void addAnnotationStyleDeclareParents(List<DeclareParents> toList) {
        for (Field f : clazz.getDeclaredFields()) {
            if (f.isAnnotationPresent(org.aspectj.lang.annotation.DeclareParents.class)) {
                if (!f.getType().isInterface()) continue;
                org.aspectj.lang.annotation.DeclareParents ann = f.getAnnotation(org.aspectj.lang.annotation.DeclareParents.class);
                String parentType = f.getType().getName();
                DeclareParentsImpl decp = new DeclareParentsImpl(
                        ann.value(),
                        parentType,
                        false,
                        this
                );
                toList.add(decp);
            }
        }
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclareSofts()
   */
  public DeclareSoft[] getDeclareSofts() {
    List<DeclareSoft> decs = new ArrayList<DeclareSoft>();
    for (Method method : clazz.getDeclaredMethods()) {
      if (method.isAnnotationPresent(ajcDeclareSoft.class)) {
        ajcDeclareSoft decSAnn = method.getAnnotation(ajcDeclareSoft.class);
        DeclareSoftImpl ds = new DeclareSoftImpl(
            this,
            decSAnn.pointcut(),
            decSAnn.exceptionType()
            );
        decs.add(ds);
      }
    }
    if (getSupertype().isAspect()) {
      decs.addAll(Arrays.asList(getSupertype().getDeclareSofts()));
    }
    DeclareSoft[] ret = new DeclareSoft[decs.size()];
    decs.toArray(ret);
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclareAnnotations()
   */
  public DeclareAnnotation[] getDeclareAnnotations() {
    List<DeclareAnnotation> decAs = new ArrayList<DeclareAnnotation>();
    for (Method method : clazz.getDeclaredMethods()) {
      if (method.isAnnotationPresent(ajcDeclareAnnotation.class)) {
        ajcDeclareAnnotation decAnn = method.getAnnotation(ajcDeclareAnnotation.class);
        // the target annotation is on this method...
        Annotation targetAnnotation = null;
        Annotation[] anns = method.getAnnotations();
        for (Annotation ann: anns) {
          if (ann.annotationType() != ajcDeclareAnnotation.class) {
            // this must be the one...
            targetAnnotation = ann;
            break;
          }
        }
        DeclareAnnotationImpl da = new DeclareAnnotationImpl(
            this,
            decAnn.kind(),
            decAnn.pattern(),
            targetAnnotation,
            decAnn.annotation()
            );
        decAs.add(da);
      }
    }
    if (getSupertype().isAspect()) {
      decAs.addAll(Arrays.asList(getSupertype().getDeclareAnnotations()));
    }
    DeclareAnnotation[] ret = new DeclareAnnotation[decAs.size()];
    decAs.toArray(ret);
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getDeclarePrecedence()
   */
  public DeclarePrecedence[] getDeclarePrecedence() {
    List<DeclarePrecedence> decps = new ArrayList<DeclarePrecedence>();
   
    // @AspectJ Style
    if (clazz.isAnnotationPresent(org.aspectj.lang.annotation.DeclarePrecedence.class)) {
      org.aspectj.lang.annotation.DeclarePrecedence ann =
        clazz.getAnnotation(org.aspectj.lang.annotation.DeclarePrecedence.class);
      DeclarePrecedenceImpl decp = new DeclarePrecedenceImpl(
          ann.value(),
          this
          );
      decps.add(decp);
    }
   
    // annotated code-style
    for (Method method : clazz.getDeclaredMethods()) {
      if (method.isAnnotationPresent(ajcDeclarePrecedence.class)) {
        ajcDeclarePrecedence decPAnn = method.getAnnotation(ajcDeclarePrecedence.class);
        DeclarePrecedenceImpl decp = new DeclarePrecedenceImpl(
            decPAnn.value(),
            this
            );
        decps.add(decp);
      }
    }
    if (getSupertype().isAspect()) {
      decps.addAll(Arrays.asList(getSupertype().getDeclarePrecedence()));
    }
    DeclarePrecedence[] ret = new DeclarePrecedence[decps.size()];
    decps.toArray(ret);
    return ret;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getEnumConstants()
   */
  public T[] getEnumConstants() {
    return clazz.getEnumConstants();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#getTypeParameters()
   */
  public TypeVariable<Class<T>>[] getTypeParameters() {
    return clazz.getTypeParameters();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isEnum()
   */
  public boolean isEnum() {
    return clazz.isEnum();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isInstance(java.lang.Object)
   */
  public boolean isInstance(Object o) {
    return clazz.isInstance(o);
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isInterface()
   */
  public boolean isInterface() {
    return clazz.isInterface();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isLocalClass()
   */
  public boolean isLocalClass() {
    return clazz.isLocalClass() && !isAspect();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isMemberClass()
   */
  public boolean isMemberClass() {
    return clazz.isMemberClass() && !isAspect();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isArray()
   */
  public boolean isArray() {
    return clazz.isArray();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isPrimitive()
   */
  public boolean isPrimitive() {
    return clazz.isPrimitive();
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isAspect()
   */
  public boolean isAspect() {
    return clazz.getAnnotation(Aspect.class) != null;
  }

  /* (non-Javadoc)
   * @see org.aspectj.lang.reflect.AjType#isMemberAspect()
   */
  public boolean isMemberAspect() {
    return clazz.isMemberClass() && isAspect();
  }

  public boolean isPrivileged() {
    return isAspect() && clazz.isAnnotationPresent(ajcPrivileged.class);
  }
 
  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof AjTypeImpl)) return false;
    AjTypeImpl other = (AjTypeImpl) obj;
    return other.clazz.equals(clazz);
  }
 
  @Override
  public int hashCode() {
    return clazz.hashCode();
  }
 
  private AjType<?>[] toAjTypeArray(Class<?>[] classes) {
    AjType<?>[] ajtypes = new AjType<?>[classes.length];
    for (int i = 0; i < ajtypes.length; i++) {
      ajtypes[i] = AjTypeSystem.getAjType(classes[i]);
    }
    return ajtypes;
  }
 
  private Class<?>[] toClassArray(AjType<?>[] ajTypes) {
    Class<?>[] classes = new Class<?>[ajTypes.length];
    for (int i = 0; i < classes.length; i++) {
      classes[i] = ajTypes[i].getJavaClass();
    }
    return classes;
  }
 
  public String toString() { return getName(); }

}
TOP

Related Classes of org.aspectj.internal.lang.reflect.AjTypeImpl

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.