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

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