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

21 yıl önce
21 yıl önce
21 yıl önce
21 yıl önce
13 yıl önce
21 yıl önce
21 yıl önce
21 yıl önce
21 yıl önce
6 yıl önce
21 yıl önce
21 yıl önce
21 yıl önce
21 yıl önce
13 yıl önce
13 yıl önce
21 yıl önce
14 yıl önce
21 yıl önce
15 yıl önce
15 yıl önce
14 yıl önce
15 yıl önce
14 yıl önce
15 yıl önce
21 yıl önce
21 yıl önce
21 yıl önce
21 yıl önce
13 yıl önce
13 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
21 yıl önce
14 yıl önce
21 yıl önce
15 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
21 yıl önce
14 yıl önce
21 yıl önce
15 yıl önce
21 yıl önce
14 yıl önce
21 yıl önce
14 yıl önce
21 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
14 yıl önce
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. }