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 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  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 Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-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.ArrayList;
  15. import java.util.List;
  16. import java.util.StringTokenizer;
  17. import org.aspectj.apache.bcel.classfile.AnnotationDefault;
  18. import org.aspectj.apache.bcel.classfile.Attribute;
  19. import org.aspectj.apache.bcel.classfile.ExceptionTable;
  20. import org.aspectj.apache.bcel.classfile.JavaClass;
  21. import org.aspectj.apache.bcel.classfile.LineNumber;
  22. import org.aspectj.apache.bcel.classfile.LineNumberTable;
  23. import org.aspectj.apache.bcel.classfile.LocalVariable;
  24. import org.aspectj.apache.bcel.classfile.LocalVariableTable;
  25. import org.aspectj.apache.bcel.classfile.Method;
  26. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  27. import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
  28. import org.aspectj.bridge.ISourceLocation;
  29. import org.aspectj.bridge.SourceLocation;
  30. import org.aspectj.util.GenericSignature;
  31. import org.aspectj.util.GenericSignature.TypeVariableSignature;
  32. import org.aspectj.util.GenericSignatureParser;
  33. import org.aspectj.weaver.AjAttribute;
  34. import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  35. import org.aspectj.weaver.AnnotationAJ;
  36. import org.aspectj.weaver.BCException;
  37. import org.aspectj.weaver.ISourceContext;
  38. import org.aspectj.weaver.MemberKind;
  39. import org.aspectj.weaver.ResolvedMemberImpl;
  40. import org.aspectj.weaver.ResolvedPointcutDefinition;
  41. import org.aspectj.weaver.ResolvedType;
  42. import org.aspectj.weaver.ShadowMunger;
  43. import org.aspectj.weaver.TypeVariable;
  44. import org.aspectj.weaver.UnresolvedType;
  45. import org.aspectj.weaver.World;
  46. import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
  47. //public final
  48. class BcelMethod extends ResolvedMemberImpl {
  49. private final static String ASPECTJ_ANNOTATION_PACKAGE = "org.aspectj.lang.annotation";
  50. private final static char PACKAGE_INITIAL_CHAR = ASPECTJ_ANNOTATION_PACKAGE.charAt(0);
  51. private Method method;
  52. // these fields are not set for many BcelMethods...
  53. private ShadowMunger associatedShadowMunger;
  54. private ResolvedPointcutDefinition preResolvedPointcut; // used when ajc has pre-resolved the pointcut of some @Advice
  55. private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
  56. private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber;
  57. private final BcelObjectType bcelObjectType;
  58. private int bitflags;
  59. private static final int KNOW_IF_SYNTHETIC = 0x0001;
  60. private static final int PARAMETER_NAMES_INITIALIZED = 0x0002;
  61. private static final int CAN_BE_PARAMETERIZED = 0x0004;
  62. private static final int UNPACKED_GENERIC_SIGNATURE = 0x0008;
  63. private static final int IS_AJ_SYNTHETIC = 0x0040;
  64. private static final int IS_SYNTHETIC = 0x0080;
  65. private static final int IS_SYNTHETIC_INVERSE = 0x7f7f; // all bits but
  66. // IS_SYNTHETIC (and
  67. // topmost bit)
  68. private static final int HAS_ANNOTATIONS = 0x0400;
  69. private static final int HAVE_DETERMINED_ANNOTATIONS = 0x0800;
  70. // genericized version of return and parameter types
  71. private UnresolvedType genericReturnType = null;
  72. private UnresolvedType[] genericParameterTypes = null;
  73. BcelMethod(BcelObjectType declaringType, Method method) {
  74. super(method.getName().equals("<init>") ? CONSTRUCTOR : (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION
  75. : METHOD), declaringType.getResolvedTypeX(), method.getModifiers(), method.getName(), method.getSignature());
  76. this.method = method;
  77. sourceContext = declaringType.getResolvedTypeX().getSourceContext();
  78. bcelObjectType = declaringType;
  79. unpackJavaAttributes();
  80. unpackAjAttributes(bcelObjectType.getWorld());
  81. }
  82. /**
  83. * This constructor expects to be passed the attributes, rather than deserializing them.
  84. */
  85. BcelMethod(BcelObjectType declaringType, Method method, List<AjAttribute> attributes) {
  86. super(method.getName().equals("<init>") ? CONSTRUCTOR : (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION
  87. : METHOD), declaringType.getResolvedTypeX(), method.getModifiers(), method.getName(), method.getSignature());
  88. this.method = method;
  89. sourceContext = declaringType.getResolvedTypeX().getSourceContext();
  90. bcelObjectType = declaringType;
  91. unpackJavaAttributes();
  92. processAttributes(bcelObjectType.getWorld(), attributes);
  93. }
  94. // ----
  95. private void unpackJavaAttributes() {
  96. ExceptionTable exnTable = method.getExceptionTable();
  97. checkedExceptions = (exnTable == null) ? UnresolvedType.NONE : UnresolvedType.forNames(exnTable.getExceptionNames());
  98. }
  99. @Override
  100. public String[] getParameterNames() {
  101. determineParameterNames();
  102. return super.getParameterNames();
  103. }
  104. public int getLineNumberOfFirstInstruction() {
  105. LineNumberTable lnt = method.getLineNumberTable();
  106. if (lnt == null) {
  107. return -1;
  108. }
  109. LineNumber[] lns = lnt.getLineNumberTable();
  110. if (lns == null || lns.length == 0) {
  111. return -1;
  112. }
  113. return lns[0].getLineNumber();
  114. }
  115. public void determineParameterNames() {
  116. if ((bitflags & PARAMETER_NAMES_INITIALIZED) != 0) {
  117. return;
  118. }
  119. bitflags |= PARAMETER_NAMES_INITIALIZED;
  120. LocalVariableTable varTable = method.getLocalVariableTable();
  121. int len = getArity();
  122. if (varTable == null) {
  123. // do we have an annotation with the argNames value specified...
  124. AnnotationAJ[] annos = getAnnotations();
  125. if (annos != null && annos.length != 0) {
  126. AnnotationAJ[] axs = getAnnotations();
  127. for (int i = 0; i < axs.length; i++) {
  128. AnnotationAJ annotationX = axs[i];
  129. String typename = annotationX.getTypeName();
  130. if (typename.charAt(0) == PACKAGE_INITIAL_CHAR) {
  131. if (typename.equals("org.aspectj.lang.annotation.Pointcut")
  132. || typename.equals("org.aspectj.lang.annotation.Before")
  133. || typename.equals("org.aspectj.lang.annotation.Around")
  134. || typename.startsWith("org.aspectj.lang.annotation.After")) {
  135. AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
  136. if (a != null) {
  137. List<NameValuePair> values = a.getValues();
  138. for (NameValuePair nvPair : values) {
  139. if (nvPair.getNameString().equals("argNames")) {
  140. String argNames = nvPair.getValue().stringifyValue();
  141. StringTokenizer argNameTokenizer = new StringTokenizer(argNames, " ,");
  142. List<String> argsList = new ArrayList<String>();
  143. while (argNameTokenizer.hasMoreTokens()) {
  144. argsList.add(argNameTokenizer.nextToken());
  145. }
  146. int requiredCount = getParameterTypes().length;
  147. while (argsList.size() < requiredCount) {
  148. argsList.add("arg" + argsList.size());
  149. }
  150. setParameterNames(argsList.toArray(new String[] {}));
  151. return;
  152. }
  153. }
  154. }
  155. }
  156. }
  157. }
  158. }
  159. setParameterNames(Utility.makeArgNames(len));
  160. } else {
  161. UnresolvedType[] paramTypes = getParameterTypes();
  162. String[] paramNames = new String[len];
  163. int index = Modifier.isStatic(modifiers) ? 0 : 1;
  164. for (int i = 0; i < len; i++) {
  165. LocalVariable lv = varTable.getLocalVariable(index);
  166. if (lv == null) {
  167. paramNames[i] = "arg" + i;
  168. } else {
  169. paramNames[i] = lv.getName();
  170. }
  171. index += paramTypes[i].getSize();
  172. }
  173. setParameterNames(paramNames);
  174. }
  175. }
  176. private void unpackAjAttributes(World world) {
  177. associatedShadowMunger = null;
  178. ResolvedType resolvedDeclaringType = getDeclaringType().resolve(world);
  179. WeaverVersionInfo wvinfo = bcelObjectType.getWeaverVersionAttribute();
  180. List<AjAttribute> as = Utility.readAjAttributes(resolvedDeclaringType.getClassName(), method.getAttributes(),
  181. resolvedDeclaringType.getSourceContext(), world, wvinfo, new BcelConstantPoolReader(method.getConstantPool()));
  182. processAttributes(world, as);
  183. as = AtAjAttributes.readAj5MethodAttributes(method, this, resolvedDeclaringType, preResolvedPointcut,
  184. resolvedDeclaringType.getSourceContext(), world.getMessageHandler());
  185. processAttributes(world, as);
  186. }
  187. private void processAttributes(World world, List<AjAttribute> as) {
  188. for (AjAttribute attr : as) {
  189. if (attr instanceof AjAttribute.MethodDeclarationLineNumberAttribute) {
  190. declarationLineNumber = (AjAttribute.MethodDeclarationLineNumberAttribute) attr;
  191. } else if (attr instanceof AjAttribute.AdviceAttribute) {
  192. associatedShadowMunger = ((AjAttribute.AdviceAttribute) attr).reify(this, world, (ResolvedType) getDeclaringType());
  193. } else if (attr instanceof AjAttribute.AjSynthetic) {
  194. bitflags |= IS_AJ_SYNTHETIC;
  195. } else if (attr instanceof AjAttribute.EffectiveSignatureAttribute) {
  196. effectiveSignature = (AjAttribute.EffectiveSignatureAttribute) attr;
  197. } else if (attr instanceof AjAttribute.PointcutDeclarationAttribute) {
  198. // this is an @AspectJ annotated advice method, with pointcut pre-resolved by ajc
  199. preResolvedPointcut = ((AjAttribute.PointcutDeclarationAttribute) attr).reify();
  200. } else {
  201. throw new BCException("weird method attribute " + attr);
  202. }
  203. }
  204. }
  205. //
  206. // // for testing - if we have this attribute, return it - will return null
  207. // if
  208. // // it doesnt know anything
  209. // public AjAttribute[] getAttributes(String name) {
  210. // List results = new ArrayList();
  211. // List l = Utility.readAjAttributes(getDeclaringType().getClassName(),
  212. // method.getAttributes(),
  213. // getSourceContext(bcelObjectType.getWorld()), bcelObjectType.getWorld(),
  214. // bcelObjectType.getWeaverVersionAttribute());
  215. // for (Iterator iter = l.iterator(); iter.hasNext();) {
  216. // AjAttribute element = (AjAttribute) iter.next();
  217. // if (element.getNameString().equals(name))
  218. // results.add(element);
  219. // }
  220. // if (results.size() > 0) {
  221. // return (AjAttribute[]) results.toArray(new AjAttribute[] {});
  222. // }
  223. // return null;
  224. // }
  225. @Override
  226. public String getAnnotationDefaultValue() {
  227. Attribute[] attrs = method.getAttributes();
  228. for (int i = 0; i < attrs.length; i++) {
  229. Attribute attribute = attrs[i];
  230. if (attribute.getName().equals("AnnotationDefault")) {
  231. AnnotationDefault def = (AnnotationDefault) attribute;
  232. return def.getElementValue().stringifyValue();
  233. }
  234. }
  235. return null;
  236. }
  237. // for testing - use with the method above
  238. public String[] getAttributeNames(boolean onlyIncludeAjOnes) {
  239. Attribute[] as = method.getAttributes();
  240. List<String> names = new ArrayList<String>();
  241. // String[] strs = new String[as.length];
  242. for (int j = 0; j < as.length; j++) {
  243. if (!onlyIncludeAjOnes || as[j].getName().startsWith(AjAttribute.AttributePrefix)) {
  244. names.add(as[j].getName());
  245. }
  246. }
  247. return names.toArray(new String[] {});
  248. }
  249. @Override
  250. public boolean isAjSynthetic() {
  251. return (bitflags & IS_AJ_SYNTHETIC) != 0;
  252. }
  253. @Override
  254. public ShadowMunger getAssociatedShadowMunger() {
  255. return associatedShadowMunger;
  256. }
  257. @Override
  258. public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
  259. return effectiveSignature;
  260. }
  261. public boolean hasDeclarationLineNumberInfo() {
  262. return declarationLineNumber != null;
  263. }
  264. public int getDeclarationLineNumber() {
  265. if (declarationLineNumber != null) {
  266. return declarationLineNumber.getLineNumber();
  267. } else {
  268. return -1;
  269. }
  270. }
  271. public int getDeclarationOffset() {
  272. if (declarationLineNumber != null) {
  273. return declarationLineNumber.getOffset();
  274. } else {
  275. return -1;
  276. }
  277. }
  278. @Override
  279. public ISourceLocation getSourceLocation() {
  280. ISourceLocation ret = super.getSourceLocation();
  281. if ((ret == null || ret.getLine() == 0) && hasDeclarationLineNumberInfo()) {
  282. // lets see if we can do better
  283. ISourceContext isc = getSourceContext();
  284. if (isc != null) {
  285. ret = isc.makeSourceLocation(getDeclarationLineNumber(), getDeclarationOffset());
  286. } else {
  287. ret = new SourceLocation(null, getDeclarationLineNumber());
  288. }
  289. }
  290. return ret;
  291. }
  292. @Override
  293. public MemberKind getKind() {
  294. if (associatedShadowMunger != null) {
  295. return ADVICE;
  296. } else {
  297. return super.getKind();
  298. }
  299. }
  300. @Override
  301. public boolean hasAnnotation(UnresolvedType ofType) {
  302. ensureAnnotationsRetrieved();
  303. for (ResolvedType aType : annotationTypes) {
  304. if (aType.equals(ofType)) {
  305. return true;
  306. }
  307. }
  308. return false;
  309. }
  310. @Override
  311. public AnnotationAJ[] getAnnotations() {
  312. ensureAnnotationsRetrieved();
  313. if ((bitflags & HAS_ANNOTATIONS) != 0) {
  314. return annotations;
  315. } else {
  316. return AnnotationAJ.EMPTY_ARRAY;
  317. }
  318. }
  319. @Override
  320. public ResolvedType[] getAnnotationTypes() {
  321. ensureAnnotationsRetrieved();
  322. return annotationTypes;
  323. }
  324. @Override
  325. public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
  326. ensureAnnotationsRetrieved();
  327. if ((bitflags & HAS_ANNOTATIONS) == 0) {
  328. return null;
  329. }
  330. for (int i = 0; i < annotations.length; i++) {
  331. if (annotations[i].getTypeName().equals(ofType.getName())) {
  332. return annotations[i];
  333. }
  334. }
  335. return null;
  336. }
  337. @Override
  338. public void addAnnotation(AnnotationAJ annotation) {
  339. ensureAnnotationsRetrieved();
  340. if ((bitflags & HAS_ANNOTATIONS) == 0) {
  341. annotations = new AnnotationAJ[1];
  342. annotations[0] = annotation;
  343. annotationTypes = new ResolvedType[1];
  344. annotationTypes[0] = annotation.getType();
  345. } else {
  346. // Add it to the set of annotations
  347. int len = annotations.length;
  348. AnnotationAJ[] ret = new AnnotationAJ[len + 1];
  349. System.arraycopy(annotations, 0, ret, 0, len);
  350. ret[len] = annotation;
  351. annotations = ret;
  352. ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
  353. System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
  354. newAnnotationTypes[len] = annotation.getType();
  355. annotationTypes = newAnnotationTypes;
  356. }
  357. bitflags |= HAS_ANNOTATIONS;
  358. }
  359. public void removeAnnotation(ResolvedType annotationType) {
  360. ensureAnnotationsRetrieved();
  361. if ((bitflags & HAS_ANNOTATIONS) == 0) {
  362. // nothing to do, why did we get called?
  363. } else {
  364. int len = annotations.length;
  365. if (len == 1) {
  366. bitflags &= ~HAS_ANNOTATIONS;
  367. annotations = null;
  368. annotationTypes = null;
  369. return;
  370. }
  371. AnnotationAJ[] ret = new AnnotationAJ[len - 1];
  372. int p = 0;
  373. for (AnnotationAJ annotation : annotations) {
  374. if (!annotation.getType().equals(annotationType)) {
  375. ret[p++] = annotation;
  376. }
  377. }
  378. annotations = ret;
  379. ResolvedType[] newAnnotationTypes = new ResolvedType[len - 1];
  380. p = 0;
  381. for (AnnotationAJ annotation : annotations) {
  382. if (!annotation.getType().equals(annotationType)) {
  383. newAnnotationTypes[p++] = annotationType;
  384. }
  385. }
  386. annotationTypes = newAnnotationTypes;
  387. }
  388. bitflags |= HAS_ANNOTATIONS;
  389. }
  390. public static final AnnotationAJ[] NO_PARAMETER_ANNOTATIONS = new AnnotationAJ[] {};
  391. public void addParameterAnnotation(int param, AnnotationAJ anno) {
  392. ensureParameterAnnotationsRetrieved();
  393. if (parameterAnnotations == NO_PARAMETER_ANNOTATIONXS) {
  394. // First time we've added any, so lets set up the array
  395. parameterAnnotations = new AnnotationAJ[getArity()][];
  396. for (int i = 0; i < getArity(); i++) {
  397. parameterAnnotations[i] = NO_PARAMETER_ANNOTATIONS;
  398. }
  399. }
  400. int existingCount = parameterAnnotations[param].length;
  401. if (existingCount == 0) {
  402. AnnotationAJ[] annoArray = new AnnotationAJ[1];
  403. annoArray[0] = anno;
  404. parameterAnnotations[param] = annoArray;
  405. } else {
  406. AnnotationAJ[] newAnnoArray = new AnnotationAJ[existingCount + 1];
  407. System.arraycopy(parameterAnnotations[param], 0, newAnnoArray, 0, existingCount);
  408. newAnnoArray[existingCount] = anno;
  409. parameterAnnotations[param] = newAnnoArray;
  410. }
  411. }
  412. private void ensureAnnotationsRetrieved() {
  413. if (method == null) {
  414. return; // must be ok, we have evicted it
  415. }
  416. if ((bitflags & HAVE_DETERMINED_ANNOTATIONS) != 0) {
  417. return;
  418. }
  419. bitflags |= HAVE_DETERMINED_ANNOTATIONS;
  420. AnnotationGen annos[] = method.getAnnotations();
  421. if (annos.length == 0) {
  422. annotationTypes = ResolvedType.NONE;
  423. annotations = AnnotationAJ.EMPTY_ARRAY;
  424. } else {
  425. int annoCount = annos.length;
  426. annotationTypes = new ResolvedType[annoCount];
  427. annotations = new AnnotationAJ[annoCount];
  428. for (int i = 0; i < annoCount; i++) {
  429. AnnotationGen annotation = annos[i];
  430. annotations[i] = new BcelAnnotation(annotation, bcelObjectType.getWorld());
  431. annotationTypes[i] = annotations[i].getType();
  432. }
  433. bitflags |= HAS_ANNOTATIONS;
  434. }
  435. }
  436. private void ensureParameterAnnotationsRetrieved() {
  437. if (method == null) {
  438. return; // must be ok, we have evicted it
  439. }
  440. AnnotationGen[][] pAnns = method.getParameterAnnotations();
  441. if (parameterAnnotationTypes == null || pAnns.length != parameterAnnotationTypes.length) {
  442. if (pAnns == Method.NO_PARAMETER_ANNOTATIONS) {
  443. parameterAnnotationTypes = BcelMethod.NO_PARAMETER_ANNOTATION_TYPES;
  444. parameterAnnotations = BcelMethod.NO_PARAMETER_ANNOTATIONXS;
  445. } else {
  446. AnnotationGen annos[][] = method.getParameterAnnotations();
  447. parameterAnnotations = new AnnotationAJ[annos.length][];
  448. parameterAnnotationTypes = new ResolvedType[annos.length][];
  449. for (int i = 0; i < annos.length; i++) {
  450. AnnotationGen[] annosOnThisParam = annos[i];
  451. if (annos[i].length == 0) {
  452. parameterAnnotations[i] = AnnotationAJ.EMPTY_ARRAY;
  453. parameterAnnotationTypes[i] = ResolvedType.NONE;
  454. } else {
  455. parameterAnnotations[i] = new AnnotationAJ[annosOnThisParam.length];
  456. parameterAnnotationTypes[i] = new ResolvedType[annosOnThisParam.length];
  457. for (int j = 0; j < annosOnThisParam.length; j++) {
  458. parameterAnnotations[i][j] = new BcelAnnotation(annosOnThisParam[j], bcelObjectType.getWorld());
  459. parameterAnnotationTypes[i][j] = bcelObjectType.getWorld().resolve(
  460. UnresolvedType.forSignature(annosOnThisParam[j].getTypeSignature()));
  461. }
  462. }
  463. }
  464. }
  465. }
  466. }
  467. @Override
  468. public AnnotationAJ[][] getParameterAnnotations() {
  469. ensureParameterAnnotationsRetrieved();
  470. return parameterAnnotations;
  471. }
  472. @Override
  473. public ResolvedType[][] getParameterAnnotationTypes() {
  474. ensureParameterAnnotationsRetrieved();
  475. return parameterAnnotationTypes;
  476. }
  477. /**
  478. * A method can be parameterized if it has one or more generic parameters. A generic parameter (type variable parameter) is
  479. * identified by the prefix "T"
  480. */
  481. @Override
  482. public boolean canBeParameterized() {
  483. unpackGenericSignature();
  484. return (bitflags & CAN_BE_PARAMETERIZED) != 0;
  485. }
  486. @Override
  487. public UnresolvedType[] getGenericParameterTypes() {
  488. unpackGenericSignature();
  489. return genericParameterTypes;
  490. }
  491. /**
  492. * Return the parameterized/generic return type or the normal return type if the method is not generic.
  493. */
  494. @Override
  495. public UnresolvedType getGenericReturnType() {
  496. unpackGenericSignature();
  497. return genericReturnType;
  498. }
  499. /** For testing only */
  500. public Method getMethod() {
  501. return method;
  502. }
  503. private void unpackGenericSignature() {
  504. if ((bitflags & UNPACKED_GENERIC_SIGNATURE) != 0) {
  505. return;
  506. }
  507. bitflags |= UNPACKED_GENERIC_SIGNATURE;
  508. if (!bcelObjectType.getWorld().isInJava5Mode()) {
  509. genericReturnType = getReturnType();
  510. genericParameterTypes = getParameterTypes();
  511. return;
  512. }
  513. String gSig = method.getGenericSignature();
  514. if (gSig != null) {
  515. GenericSignature.MethodTypeSignature mSig = new GenericSignatureParser().parseAsMethodSignature(gSig);// method
  516. // .
  517. // getGenericSignature
  518. // ());
  519. if (mSig.formalTypeParameters.length > 0) {
  520. // generic method declaration
  521. bitflags |= CAN_BE_PARAMETERIZED;
  522. }
  523. typeVariables = new TypeVariable[mSig.formalTypeParameters.length];
  524. for (int i = 0; i < typeVariables.length; i++) {
  525. GenericSignature.FormalTypeParameter methodFtp = mSig.formalTypeParameters[i];
  526. try {
  527. typeVariables[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable(methodFtp,
  528. mSig.formalTypeParameters, bcelObjectType.getWorld());
  529. } catch (GenericSignatureFormatException e) {
  530. // this is a development bug, so fail fast with good info
  531. throw new IllegalStateException("While getting the type variables for method " + this.toString()
  532. + " with generic signature " + mSig + " the following error condition was detected: " + e.getMessage());
  533. }
  534. }
  535. GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals();
  536. GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length
  537. + mSig.formalTypeParameters.length];
  538. // put method formal in front of type formals for overriding in
  539. // lookup
  540. System.arraycopy(mSig.formalTypeParameters, 0, formals, 0, mSig.formalTypeParameters.length);
  541. System.arraycopy(parentFormals, 0, formals, mSig.formalTypeParameters.length, parentFormals.length);
  542. GenericSignature.TypeSignature returnTypeSignature = mSig.returnType;
  543. try {
  544. genericReturnType = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(returnTypeSignature, formals,
  545. bcelObjectType.getWorld());
  546. } catch (GenericSignatureFormatException e) {
  547. // development bug, fail fast with good info
  548. throw new IllegalStateException("While determing the generic return type of " + this.toString()
  549. + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
  550. }
  551. GenericSignature.TypeSignature[] paramTypeSigs = mSig.parameters;
  552. if (paramTypeSigs.length == 0) {
  553. genericParameterTypes = UnresolvedType.NONE;
  554. } else {
  555. genericParameterTypes = new UnresolvedType[paramTypeSigs.length];
  556. }
  557. for (int i = 0; i < paramTypeSigs.length; i++) {
  558. try {
  559. genericParameterTypes[i] = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(paramTypeSigs[i], formals,
  560. bcelObjectType.getWorld());
  561. } catch (GenericSignatureFormatException e) {
  562. // development bug, fail fast with good info
  563. throw new IllegalStateException("While determining the generic parameter types of " + this.toString()
  564. + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
  565. }
  566. if (paramTypeSigs[i] instanceof TypeVariableSignature) {
  567. bitflags |= CAN_BE_PARAMETERIZED;
  568. }
  569. }
  570. } else {
  571. genericReturnType = getReturnType();
  572. genericParameterTypes = getParameterTypes();
  573. }
  574. }
  575. @Override
  576. public void evictWeavingState() {
  577. if (method != null) {
  578. unpackGenericSignature();
  579. unpackJavaAttributes();
  580. ensureAnnotationsRetrieved();
  581. ensureParameterAnnotationsRetrieved();
  582. determineParameterNames();
  583. // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
  584. method = null;
  585. }
  586. }
  587. @Override
  588. public boolean isSynthetic() {
  589. if ((bitflags & KNOW_IF_SYNTHETIC) == 0) {
  590. workOutIfSynthetic();
  591. }
  592. return (bitflags & IS_SYNTHETIC) != 0;// isSynthetic;
  593. }
  594. // Pre Java5 synthetic is an attribute 'Synthetic', post Java5 it is a
  595. // modifier (4096 or 0x1000)
  596. private void workOutIfSynthetic() {
  597. if ((bitflags & KNOW_IF_SYNTHETIC) != 0) {
  598. return;
  599. }
  600. bitflags |= KNOW_IF_SYNTHETIC;
  601. JavaClass jc = bcelObjectType.getJavaClass();
  602. bitflags &= IS_SYNTHETIC_INVERSE; // unset the bit
  603. if (jc == null) {
  604. return; // what the hell has gone wrong?
  605. }
  606. if (jc.getMajor() < 49/* Java5 */) {
  607. // synthetic is an attribute
  608. String[] synthetics = getAttributeNames(false);
  609. if (synthetics != null) {
  610. for (int i = 0; i < synthetics.length; i++) {
  611. if (synthetics[i].equals("Synthetic")) {
  612. bitflags |= IS_SYNTHETIC;
  613. break;
  614. }
  615. }
  616. }
  617. } else {
  618. // synthetic is a modifier (4096)
  619. if ((modifiers & 4096) != 0) {
  620. bitflags |= IS_SYNTHETIC;
  621. }
  622. }
  623. }
  624. /**
  625. * Returns whether or not the given object is equivalent to the current one. Returns true if
  626. * getMethod().getCode().getCodeString() are equal. Allows for different line number tables.
  627. */
  628. // bug 154054: is similar to equals(Object) however
  629. // doesn't require implementing equals in Method and Code
  630. // which proved expensive. Currently used within
  631. // CrosscuttingMembers.replaceWith() to decide if we need
  632. // to do a full build
  633. @Override
  634. public boolean isEquivalentTo(Object other) {
  635. if (!(other instanceof BcelMethod)) {
  636. return false;
  637. }
  638. BcelMethod o = (BcelMethod) other;
  639. return getMethod().getCode().getCodeString().equals(o.getMethod().getCode().getCodeString());
  640. }
  641. /**
  642. * Return true if the method represents the default constructor. Hard to determine this from bytecode, but the existence of the
  643. * MethodDeclarationLineNumber attribute should tell us.
  644. *
  645. * @return true if this BcelMethod represents the default constructor
  646. */
  647. @Override
  648. public boolean isDefaultConstructor() {
  649. boolean mightBe = !hasDeclarationLineNumberInfo() && name.equals("<init>") && parameterTypes.length == 0;
  650. if (mightBe) {
  651. // TODO would be nice to do a check to see if the file was compiled with javac or ajc?
  652. // maybe by checking the constant pool for aspectj strings?
  653. return true;
  654. } else {
  655. return false;
  656. }
  657. }
  658. }