You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BcelMethod.java 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.lang.reflect.Modifier;
  14. import java.util.Iterator;
  15. import java.util.List;
  16. import org.aspectj.apache.bcel.classfile.ExceptionTable;
  17. import org.aspectj.apache.bcel.classfile.LocalVariable;
  18. import org.aspectj.apache.bcel.classfile.LocalVariableTable;
  19. import org.aspectj.apache.bcel.classfile.Method;
  20. import org.aspectj.apache.bcel.classfile.annotation.Annotation;
  21. import org.aspectj.bridge.ISourceLocation;
  22. import org.aspectj.bridge.SourceLocation;
  23. import org.aspectj.weaver.AjAttribute;
  24. import org.aspectj.weaver.AnnotationX;
  25. import org.aspectj.weaver.BCException;
  26. import org.aspectj.weaver.ISourceContext;
  27. import org.aspectj.weaver.ResolvedMember;
  28. import org.aspectj.weaver.ResolvedPointcutDefinition;
  29. import org.aspectj.weaver.ResolvedTypeX;
  30. import org.aspectj.weaver.ShadowMunger;
  31. import org.aspectj.weaver.TypeX;
  32. import org.aspectj.weaver.World;
  33. final class BcelMethod extends ResolvedMember {
  34. private Method method;
  35. private boolean isAjSynthetic;
  36. private ShadowMunger associatedShadowMunger;
  37. private ResolvedPointcutDefinition preResolvedPointcut; // used when ajc has pre-resolved the pointcut of some @Advice
  38. private ResolvedTypeX[] annotationTypes = null;
  39. private AnnotationX[] annotations = null;
  40. private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
  41. private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber;
  42. private ResolvedTypeX[] resolvedAnnotations;
  43. private World world;
  44. BcelMethod(BcelObjectType declaringType, Method method) {
  45. super(
  46. method.getName().equals("<init>") ? CONSTRUCTOR :
  47. (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION : METHOD),
  48. declaringType.getResolvedTypeX(),
  49. declaringType.isInterface()
  50. ? method.getAccessFlags() | Modifier.INTERFACE
  51. : method.getAccessFlags(),
  52. method.getName(),
  53. method.getSignature());
  54. this.method = method;
  55. this.sourceContext = declaringType.getResolvedTypeX().getSourceContext();
  56. this.world = declaringType.getResolvedTypeX().getWorld();
  57. unpackAjAttributes(world);
  58. unpackJavaAttributes();
  59. }
  60. // ----
  61. private void unpackJavaAttributes() {
  62. ExceptionTable exnTable = method.getExceptionTable();
  63. checkedExceptions = (exnTable == null)
  64. ? TypeX.NONE
  65. : TypeX.forNames(exnTable.getExceptionNames());
  66. LocalVariableTable varTable = method.getLocalVariableTable();
  67. int len = getArity();
  68. if (varTable == null) {
  69. this.parameterNames = Utility.makeArgNames(len);
  70. } else {
  71. TypeX[] paramTypes = getParameterTypes();
  72. String[] paramNames = new String[len];
  73. int index = isStatic() ? 0 : 1;
  74. for (int i = 0; i < len; i++) {
  75. LocalVariable lv = varTable.getLocalVariable(index);
  76. if (lv == null) {
  77. paramNames[i] = "arg" + i;
  78. } else {
  79. paramNames[i] = lv.getName();
  80. }
  81. index += paramTypes[i].getSize();
  82. }
  83. this.parameterNames = paramNames;
  84. }
  85. }
  86. private void unpackAjAttributes(World world) {
  87. associatedShadowMunger = null;
  88. List as = BcelAttributes.readAjAttributes(getDeclaringType().getClassName(),method.getAttributes(), getSourceContext(world),world.getMessageHandler());
  89. processAttributes(world, as);
  90. as = AtAjAttributes.readAj5MethodAttributes(method, this, world.resolve(getDeclaringType()), preResolvedPointcut,getSourceContext(world), world.getMessageHandler());
  91. processAttributes(world,as);
  92. }
  93. private void processAttributes(World world, List as) {
  94. for (Iterator iter = as.iterator(); iter.hasNext();) {
  95. AjAttribute a = (AjAttribute) iter.next();
  96. if (a instanceof AjAttribute.MethodDeclarationLineNumberAttribute) {
  97. declarationLineNumber = (AjAttribute.MethodDeclarationLineNumberAttribute)a;
  98. } else if (a instanceof AjAttribute.AdviceAttribute) {
  99. associatedShadowMunger = ((AjAttribute.AdviceAttribute)a).reify(this, world);
  100. // return;
  101. } else if (a instanceof AjAttribute.AjSynthetic) {
  102. isAjSynthetic = true;
  103. } else if (a instanceof AjAttribute.EffectiveSignatureAttribute) {
  104. //System.out.println("found effective: " + this);
  105. effectiveSignature = (AjAttribute.EffectiveSignatureAttribute)a;
  106. } else if (a instanceof AjAttribute.PointcutDeclarationAttribute) {
  107. // this is an @AspectJ annotated advice method, with pointcut pre-resolved by ajc
  108. preResolvedPointcut = ((AjAttribute.PointcutDeclarationAttribute)a).reify();
  109. } else {
  110. throw new BCException("weird method attribute " + a);
  111. }
  112. }
  113. }
  114. public boolean isAjSynthetic() {
  115. return isAjSynthetic; // || getName().startsWith(NameMangler.PREFIX);
  116. }
  117. //FIXME ??? needs an isSynthetic method
  118. public ShadowMunger getAssociatedShadowMunger() {
  119. return associatedShadowMunger;
  120. }
  121. public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
  122. return effectiveSignature;
  123. }
  124. public boolean hasDeclarationLineNumberInfo() {
  125. return declarationLineNumber != null;
  126. }
  127. public int getDeclarationLineNumber() {
  128. if (declarationLineNumber != null) {
  129. return declarationLineNumber.getLineNumber();
  130. } else {
  131. return -1;
  132. }
  133. }
  134. public ISourceLocation getSourceLocation() {
  135. ISourceLocation ret = super.getSourceLocation();
  136. if ((ret == null || ret.getLine()==0) && hasDeclarationLineNumberInfo()) {
  137. // lets see if we can do better
  138. ISourceContext isc = getSourceContext();
  139. if (isc !=null) ret = isc.makeSourceLocation(getDeclarationLineNumber());
  140. else ret = new SourceLocation(null,getDeclarationLineNumber());
  141. }
  142. return ret;
  143. }
  144. public Kind getKind() {
  145. if (associatedShadowMunger != null) {
  146. return ADVICE;
  147. } else {
  148. return super.getKind();
  149. }
  150. }
  151. public boolean hasAnnotation(TypeX ofType) {
  152. ensureAnnotationTypesRetrieved();
  153. for (int i=0; i<annotationTypes.length; i++) {
  154. ResolvedTypeX aType = annotationTypes[i];
  155. if (aType.equals(ofType)) return true;
  156. }
  157. return false;
  158. }
  159. public AnnotationX[] getAnnotations() {
  160. ensureAnnotationTypesRetrieved();
  161. return annotations;
  162. }
  163. public ResolvedTypeX[] getAnnotationTypes() {
  164. ensureAnnotationTypesRetrieved();
  165. return annotationTypes;
  166. }
  167. public void addAnnotation(AnnotationX annotation) {
  168. ensureAnnotationTypesRetrieved();
  169. // Add it to the set of annotations
  170. int len = annotations.length;
  171. AnnotationX[] ret = new AnnotationX[len+1];
  172. System.arraycopy(annotations, 0, ret, 0, len);
  173. ret[len] = annotation;
  174. annotations = ret;
  175. // Add it to the set of annotation types
  176. len = annotationTypes.length;
  177. ResolvedTypeX[] ret2 = new ResolvedTypeX[len+1];
  178. System.arraycopy(annotationTypes,0,ret2,0,len);
  179. ret2[len] =world.resolve(TypeX.forName(annotation.getTypeName()));
  180. annotationTypes = ret2;
  181. // FIXME asc looks like we are managing two 'bunches' of annotations, one
  182. // here and one in the real 'method' - should we reduce it to one layer?
  183. method.addAnnotation(annotation.getBcelAnnotation());
  184. }
  185. private void ensureAnnotationTypesRetrieved() {
  186. if (annotationTypes == null || method.getAnnotations().length!=annotations.length) { // sometimes the list changes underneath us!
  187. Annotation annos[] = method.getAnnotations();
  188. annotationTypes = new ResolvedTypeX[annos.length];
  189. annotations = new AnnotationX[annos.length];
  190. for (int i = 0; i < annos.length; i++) {
  191. Annotation annotation = annos[i];
  192. ResolvedTypeX rtx = world.resolve(TypeX.forName(annotation.getTypeName()));
  193. annotationTypes[i] = rtx;
  194. annotations[i] = new AnnotationX(annotation,world);
  195. }
  196. }
  197. }
  198. }