Package org.aspectj.weaver.bcel

Source Code of org.aspectj.weaver.bcel.BcelField

/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* 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://www.eclipse.org/legal/epl-v10.html
* Contributors:
*     PARC     initial implementation
* ******************************************************************/

package org.aspectj.weaver.bcel;

import java.util.List;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.Synthetic;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
import org.aspectj.apache.bcel.generic.FieldGen;
import org.aspectj.util.GenericSignature;
import org.aspectj.util.GenericSignatureParser;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;

/**
* An AspectJ Field object that is backed by a Bcel Field object.
*
* @author PARC
* @author Andy Clement
*/
final class BcelField extends ResolvedMemberImpl {

  public static int AccSynthetic = 0x1000;

  private Field field;
  private boolean isAjSynthetic;
  private boolean isSynthetic = false;
  private AnnotationAJ[] annotations;
  private final World world;
  private final BcelObjectType bcelObjectType;
  private UnresolvedType genericFieldType = null;
  private boolean unpackedGenericSignature = false;
  private boolean annotationsOnFieldObjectAreOutOfDate = false;

  BcelField(BcelObjectType declaringType, Field field) {
    super(FIELD, declaringType.getResolvedTypeX(), field.getModifiers(), field.getName(), field.getSignature());
    this.field = field;
    this.world = declaringType.getResolvedTypeX().getWorld();
    this.bcelObjectType = declaringType;
    unpackAttributes(world);
    checkedExceptions = UnresolvedType.NONE;
  }

  /**
   * Constructs an instance that wrappers a Field object, but where we do not (yet) have a BcelObjectType - usually because the
   * containing type (and this field) are being constructed at runtime (so there is no .class file to retrieve).
   */
  BcelField(String declaringTypeName, Field field, World world) {
    super(FIELD, UnresolvedType.forName(declaringTypeName), field.getModifiers(), field.getName(), field.getSignature());
    this.field = field;
    this.world = world;
    this.bcelObjectType = null;
    unpackAttributes(world);
    checkedExceptions = UnresolvedType.NONE;
  }

  private void unpackAttributes(World world) {
    Attribute[] attrs = field.getAttributes();
    if (attrs != null && attrs.length > 0) {
      ISourceContext sourceContext = getSourceContext(world);
      List<AjAttribute> as = Utility.readAjAttributes(getDeclaringType().getClassName(), attrs, sourceContext, world,
          (bcelObjectType != null ? bcelObjectType.getWeaverVersionAttribute() : WeaverVersionInfo.CURRENT),
          new BcelConstantPoolReader(field.getConstantPool()));
      as.addAll(AtAjAttributes.readAj5FieldAttributes(field, this, world.resolve(getDeclaringType()), sourceContext,
          world.getMessageHandler()));

      // FIXME this code has no effect!!!??? it is set to false immediately after the block
      // for (AjAttribute a : as) {
      // if (a instanceof AjAttribute.AjSynthetic) {
      // isAjSynthetic = true;
      // } else {
      // throw new BCException("weird field attribute " + a);
      // }
      // }
    }
    isAjSynthetic = false;

    for (int i = attrs.length - 1; i >= 0; i--) {
      if (attrs[i] instanceof Synthetic) {
        isSynthetic = true;
      }
    }
    // in 1.5, synthetic is a modifier, not an attribute
    if ((field.getModifiers() & AccSynthetic) != 0) {
      isSynthetic = true;
    }

  }

  @Override
  public boolean isAjSynthetic() {
    return isAjSynthetic;
  }

  @Override
  public boolean isSynthetic() {
    return isSynthetic;
  }

