Logo Search packages:      
Sourcecode: aspectj version File versions

BcelMethod.java

/* *******************************************************************
 * 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.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.aspectj.apache.bcel.classfile.AnnotationDefault;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ExceptionTable;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.LineNumber;
import org.aspectj.apache.bcel.classfile.LineNumberTable;
import org.aspectj.apache.bcel.classfile.LocalVariable;
import org.aspectj.apache.bcel.classfile.LocalVariableTable;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.GenericSignature;
import org.aspectj.util.GenericSignatureParser;
import org.aspectj.util.GenericSignature.TypeVariableSignature;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.ShadowMunger;
import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;

//public final 
class BcelMethod extends ResolvedMemberImpl {

      private Method method;

      // these fields are not set for many BcelMethods...
      private ShadowMunger associatedShadowMunger;
      private ResolvedPointcutDefinition preResolvedPointcut; // used when ajc has
      // pre-resolved the
      // pointcut of some
      // @Advice
      private AjAttribute.EffectiveSignatureAttribute effectiveSignature;

      private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber;
      private AnnotationAJ[] annotations = null;
      private AnnotationAJ[][] parameterAnnotations = null;
      private final BcelObjectType bcelObjectType;

      private int bitflags;
      private static final int KNOW_IF_SYNTHETIC = 0x0001;
      private static final int PARAMETER_NAMES_INITIALIZED = 0x0002;
      private static final int CAN_BE_PARAMETERIZED = 0x0004;
      private static final int UNPACKED_GENERIC_SIGNATURE = 0x0008;
      private static final int IS_AJ_SYNTHETIC = 0x0040;
      private static final int IS_SYNTHETIC = 0x0080;
      private static final int IS_SYNTHETIC_INVERSE = 0x7f7f; // all bits but
      // IS_SYNTHETIC (and
      // topmost bit)
      private static final int HAS_ANNOTATIONS = 0x0400;
      private static final int HAVE_DETERMINED_ANNOTATIONS = 0x0800;

      // genericized version of return and parameter types
      private UnresolvedType genericReturnType = null;
      private UnresolvedType[] genericParameterTypes = null;

      BcelMethod(BcelObjectType declaringType, Method method) {
            super(method.getName().equals("<init>") ? CONSTRUCTOR : (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION
                        : METHOD), declaringType.getResolvedTypeX(), declaringType.isInterface() ? method.getModifiers()
                        | Modifier.INTERFACE : method.getModifiers(), method.getName(), method.getSignature());
            this.method = method;
            sourceContext = declaringType.getResolvedTypeX().getSourceContext();
            bcelObjectType = declaringType;
            unpackJavaAttributes();
            unpackAjAttributes(bcelObjectType.getWorld());
      }

      // ----

      private void unpackJavaAttributes() {
            ExceptionTable exnTable = method.getExceptionTable();
            checkedExceptions = (exnTable == null) ? UnresolvedType.NONE : UnresolvedType.forNames(exnTable.getExceptionNames());

      }

      public String[] getParameterNames() {
            determineParameterNames();
            return super.getParameterNames();
      }

      public int getLineNumberOfFirstInstruction() {
            LineNumberTable lnt = method.getLineNumberTable();
            if (lnt == null)
                  return -1;
            LineNumber[] lns = lnt.getLineNumberTable();
            if (lns == null || lns.length == 0)
                  return -1;
            return lns[0].getLineNumber();
      }

      public void determineParameterNames() {
            if ((bitflags & PARAMETER_NAMES_INITIALIZED) != 0) {
                  return;
            }
            bitflags |= PARAMETER_NAMES_INITIALIZED;
            LocalVariableTable varTable = method.getLocalVariableTable();
            int len = getArity();
            if (varTable == null) {
                  // do we have an annotation with the argNames value specified...
                  if (hasAnnotations()) {
                        AnnotationAJ[] axs = getAnnotations();
                        for (int i = 0; i < axs.length; i++) {
                              AnnotationAJ annotationX = axs[i];
                              String typename = annotationX.getTypeName();
                              if (typename.charAt(0) == 'o') {
                                    if (typename.equals("org.aspectj.lang.annotation.Pointcut")
                                                || typename.equals("org.aspectj.lang.annotation.Before")
                                                || typename.equals("org.aspectj.lang.annotation.Around")
                                                || typename.startsWith("org.aspectj.lang.annotation.After")) {
                                          AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
                                          if (a != null) {
                                                List values = a.getValues();
                                                for (Iterator iterator = values.iterator(); iterator.hasNext();) {
                                                      ElementNameValuePairGen nvPair = (ElementNameValuePairGen) iterator.next();
                                                      if (nvPair.getNameString().equals("argNames")) {
                                                            String argNames = nvPair.getValue().stringifyValue();
                                                            StringTokenizer argNameTokenizer = new StringTokenizer(argNames, " ,");
                                                            List argsList = new ArrayList();
                                                            while (argNameTokenizer.hasMoreTokens()) {
                                                                  argsList.add(argNameTokenizer.nextToken());
                                                            }
                                                            int requiredCount = getParameterTypes().length;
                                                            while (argsList.size() < requiredCount) {
                                                                  argsList.add("arg" + argsList.size());
                                                            }
                                                            setParameterNames((String[]) argsList.toArray(new String[] {}));
                                                            return;
                                                      }
                                                }
                                          }
                                    }
                              }
                        }
                  }
                  setParameterNames(Utility.makeArgNames(len));
            } else {
                  UnresolvedType[] paramTypes = getParameterTypes();
                  String[] paramNames = new String[len];
                  int index = isStatic() ? 0 : 1;
                  for (int i = 0; i < len; i++) {
                        LocalVariable lv = varTable.getLocalVariable(index);
                        if (lv == null) {
                              paramNames[i] = "arg" + i;
                        } else {
                              paramNames[i] = lv.getName();
                        }
                        index += paramTypes[i].getSize();
                  }
                  setParameterNames(paramNames);
            }
      }

      private void unpackAjAttributes(World world) {
            associatedShadowMunger = null;
            List as = Utility.readAjAttributes(getDeclaringType().getClassName(), method.getAttributes(), getSourceContext(world),
                        world, bcelObjectType.getWeaverVersionAttribute());
            processAttributes(world, as);
            as = AtAjAttributes.readAj5MethodAttributes(method, this, world.resolve(getDeclaringType()), preResolvedPointcut,
                        getSourceContext(world), world.getMessageHandler());
            processAttributes(world, as);
      }

      private void processAttributes(World world, List as) {
            for (Iterator iter = as.iterator(); iter.hasNext();) {
                  AjAttribute a = (AjAttribute) iter.next();
                  if (a instanceof AjAttribute.MethodDeclarationLineNumberAttribute) {
                        declarationLineNumber = (AjAttribute.MethodDeclarationLineNumberAttribute) a;
                  } else if (a instanceof AjAttribute.AdviceAttribute) {
                        associatedShadowMunger = ((AjAttribute.AdviceAttribute) a).reify(this, world);
                        // return;
                  } else if (a instanceof AjAttribute.AjSynthetic) {
                        bitflags |= IS_AJ_SYNTHETIC;
                        // isAjSynthetic = true;
                  } else if (a instanceof AjAttribute.EffectiveSignatureAttribute) {
                        // System.out.println("found effective: " + this);
                        effectiveSignature = (AjAttribute.EffectiveSignatureAttribute) a;
                  } else if (a instanceof AjAttribute.PointcutDeclarationAttribute) {
                        // this is an @AspectJ annotated advice method, with pointcut
                        // pre-resolved by ajc
                        preResolvedPointcut = ((AjAttribute.PointcutDeclarationAttribute) a).reify();
                  } else {
                        throw new BCException("weird method attribute " + a);
                  }
            }
      }

      //
      // // for testing - if we have this attribute, return it - will return null
      // if
      // // it doesnt know anything
      // public AjAttribute[] getAttributes(String name) {
      // List results = new ArrayList();
      // List l = Utility.readAjAttributes(getDeclaringType().getClassName(),
      // method.getAttributes(),
      // getSourceContext(bcelObjectType.getWorld()), bcelObjectType.getWorld(),
      // bcelObjectType.getWeaverVersionAttribute());
      // for (Iterator iter = l.iterator(); iter.hasNext();) {
      // AjAttribute element = (AjAttribute) iter.next();
      // if (element.getNameString().equals(name))
      // results.add(element);
      // }
      // if (results.size() > 0) {
      // return (AjAttribute[]) results.toArray(new AjAttribute[] {});
      // }
      // return null;
      // }

      public String getAnnotationDefaultValue() {
            Attribute[] attrs = method.getAttributes();
            for (int i = 0; i < attrs.length; i++) {
                  Attribute attribute = attrs[i];
                  if (attribute.getName().equals("AnnotationDefault")) {
                        AnnotationDefault def = (AnnotationDefault) attribute;
                        return def.getElementValue().stringifyValue();
                  }
            }
            return null;
      }

      // for testing - use with the method above
      public String[] getAttributeNames(boolean onlyIncludeAjOnes) {
            Attribute[] as = method.getAttributes();
            List names = new ArrayList();
            // String[] strs = new String[as.length];
            for (int j = 0; j < as.length; j++) {
                  if (!onlyIncludeAjOnes || as[j].getName().startsWith(AjAttribute.AttributePrefix))
                        names.add(as[j].getName());
            }
            return (String[]) names.toArray(new String[] {});
      }

      public boolean isAjSynthetic() {
            return (bitflags & IS_AJ_SYNTHETIC) != 0;
      }

      // FIXME ??? needs an isSynthetic method

      public ShadowMunger getAssociatedShadowMunger() {
            return associatedShadowMunger;
      }

      public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
            return effectiveSignature;
      }

      public boolean hasDeclarationLineNumberInfo() {
            return declarationLineNumber != null;
      }

      public int getDeclarationLineNumber() {
            if (declarationLineNumber != null) {
                  return declarationLineNumber.getLineNumber();
            } else {
                  return -1;
            }
      }

      public int getDeclarationOffset() {
            if (declarationLineNumber != null) {
                  return declarationLineNumber.getOffset();
            } else {
                  return -1;
            }
      }

      public ISourceLocation getSourceLocation() {
            ISourceLocation ret = super.getSourceLocation();
            if ((ret == null || ret.getLine() == 0) && hasDeclarationLineNumberInfo()) {
                  // lets see if we can do better
                  ISourceContext isc = getSourceContext();
                  if (isc != null)
                        ret = isc.makeSourceLocation(getDeclarationLineNumber(), getDeclarationOffset());
                  else
                        ret = new SourceLocation(null, getDeclarationLineNumber());
            }
            return ret;
      }

      public MemberKind getKind() {
            if (associatedShadowMunger != null) {
                  return ADVICE;
            } else {
                  return super.getKind();
            }
      }

      public boolean hasAnnotation(UnresolvedType ofType) {
            ensureAnnotationsRetrieved();
            for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
                  ResolvedType aType = (ResolvedType) iter.next();
                  if (aType.equals(ofType))
                        return true;
            }
            return false;
      }

      public AnnotationAJ[] getAnnotations() {
            ensureAnnotationsRetrieved();
            if ((bitflags & HAS_ANNOTATIONS) != 0) {
                  return annotations;
            } else {
                  return AnnotationAJ.EMPTY_ARRAY;
            }
      }

      public ResolvedType[] getAnnotationTypes() {
            ensureAnnotationsRetrieved();
            ResolvedType[] ret = new ResolvedType[annotationTypes.size()];
            annotationTypes.toArray(ret);
            return ret;
      }

      public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
            ensureAnnotationsRetrieved();
            if ((bitflags & HAS_ANNOTATIONS) == 0)
                  return null;
            for (int i = 0; i < annotations.length; i++) {
                  if (annotations[i].getTypeName().equals(ofType.getName()))
                        return annotations[i];
            }
            return null;
      }

      public void addAnnotation(AnnotationAJ annotation) {
            ensureAnnotationsRetrieved();
            if ((bitflags & HAS_ANNOTATIONS) == 0) {
                  annotations = new AnnotationAJ[1];
                  annotations[0] = annotation;
            } else {
                  // Add it to the set of annotations
                  int len = annotations.length;
                  AnnotationAJ[] ret = new AnnotationAJ[len + 1];
                  System.arraycopy(annotations, 0, ret, 0, len);
                  ret[len] = annotation;
                  annotations = ret;
            }
            bitflags |= HAS_ANNOTATIONS;

            // Add it to the set of annotation types
            if (annotationTypes == Collections.EMPTY_SET)
                  annotationTypes = new HashSet();
            annotationTypes.add(UnresolvedType.forName(annotation.getTypeName()).resolve(bcelObjectType.getWorld()));
            // FIXME asc looks like we are managing two 'bunches' of annotations,
            // one
            // here and one in the real 'method' - should we reduce it to one layer?
            // method.addAnnotation(annotation.getBcelAnnotation());
      }

      public static final AnnotationAJ[] NO_PARAMETER_ANNOTATIONS = new AnnotationAJ[] {};

      public void addParameterAnnotation(int param, AnnotationAJ anno) {
            ensureParameterAnnotationsRetrieved();
            if (parameterAnnotations == NO_PARAMETER_ANNOTATIONXS) {
                  // First time we've added any, so lets set up the array
                  parameterAnnotations = new AnnotationAJ[getArity()][];
                  for (int i = 0; i < getArity(); i++) {
                        parameterAnnotations[i] = NO_PARAMETER_ANNOTATIONS;
                  }
            }
            int existingCount = parameterAnnotations[param].length;
            if (existingCount == 0) {
                  AnnotationAJ[] annoArray = new AnnotationAJ[1];
                  annoArray[0] = anno;
                  parameterAnnotations[param] = annoArray;
            } else {
                  AnnotationAJ[] newAnnoArray = new AnnotationAJ[existingCount + 1];
                  System.arraycopy(parameterAnnotations[param], 0, newAnnoArray, 0, existingCount);
                  newAnnoArray[existingCount] = anno;
                  parameterAnnotations[param] = newAnnoArray;
            }
      }

      private void ensureAnnotationsRetrieved() {
            if (method == null)
                  return; // must be ok, we have evicted it
            if ((bitflags & HAVE_DETERMINED_ANNOTATIONS) != 0)
                  return;
            bitflags |= HAVE_DETERMINED_ANNOTATIONS;

            AnnotationGen annos[] = method.getAnnotations();
            if (annos.length != 0) {
                  annotationTypes = new HashSet();
                  annotations = new AnnotationAJ[annos.length];
                  for (int i = 0; i < annos.length; i++) {
                        AnnotationGen annotation = annos[i];
                        annotationTypes.add(bcelObjectType.getWorld().resolve(UnresolvedType.forSignature(annotation.getTypeSignature())));
                        annotations[i] = new BcelAnnotation(annotation, bcelObjectType.getWorld());
                  }
                  bitflags |= HAS_ANNOTATIONS;
            } else {
                  annotationTypes = Collections.EMPTY_SET;
            }
      }

      private void ensureParameterAnnotationsRetrieved() {
            if (method == null)
                  return; // must be ok, we have evicted it
            AnnotationGen[][] pAnns = method.getParameterAnnotations();
            if (parameterAnnotationTypes == null || pAnns.length != parameterAnnotationTypes.length) {
                  if (pAnns == Method.NO_PARAMETER_ANNOTATIONS) {
                        parameterAnnotationTypes = BcelMethod.NO_PARAMETER_ANNOTATION_TYPES;
                        parameterAnnotations = BcelMethod.NO_PARAMETER_ANNOTATIONXS;
                  } else {
                        AnnotationGen annos[][] = method.getParameterAnnotations();
                        parameterAnnotations = new AnnotationAJ[annos.length][];
                        parameterAnnotationTypes = new ResolvedType[annos.length][];
                        for (int i = 0; i < annos.length; i++) {
                              parameterAnnotations[i] = new AnnotationAJ[annos[i].length];
                              parameterAnnotationTypes[i] = new ResolvedType[annos[i].length];
                              for (int j = 0; j < annos[i].length; j++) {
                                    parameterAnnotations[i][j] = new BcelAnnotation(annos[i][j], bcelObjectType.getWorld());
                                    parameterAnnotationTypes[i][j] = bcelObjectType.getWorld().resolve(
                                                UnresolvedType.forSignature(annos[i][j].getTypeSignature()));
                              }
                        }
                  }
            }
      }

      public AnnotationAJ[][] getParameterAnnotations() {
            ensureParameterAnnotationsRetrieved();
            return parameterAnnotations;
      }

      public ResolvedType[][] getParameterAnnotationTypes() {
            ensureParameterAnnotationsRetrieved();
            return parameterAnnotationTypes;
      }

      /**
       * A method can be parameterized if it has one or more generic parameters. A generic parameter (type variable parameter) is
       * identified by the prefix "T"
       */
      public boolean canBeParameterized() {
            unpackGenericSignature();
            return (bitflags & CAN_BE_PARAMETERIZED) != 0;
      }

      public UnresolvedType[] getGenericParameterTypes() {
            unpackGenericSignature();
            return genericParameterTypes;
      }

      /**
       * Return the parameterized/generic return type or the normal return type if the method is not generic.
       */
      public UnresolvedType getGenericReturnType() {
            unpackGenericSignature();
            return genericReturnType;
      }

      /** For testing only */
      public Method getMethod() {
            return method;
      }

      private void unpackGenericSignature() {
            if ((bitflags & UNPACKED_GENERIC_SIGNATURE) != 0) {
                  return;
            }
            bitflags |= UNPACKED_GENERIC_SIGNATURE;
            if (!bcelObjectType.getWorld().isInJava5Mode()) {
                  genericReturnType = getReturnType();
                  genericParameterTypes = getParameterTypes();
                  return;
            }
            String gSig = method.getGenericSignature();
            if (gSig != null) {
                  GenericSignature.MethodTypeSignature mSig = new GenericSignatureParser().parseAsMethodSignature(gSig);// method
                  // .
                  // getGenericSignature
                  // ());
                  if (mSig.formalTypeParameters.length > 0) {
                        // generic method declaration
                        bitflags |= CAN_BE_PARAMETERIZED;
                  }

                  typeVariables = new TypeVariable[mSig.formalTypeParameters.length];
                  for (int i = 0; i < typeVariables.length; i++) {
                        GenericSignature.FormalTypeParameter methodFtp = mSig.formalTypeParameters[i];
                        try {
                              typeVariables[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable(methodFtp,
                                          mSig.formalTypeParameters, bcelObjectType.getWorld());
                        } catch (GenericSignatureFormatException e) {
                              // this is a development bug, so fail fast with good info
                              throw new IllegalStateException("While getting the type variables for method " + this.toString()
                                          + " with generic signature " + mSig + " the following error condition was detected: " + e.getMessage());
                        }
                  }

                  GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals();
                  GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length
                              + mSig.formalTypeParameters.length];
                  // put method formal in front of type formals for overriding in
                  // lookup
                  System.arraycopy(mSig.formalTypeParameters, 0, formals, 0, mSig.formalTypeParameters.length);
                  System.arraycopy(parentFormals, 0, formals, mSig.formalTypeParameters.length, parentFormals.length);
                  GenericSignature.TypeSignature returnTypeSignature = mSig.returnType;
                  try {
                        genericReturnType = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(returnTypeSignature, formals,
                                    bcelObjectType.getWorld());
                  } catch (GenericSignatureFormatException e) {
                        // development bug, fail fast with good info
                        throw new IllegalStateException("While determing the generic return type of " + this.toString()
                                    + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
                  }
                  GenericSignature.TypeSignature[] paramTypeSigs = mSig.parameters;
                  genericParameterTypes = new UnresolvedType[paramTypeSigs.length];
                  for (int i = 0; i < paramTypeSigs.length; i++) {
                        try {
                              genericParameterTypes[i] = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(paramTypeSigs[i], formals,
                                          bcelObjectType.getWorld());
                        } catch (GenericSignatureFormatException e) {
                              // development bug, fail fast with good info
                              throw new IllegalStateException("While determining the generic parameter types of " + this.toString()
                                          + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
                        }
                        if (paramTypeSigs[i] instanceof TypeVariableSignature) {
                              bitflags |= CAN_BE_PARAMETERIZED;
                        }
                  }
            } else {
                  genericReturnType = getReturnType();
                  genericParameterTypes = getParameterTypes();
            }
      }

      public void evictWeavingState() {
            if (method != null) {
                  unpackGenericSignature();
                  unpackJavaAttributes();
                  ensureAnnotationsRetrieved();
                  ensureParameterAnnotationsRetrieved();
                  determineParameterNames();
                  // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
                  method = null;
            }
      }

      public boolean isSynthetic() {
            if ((bitflags & KNOW_IF_SYNTHETIC) == 0) {
                  workOutIfSynthetic();
            }
            return (bitflags & IS_SYNTHETIC) != 0;// isSynthetic;
      }

      // Pre Java5 synthetic is an attribute 'Synthetic', post Java5 it is a
      // modifier (4096 or 0x1000)
      private void workOutIfSynthetic() {
            if ((bitflags & KNOW_IF_SYNTHETIC) != 0)
                  return;
            bitflags |= KNOW_IF_SYNTHETIC;
            JavaClass jc = bcelObjectType.getJavaClass();
            bitflags &= IS_SYNTHETIC_INVERSE; // unset the bit
            if (jc == null)
                  return; // what the hell has gone wrong?
            if (jc.getMajor() < 49/* Java5 */) {
                  // synthetic is an attribute
                  String[] synthetics = getAttributeNames(false);
                  if (synthetics != null) {
                        for (int i = 0; i < synthetics.length; i++) {
                              if (synthetics[i].equals("Synthetic")) {
                                    bitflags |= IS_SYNTHETIC;
                                    break;
                              }
                        }
                  }
            } else {
                  // synthetic is a modifier (4096)
                  if ((modifiers & 4096) != 0) {
                        bitflags |= IS_SYNTHETIC;
                  }
            }
      }

      /**
       * Returns whether or not the given object is equivalent to the current one. Returns true if
       * getMethod().getCode().getCodeString() are equal. Allows for different line number tables.
       */
      // bug 154054: is similar to equals(Object) however
      // doesn't require implementing equals in Method and Code
      // which proved expensive. Currently used within
      // CrosscuttingMembers.replaceWith() to decide if we need
      // to do a full build
      public boolean isEquivalentTo(Object other) {
            if (!(other instanceof BcelMethod))
                  return false;
            BcelMethod o = (BcelMethod) other;
            return getMethod().getCode().getCodeString().equals(o.getMethod().getCode().getCodeString());
      }

      /**
       * Return true if the method represents the default constructor. Hard to determine this from bytecode, but the existence of the
       * MethodDeclarationLineNumber attribute should tell us.
       * 
       * @return true if this BcelMethod represents the default constructor
       */
      public boolean isDefaultConstructor() {
            boolean mightBe = !hasDeclarationLineNumberInfo() && name.equals("<init>") && parameterTypes.length == 0;
            if (mightBe) {
                  // TODO would be nice to do a check to see if the file was compiled with javac or ajc?
                  // maybe by checking the constant pool for aspectj strings?
                  return true;
            } else {
                  return false;
            }
      }

}

Generated by  Doxygen 1.6.0   Back to index