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.

MemberImpl.java 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  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;
  13. import java.lang.reflect.Modifier;
  14. import java.util.ArrayList;
  15. import java.util.Collection;
  16. import java.util.HashSet;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. public class MemberImpl implements Member {
  20. protected MemberKind kind;
  21. protected int modifiers;
  22. protected String name;
  23. protected UnresolvedType declaringType;
  24. protected UnresolvedType returnType;
  25. protected UnresolvedType[] parameterTypes;
  26. private final String erasedSignature; // eg. (Ljava/util/Set;V)Ljava/lang/String;
  27. private String paramSignature; // eg. (Ljava/util/Set<Ljava/lang/String;>;V) // no return type
  28. // OPTIMIZE move out of the member!
  29. private boolean reportedCantFindDeclaringType = false;
  30. private boolean reportedUnresolvableMember = false;
  31. /**
  32. * All the signatures that a join point with this member as its signature has.
  33. */
  34. private JoinPointSignatureIterator joinPointSignatures = null;
  35. /**
  36. * Construct a MemberImpl using an erased signature for the parameters and return type (member method/ctor) or type (member
  37. * field)
  38. */
  39. public MemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String erasedSignature) {
  40. this.kind = kind;
  41. this.declaringType = declaringType;
  42. this.modifiers = modifiers;
  43. this.name = name;
  44. this.erasedSignature = erasedSignature;
  45. if (kind == FIELD) {
  46. this.returnType = UnresolvedType.forSignature(erasedSignature);
  47. this.parameterTypes = UnresolvedType.NONE;
  48. } else {
  49. Object[] returnAndParams = signatureToTypes(erasedSignature);
  50. this.returnType = (UnresolvedType) returnAndParams[0];
  51. this.parameterTypes = (UnresolvedType[]) returnAndParams[1];
  52. }
  53. }
  54. /**
  55. * Construct a MemberImpl using real type information for the parameters and return type (member method/ctor) or type (member
  56. * field)
  57. */
  58. public MemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
  59. UnresolvedType[] parameterTypes) {
  60. this.kind = kind;
  61. this.declaringType = declaringType;
  62. this.modifiers = modifiers;
  63. this.returnType = returnType;
  64. this.name = name;
  65. this.parameterTypes = parameterTypes;
  66. if (kind == FIELD) {
  67. this.erasedSignature = returnType.getErasureSignature();
  68. } else {
  69. this.erasedSignature = typesToSignature(returnType, parameterTypes, true);
  70. // Check parameter recovery by collapsing types to the string then rebuilding them from that
  71. // this will check we are capable of having WeakRefs to the parameter types
  72. // String nonErasedSignature = getParameterSignature()+getReturnType().getSignature();
  73. // Object[] returnAndParams = signatureToTypes(nonErasedSignature);
  74. // UnresolvedType[] recoveredParams = (UnresolvedType[]) returnAndParams[1];
  75. // for (int jj=0;jj<parameterTypes.length;jj++) {
  76. // if (!parameterTypes[jj].getSignature().equals(recoveredParams[jj].getSignature())) {
  77. // throw new
  78. // RuntimeException(parameterTypes[jj].getSignature()+" != "+recoveredParams[jj].getSignature()+" "+paramSignature);
  79. // }
  80. // }
  81. }
  82. }
  83. public ResolvedMember resolve(World world) {
  84. return world.resolve(this);
  85. }
  86. // ---- utility methods
  87. /**
  88. * Build a signature based on the return type and parameter types. For example: "(Ljava/util/Set&lt;Ljava/lang/String;&gt;;)V" or
  89. * "(Ljava/util/Set;)V". The latter form shows what happens when the generics are erased
  90. */
  91. public static String typesToSignature(UnresolvedType returnType, UnresolvedType[] paramTypes, boolean eraseGenerics) {
  92. StringBuilder buf = new StringBuilder();
  93. buf.append("(");
  94. for (UnresolvedType paramType : paramTypes) {
  95. if (eraseGenerics) {
  96. buf.append(paramType.getErasureSignature());
  97. } else {
  98. buf.append(paramType.getSignature());
  99. }
  100. }
  101. buf.append(")");
  102. if (eraseGenerics) {
  103. buf.append(returnType.getErasureSignature());
  104. } else {
  105. buf.append(returnType.getSignature());
  106. }
  107. return buf.toString();
  108. }
  109. /**
  110. * Returns "(&lt;signaturesOfParamTypes&gt;,...)" - unlike the other typesToSignature that also includes the return type, this one
  111. * just deals with the parameter types.
  112. */
  113. public static String typesToSignature(UnresolvedType[] paramTypes) {
  114. StringBuilder buf = new StringBuilder();
  115. buf.append("(");
  116. for (UnresolvedType paramType : paramTypes) {
  117. buf.append(paramType.getSignature());
  118. }
  119. buf.append(")");
  120. return buf.toString();
  121. }
  122. /**
  123. * returns an Object[] pair of UnresolvedType, UnresolvedType[] representing return type, argument types parsed from the JVM
  124. * bytecode signature of a method. Yes, this should actually return a nice statically-typed pair object, but we don't have one
  125. * of those.
  126. *
  127. * <blockquote>
  128. *
  129. * <pre>
  130. * UnresolvedType.signatureToTypes(&quot;()[Z&quot;)[0].equals(Type.forSignature(&quot;[Z&quot;))
  131. * UnresolvedType.signatureToTypes(&quot;(JJ)I&quot;)[1]
  132. * .equals(UnresolvedType.forSignatures(new String[] {&quot;J&quot;, &quot;J&quot;}))
  133. * </pre>
  134. *
  135. * </blockquote>
  136. *
  137. * @param erasedSignature the JVM bytecode method signature string we want to break apart
  138. * @return a pair of UnresolvedType, UnresolvedType[] representing the return types and parameter types.
  139. */
  140. private static Object[] signatureToTypes(String sig) {
  141. boolean hasParameters = sig.charAt(1) != ')';
  142. if (hasParameters) {
  143. List<UnresolvedType> l = new ArrayList<>();
  144. int i = 1;
  145. boolean hasAnyAnglies = sig.indexOf('<') != -1;
  146. while (true) {
  147. char c = sig.charAt(i);
  148. if (c == ')') {
  149. break; // break out when the hit the ')'
  150. }
  151. int start = i;
  152. while (c == '[') {
  153. c = sig.charAt(++i);
  154. }
  155. if (c == 'L' || c == 'P') {
  156. int nextSemicolon = sig.indexOf(';', start);
  157. int firstAngly = (hasAnyAnglies ? sig.indexOf('<', start) : -1);
  158. if (!hasAnyAnglies || firstAngly == -1 || firstAngly > nextSemicolon) {
  159. i = nextSemicolon + 1;
  160. l.add(UnresolvedType.forSignature(sig.substring(start, i)));
  161. } else {
  162. // generics generics generics
  163. // Have to skip to the *correct* ';'
  164. boolean endOfSigReached = false;
  165. int posn = firstAngly;
  166. int genericDepth = 0;
  167. while (!endOfSigReached) {
  168. switch (sig.charAt(posn)) {
  169. case '<':
  170. genericDepth++;
  171. break;
  172. case '>':
  173. genericDepth--;
  174. break;
  175. case ';':
  176. if (genericDepth == 0) {
  177. endOfSigReached = true;
  178. }
  179. break;
  180. default:
  181. }
  182. posn++;
  183. }
  184. // posn now points to the correct nextSemicolon :)
  185. i = posn;
  186. l.add(UnresolvedType.forSignature(sig.substring(start, i)));
  187. }
  188. } else if (c == 'T') { // assumed 'reference' to a type
  189. // variable, so just "Tname;"
  190. int nextSemicolon = sig.indexOf(';', start);
  191. String nextbit = sig.substring(start, nextSemicolon + 1);
  192. l.add(UnresolvedType.forSignature(nextbit));
  193. i = nextSemicolon + 1;
  194. } else {
  195. i++;
  196. l.add(UnresolvedType.forSignature(sig.substring(start, i)));
  197. }
  198. }
  199. UnresolvedType[] paramTypes = l.toArray(UnresolvedType.NONE);
  200. UnresolvedType returnType = UnresolvedType.forSignature(sig.substring(i + 1, sig.length()));
  201. return new Object[] { returnType, paramTypes };
  202. } else {
  203. UnresolvedType returnType = UnresolvedType.forSignature(sig.substring(2));
  204. return new Object[] { returnType, UnresolvedType.NONE };
  205. }
  206. }
  207. // ---- factory methods
  208. public static MemberImpl field(String declaring, int mods, String name, String signature) {
  209. return field(declaring, mods, UnresolvedType.forSignature(signature), name);
  210. }
  211. // OPTIMIZE do we need to call this? unless necessary the signatureToTypes()
  212. // call smacks of laziness on the behalf of the caller of this method
  213. public static MemberImpl method(UnresolvedType declaring, int mods, String name, String signature) {
  214. Object[] pair = signatureToTypes(signature);
  215. return method(declaring, mods, (UnresolvedType) pair[0], name, (UnresolvedType[]) pair[1]);
  216. }
  217. public static MemberImpl monitorEnter() {
  218. return new MemberImpl(MONITORENTER, UnresolvedType.OBJECT, Modifier.STATIC, UnresolvedType.VOID, "<lock>",
  219. UnresolvedType.ARRAY_WITH_JUST_OBJECT);
  220. }
  221. public static MemberImpl monitorExit() {
  222. return new MemberImpl(MONITOREXIT, UnresolvedType.OBJECT, Modifier.STATIC, UnresolvedType.VOID, "<unlock>",
  223. UnresolvedType.ARRAY_WITH_JUST_OBJECT);
  224. }
  225. public static Member pointcut(UnresolvedType declaring, String name, String signature) {
  226. Object[] pair = signatureToTypes(signature);
  227. return pointcut(declaring, 0, (UnresolvedType) pair[0], name, (UnresolvedType[]) pair[1]);
  228. }
  229. private static MemberImpl field(String declaring, int mods, UnresolvedType ty, String name) {
  230. return new MemberImpl(FIELD, UnresolvedType.forName(declaring), mods, ty, name, UnresolvedType.NONE);
  231. }
  232. public static MemberImpl method(UnresolvedType declTy, int mods, UnresolvedType rTy, String name, UnresolvedType[] paramTys) {
  233. return new MemberImpl(
  234. // ??? this calls <clinit> a method
  235. name.equals("<init>") ? CONSTRUCTOR : METHOD, declTy, mods, rTy, name, paramTys);
  236. }
  237. private static Member pointcut(UnresolvedType declTy, int mods, UnresolvedType rTy, String name, UnresolvedType[] paramTys) {
  238. return new MemberImpl(POINTCUT, declTy, mods, rTy, name, paramTys);
  239. }
  240. public static ResolvedMemberImpl makeExceptionHandlerSignature(UnresolvedType inType, UnresolvedType catchType) {
  241. return new ResolvedMemberImpl(HANDLER, inType, Modifier.STATIC, "<catch>", "(" + catchType.getSignature() + ")V");
  242. }
  243. @Override
  244. public final boolean equals(Object other) {
  245. if (!(other instanceof Member)) {
  246. return false;
  247. }
  248. Member o = (Member) other;
  249. return (getKind() == o.getKind() && getName().equals(o.getName()) && getSignature().equals(o.getSignature()) && getDeclaringType()
  250. .equals(o.getDeclaringType()));
  251. }
  252. /**
  253. * @return true if this member equals the one supplied in every respect other than the declaring type
  254. */
  255. public final boolean equalsApartFromDeclaringType(Object other) {
  256. if (!(other instanceof Member)) {
  257. return false;
  258. }
  259. Member o = (Member) other;
  260. return (getKind() == o.getKind() && getName().equals(o.getName()) && getSignature().equals(o.getSignature()));
  261. }
  262. /**
  263. * Equality is checked based on the underlying signature, so the hash code of a member is based on its kind, name, signature,
  264. * and declaring type. The algorithm for this was taken from page 38 of effective java.
  265. */
  266. private volatile int hashCode = 0;
  267. @Override
  268. public int hashCode() {
  269. if (hashCode == 0) {
  270. int result = 17;
  271. result = 37 * result + getKind().hashCode();
  272. result = 37 * result + getName().hashCode();
  273. result = 37 * result + getSignature().hashCode();
  274. result = 37 * result + getDeclaringType().hashCode();
  275. hashCode = result;
  276. }
  277. return hashCode;
  278. }
  279. public int compareTo(Member other) {
  280. Member o = other;
  281. int i = getName().compareTo(o.getName());
  282. if (i != 0) {
  283. return i;
  284. }
  285. return getSignature().compareTo(o.getSignature());
  286. }
  287. @Override
  288. public String toString() {
  289. StringBuilder buf = new StringBuilder();
  290. buf.append(returnType.getName());
  291. buf.append(' ');
  292. if (declaringType == null) {
  293. buf.append("<NULL>");
  294. } else {
  295. buf.append(declaringType.getName());
  296. }
  297. buf.append('.');
  298. buf.append(name);
  299. if (kind != FIELD) {
  300. buf.append("(");
  301. if (parameterTypes.length != 0) {
  302. buf.append(parameterTypes[0]);
  303. for (int i = 1, len = parameterTypes.length; i < len; i++) {
  304. buf.append(", ");
  305. buf.append(parameterTypes[i].getName());
  306. }
  307. }
  308. buf.append(")");
  309. }
  310. return buf.toString();
  311. }
  312. public MemberKind getKind() {
  313. return kind;
  314. }
  315. public UnresolvedType getDeclaringType() {
  316. return declaringType;
  317. }
  318. public UnresolvedType getReturnType() {
  319. return returnType;
  320. }
  321. public UnresolvedType getGenericReturnType() {
  322. return getReturnType();
  323. }
  324. public UnresolvedType[] getGenericParameterTypes() {
  325. return getParameterTypes();
  326. }
  327. public final UnresolvedType getType() {
  328. return returnType;
  329. }
  330. public String getName() {
  331. return name;
  332. }
  333. public UnresolvedType[] getParameterTypes() {
  334. return parameterTypes;
  335. }
  336. public String getSignature() {
  337. return erasedSignature;
  338. }
  339. public int getArity() {
  340. return parameterTypes.length;
  341. }
  342. public String getParameterSignature() {
  343. if (paramSignature == null) {
  344. StringBuilder sb = new StringBuilder("(");
  345. for (UnresolvedType parameterType : parameterTypes) {
  346. sb.append(parameterType.getSignature());
  347. }
  348. paramSignature = sb.append(")").toString();
  349. }
  350. return paramSignature;
  351. }
  352. // OPTIMIZE see next line. Why the hell are they in here if we only know it
  353. // once resolution has occurred...
  354. // ---- things we know only with resolution
  355. public int getModifiers(World world) {
  356. ResolvedMember resolved = resolve(world);
  357. if (resolved == null) {
  358. reportDidntFindMember(world);
  359. return 0;
  360. }
  361. return resolved.getModifiers();
  362. }
  363. public UnresolvedType[] getExceptions(World world) {
  364. ResolvedMember resolved = resolve(world);
  365. if (resolved == null) {
  366. reportDidntFindMember(world);
  367. return UnresolvedType.NONE;
  368. }
  369. return resolved.getExceptions();
  370. }
  371. public final boolean isStatic() {
  372. return Modifier.isStatic(modifiers);
  373. }
  374. public final boolean isInterface() {
  375. return Modifier.isInterface(modifiers);
  376. }
  377. public final boolean isPrivate() {
  378. return Modifier.isPrivate(modifiers);
  379. }
  380. public boolean canBeParameterized() {
  381. return false;
  382. }
  383. public int getModifiers() {
  384. return modifiers;
  385. }
  386. public AnnotationAJ[] getAnnotations() {
  387. throw new UnsupportedOperationException("You should resolve this member '" + this
  388. + "' and call getAnnotations() on the result...");
  389. }
  390. // ---- fields 'n' stuff
  391. public Collection<ResolvedType> getDeclaringTypes(World world) {
  392. ResolvedType myType = getDeclaringType().resolve(world);
  393. Collection<ResolvedType> ret = new HashSet<>();
  394. if (kind == CONSTRUCTOR) {
  395. // this is wrong if the member doesn't exist, but that doesn't
  396. // matter
  397. ret.add(myType);
  398. } else if (Modifier.isStatic(modifiers) || kind == FIELD) {
  399. walkUpStatic(ret, myType);
  400. } else {
  401. walkUp(ret, myType);
  402. }
  403. return ret;
  404. }
  405. private boolean walkUp(Collection<ResolvedType> acc, ResolvedType curr) {
  406. if (acc.contains(curr)) {
  407. return true;
  408. }
  409. boolean b = false;
  410. for (Iterator<ResolvedType> i = curr.getDirectSupertypes(); i.hasNext();) {
  411. b |= walkUp(acc, i.next());
  412. }
  413. if (!b && curr.isParameterizedType()) {
  414. b = walkUp(acc, curr.getGenericType());
  415. }
  416. if (!b) {
  417. b = curr.lookupMemberNoSupers(this) != null;
  418. }
  419. if (b) {
  420. acc.add(curr);
  421. }
  422. return b;
  423. }
  424. private boolean walkUpStatic(Collection<ResolvedType> acc, ResolvedType curr) {
  425. if (curr.lookupMemberNoSupers(this) != null) {
  426. acc.add(curr);
  427. return true;
  428. } else {
  429. boolean b = false;
  430. for (Iterator<ResolvedType> i = curr.getDirectSupertypes(); i.hasNext();) {
  431. b |= walkUpStatic(acc, i.next());
  432. }
  433. if (!b && curr.isParameterizedType()) {
  434. b = walkUpStatic(acc, curr.getGenericType());
  435. }
  436. if (b) {
  437. acc.add(curr);
  438. }
  439. return b;
  440. }
  441. }
  442. public String[] getParameterNames(World world) {
  443. ResolvedMember resolved = resolve(world);
  444. if (resolved == null) {
  445. reportDidntFindMember(world);
  446. return null;
  447. }
  448. return resolved.getParameterNames();
  449. }
  450. /**
  451. * All the signatures that a join point with this member as its signature has.
  452. */
  453. public JoinPointSignatureIterator getJoinPointSignatures(World inAWorld) {
  454. if (joinPointSignatures == null) {
  455. joinPointSignatures = new JoinPointSignatureIterator(this, inAWorld);
  456. }
  457. joinPointSignatures.reset();
  458. return joinPointSignatures;
  459. }
  460. /**
  461. * Raises an [Xlint:cantFindType] message if the declaring type cannot be found or an [Xlint:unresolvableMember] message if the
  462. * type can be found (bug 149908)
  463. */
  464. private void reportDidntFindMember(World world) {
  465. if (reportedCantFindDeclaringType || reportedUnresolvableMember) {
  466. return;
  467. }
  468. ResolvedType rType = getDeclaringType().resolve(world);
  469. if (rType.isMissing()) {
  470. world.getLint().cantFindType.signal(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE, rType.getName()), null);
  471. reportedCantFindDeclaringType = true;
  472. } else {
  473. world.getLint().unresolvableMember.signal(getName(), null);
  474. reportedUnresolvableMember = true;
  475. }
  476. }
  477. public void wipeJoinpointSignatures() {
  478. joinPointSignatures = null;
  479. }
  480. }