  @Override
  public boolean hasAnnotation(UnresolvedType ofType) {
    ensureAnnotationTypesRetrieved();
    for (ResolvedType aType : annotationTypes) {
      if (aType.equals(ofType)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public ResolvedType[] getAnnotationTypes() {
    ensureAnnotationTypesRetrieved();
    return annotationTypes;
  }

  @Override
  public AnnotationAJ[] getAnnotations() {
    ensureAnnotationTypesRetrieved();
    return annotations;
  }

  @Override
  public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
    ensureAnnotationTypesRetrieved();
    for (AnnotationAJ annotation : annotations) {
      if (annotation.getTypeName().equals(ofType.getName())) {
        return annotation;
      }
    }
    return null;
  }

  private void ensureAnnotationTypesRetrieved() {
    if (annotationTypes == null) {
      AnnotationGen annos[] = field.getAnnotations();
      if (annos.length == 0) {
        annotationTypes = ResolvedType.EMPTY_ARRAY;
        annotations = AnnotationAJ.EMPTY_ARRAY;
      } else {
        int annosCount = annos.length;
        annotationTypes = new ResolvedType[annosCount];
        annotations = new AnnotationAJ[annosCount];
        for (int i = 0; i < annosCount; i++) {
          AnnotationGen anno = annos[i];
          annotations[i] = new BcelAnnotation(anno, world);
          annotationTypes[i] = annotations[i].getType();
        }
      }
    }
  }

  @Override
  public void addAnnotation(AnnotationAJ annotation) {
    ensureAnnotationTypesRetrieved();
    int len = annotations.length;
    AnnotationAJ[] ret = new AnnotationAJ[len + 1];
    System.arraycopy(annotations, 0, ret, 0, len);
    ret[len] = annotation;
    annotations = ret;

    ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
    System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
    newAnnotationTypes[len] = annotation.getType();
    annotationTypes = newAnnotationTypes;

    annotationsOnFieldObjectAreOutOfDate = true;
  }

  public void removeAnnotation(AnnotationAJ annotation) {
    ensureAnnotationTypesRetrieved();

    int len = annotations.length;
    AnnotationAJ[] ret = new AnnotationAJ[len - 1];
    int p = 0;
    for (AnnotationAJ anno : annotations) {
      if (!anno.getType().equals(annotation.getType())) {
        ret[p++] = anno;
      }
    }
    annotations = ret;

    ResolvedType[] newAnnotationTypes = new ResolvedType[len - 1];
    p = 0;
    for (ResolvedType anno : annotationTypes) {
      if (!anno.equals(annotation.getType())) {
        newAnnotationTypes[p++] = anno;
      }
    }
    annotationTypes = newAnnotationTypes;

    annotationsOnFieldObjectAreOutOfDate = true;
  }

  /**
   * Unpack the generic signature attribute if there is one and we haven't already done so, then find the true field type of this
   * field (eg. List<String>).
   */
  @Override
  public UnresolvedType getGenericReturnType() {
    unpackGenericSignature();
    return genericFieldType;
  }

  public Field getFieldAsIs() {
    return field;
  }

  public Field getField(ConstantPool cpool) {
    if (!annotationsOnFieldObjectAreOutOfDate) {
      return field;
    }
    FieldGen newFieldGen = new FieldGen(field, cpool);
    newFieldGen.removeAnnotations();
    // List<AnnotationGen> alreadyHas = fg.getAnnotations();
    // if (annotations != null) {
    // fg.removeAnnotations();
    for (AnnotationAJ annotation : annotations) {
      newFieldGen.addAnnotation(new AnnotationGen(((BcelAnnotation) annotation).getBcelAnnotation(), cpool, true));
    }
    // for (int i = 0; i < annotations.length; i++) {
    // AnnotationAJ array_element = annotations[i];
    // boolean alreadyHasIt = false;
    // for (AnnotationGen gen : alreadyHas) {
    // if (gen.getTypeName().equals(array_element.getTypeName())) {
    // alreadyHasIt = true;
    // break;
    // }
    // }
    // if (!alreadyHasIt) {
    // fg.addAnnotation(new AnnotationGen(((BcelAnnotation) array_element).getBcelAnnotation(), cpg, true));
    // // }
    // // }
    // }
    field = newFieldGen.getField();
    annotationsOnFieldObjectAreOutOfDate = false; // we are now correct again
    return field;
  }

  private void unpackGenericSignature() {
    if (unpackedGenericSignature) {
      return;
    }
    if (!world.isInJava5Mode()) {
      this.genericFieldType = getReturnType();
      return;
    }
    unpackedGenericSignature = true;
    String gSig = field.getGenericSignature();
    if (gSig != null) {
      // get from generic
      GenericSignature.FieldTypeSignature fts = new GenericSignatureParser().parseAsFieldSignature(gSig);
      GenericSignature.ClassSignature genericTypeSig = bcelObjectType.getGenericClassTypeSignature();

      GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals();
      GenericSignature.FormalTypeParameter[] typeVars = ((genericTypeSig == null) ? new GenericSignature.FormalTypeParameter[0]
          : genericTypeSig.formalTypeParameters);
      GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length
          + typeVars.length];
      // put method formal in front of type formals for overriding in
      // lookup
      System.arraycopy(typeVars, 0, formals, 0, typeVars.length);
      System.arraycopy(parentFormals, 0, formals, typeVars.length, parentFormals.length);

      try {
        genericFieldType = BcelGenericSignatureToTypeXConverter.fieldTypeSignature2TypeX(fts, formals, world);
      } catch (GenericSignatureFormatException e) {
        // development bug, fail fast with good info
        throw new IllegalStateException("While determing the generic field type of " + this.toString()
            + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
      }
    } else {
      genericFieldType = getReturnType();
    }
  }

  @Override
  public void evictWeavingState() {
    if (field != null) {
      unpackGenericSignature();
      unpackAttributes(world);
      ensureAnnotationTypesRetrieved();
      // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
      field = null;
    }
  }
}
TOP

Related Classes of org.aspectj.weaver.bcel.BcelField

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.