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.

JoinPointSignatureIterator.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /* *******************************************************************
  2. * Copyright (c) 2005 Contributors.
  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://eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Adrian Colyer Initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver;
  13. import java.lang.reflect.Modifier;
  14. import java.util.ArrayList;
  15. import java.util.Collections;
  16. import java.util.HashSet;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.NoSuchElementException;
  20. import java.util.Set;
  21. /**
  22. * Iterates over the signatures of a join point, calculating new signatures lazily to minimize processing and to avoid unneccessary
  23. * "can't find type" errors. Iterator can be cached and reused by calling the "reset" method between iterations.
  24. */
  25. public class JoinPointSignatureIterator implements Iterator<JoinPointSignature> {
  26. ResolvedType firstDefiningType;
  27. private Member signaturesOfMember;
  28. private ResolvedMember firstDefiningMember;
  29. private World world;
  30. private List<JoinPointSignature> discoveredSignatures = new ArrayList<JoinPointSignature>();
  31. private List<JoinPointSignature> additionalSignatures = Collections.emptyList();
  32. private Iterator<JoinPointSignature> discoveredSignaturesIterator = null;
  33. private Iterator<ResolvedType> superTypeIterator = null;
  34. private boolean isProxy = false;
  35. private Set<ResolvedType> visitedSuperTypes = new HashSet<ResolvedType>();
  36. private List<SearchPair> yetToBeProcessedSuperMembers = null;
  37. private boolean iteratingOverDiscoveredSignatures = true;
  38. private boolean couldBeFurtherAsYetUndiscoveredSignatures = true;
  39. private final static UnresolvedType jlrProxy = UnresolvedType.forSignature("Ljava/lang/reflect/Proxy;");
  40. public JoinPointSignatureIterator(Member joinPointSignature, World world) {
  41. this.signaturesOfMember = joinPointSignature;
  42. this.world = world;
  43. addSignaturesUpToFirstDefiningMember();
  44. if (!shouldWalkUpHierarchy()) {
  45. couldBeFurtherAsYetUndiscoveredSignatures = false;
  46. }
  47. }
  48. public void reset() {
  49. discoveredSignaturesIterator = discoveredSignatures.iterator();
  50. additionalSignatures.clear();
  51. iteratingOverDiscoveredSignatures = true;
  52. }
  53. public boolean hasNext() {
  54. if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
  55. return true;
  56. } else if (couldBeFurtherAsYetUndiscoveredSignatures) {
  57. if (additionalSignatures.size() > 0) {
  58. return true;
  59. } else {
  60. return findSignaturesFromSupertypes();
  61. }
  62. } else {
  63. return false;
  64. }
  65. }
  66. public JoinPointSignature next() {
  67. if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
  68. return discoveredSignaturesIterator.next();
  69. } else {
  70. if (additionalSignatures.size() > 0) {
  71. return additionalSignatures.remove(0);
  72. }
  73. }
  74. throw new NoSuchElementException();
  75. }
  76. public void remove() {
  77. throw new UnsupportedOperationException("can't remove from JoinPointSignatureIterator");
  78. }
  79. /**
  80. * Walk up the hierarchy creating one member for each type up to and including the first defining type.
  81. */
  82. private void addSignaturesUpToFirstDefiningMember() {
  83. ResolvedType originalDeclaringType = signaturesOfMember.getDeclaringType().resolve(world);
  84. ResolvedType superType = originalDeclaringType.getSuperclass();
  85. if (superType != null && superType.equals(jlrProxy)) {
  86. // Proxy types are generated without any regard to generics (pr268419) and so the member walking
  87. // should also ignore them
  88. isProxy = true;
  89. }
  90. // is it the array constructor join point?
  91. if (world.isJoinpointArrayConstructionEnabled() && originalDeclaringType.isArray()) {
  92. Member m = signaturesOfMember;
  93. ResolvedMember rm = new ResolvedMemberImpl(m.getKind(), m.getDeclaringType(), m.getModifiers(), m.getReturnType(), m
  94. .getName(), m.getParameterTypes());
  95. discoveredSignatures.add(new JoinPointSignature(rm, originalDeclaringType));
  96. couldBeFurtherAsYetUndiscoveredSignatures = false;
  97. return;
  98. }
  99. firstDefiningMember = (signaturesOfMember instanceof ResolvedMember ?
  100. (ResolvedMember) signaturesOfMember: signaturesOfMember.resolve(world));
  101. if (firstDefiningMember == null) {
  102. couldBeFurtherAsYetUndiscoveredSignatures = false;
  103. return;
  104. }
  105. // declaringType can be unresolved if we matched a synthetic member generated by Aj...
  106. // should be fixed elsewhere but add this resolve call on the end for now so that we can
  107. // focus on one problem at a time...
  108. firstDefiningType = firstDefiningMember.getDeclaringType().resolve(world);
  109. if (firstDefiningType != originalDeclaringType) {
  110. if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) {
  111. return;
  112. }
  113. }
  114. if (originalDeclaringType == firstDefiningType) {
  115. // a common case
  116. discoveredSignatures.add(new JoinPointSignature(firstDefiningMember, originalDeclaringType));
  117. } else {
  118. List<ResolvedType> declaringTypes = new ArrayList<ResolvedType>();
  119. accumulateTypesInBetween(originalDeclaringType, firstDefiningType, declaringTypes);
  120. for (ResolvedType declaringType : declaringTypes) {
  121. discoveredSignatures.add(new JoinPointSignature(firstDefiningMember, declaringType));
  122. }
  123. }
  124. }
  125. /**
  126. * Build a list containing every type between subtype and supertype, inclusively.
  127. */
  128. private void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List<ResolvedType> types) {
  129. types.add(subType);
  130. if (subType == superType) {
  131. return;
  132. } else {
  133. for (Iterator<ResolvedType> iter = subType.getDirectSupertypes(); iter.hasNext();) {
  134. ResolvedType parent = iter.next();
  135. if (superType.isAssignableFrom(parent, true)) {
  136. accumulateTypesInBetween(parent, superType, types);
  137. }
  138. }
  139. }
  140. }
  141. private boolean shouldWalkUpHierarchy() {
  142. if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) {
  143. return false;
  144. }
  145. if (signaturesOfMember.getKind() == Member.FIELD) {
  146. return false;
  147. }
  148. if (Modifier.isStatic(signaturesOfMember.getModifiers())) {
  149. return false;
  150. }
  151. return true;
  152. }
  153. private boolean findSignaturesFromSupertypes() {
  154. iteratingOverDiscoveredSignatures = false;
  155. if (superTypeIterator == null) {
  156. superTypeIterator = firstDefiningType.getDirectSupertypes();
  157. }
  158. if (superTypeIterator.hasNext()) {
  159. ResolvedType superType = superTypeIterator.next();
  160. if (isProxy && (superType.isGenericType() || superType.isParameterizedType())) {
  161. superType = superType.getRawType();
  162. }
  163. if (visitedSuperTypes.contains(superType)) {
  164. return findSignaturesFromSupertypes();
  165. } else {
  166. // we haven't looked in this type yet
  167. visitedSuperTypes.add(superType);
  168. if (superType.isMissing()) {
  169. // issue a warning, stop looking for join point signatures in this line
  170. warnOnMissingType(superType);
  171. return findSignaturesFromSupertypes();
  172. }
  173. ResolvedMemberImpl foundMember = (ResolvedMemberImpl) superType.lookupResolvedMember(firstDefiningMember, true,
  174. isProxy);
  175. if (foundMember != null && isVisibleTo(firstDefiningMember, foundMember)) {
  176. List<ResolvedType> declaringTypes = new ArrayList<ResolvedType>();
  177. // declaring type can be unresolved if the member can from an ITD...
  178. ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(world);
  179. accumulateTypesInBetween(superType, resolvedDeclaringType, declaringTypes);
  180. for (ResolvedType declaringType : declaringTypes) {
  181. JoinPointSignature member = null;
  182. if (isProxy) {
  183. if (declaringType.isGenericType() || declaringType.isParameterizedType()) {
  184. declaringType = declaringType.getRawType();
  185. }
  186. }
  187. member = new JoinPointSignature(foundMember, declaringType);
  188. discoveredSignatures.add(member); // for next time we are reset
  189. if (additionalSignatures == Collections.EMPTY_LIST) {
  190. additionalSignatures = new ArrayList<JoinPointSignature>();
  191. }
  192. additionalSignatures.add(member); // for this time
  193. }
  194. // if this was a parameterized type, look in the generic type that backs it too
  195. if (!isProxy && superType.isParameterizedType() && (foundMember.backingGenericMember != null)) {
  196. JoinPointSignature member = new JoinPointSignature(foundMember.backingGenericMember,
  197. foundMember.declaringType.resolve(world));
  198. discoveredSignatures.add(member); // for next time we are reset
  199. if (additionalSignatures == Collections.EMPTY_LIST) {
  200. additionalSignatures = new ArrayList<JoinPointSignature>();
  201. }
  202. additionalSignatures.add(member); // for this time
  203. }
  204. if (yetToBeProcessedSuperMembers == null) {
  205. yetToBeProcessedSuperMembers = new ArrayList<SearchPair>();
  206. }
  207. yetToBeProcessedSuperMembers.add(new SearchPair(foundMember, superType));
  208. return true;
  209. } else {
  210. return findSignaturesFromSupertypes();
  211. }
  212. }
  213. }
  214. if (yetToBeProcessedSuperMembers != null && !yetToBeProcessedSuperMembers.isEmpty()) {
  215. SearchPair nextUp = yetToBeProcessedSuperMembers.remove(0);
  216. firstDefiningType = nextUp.type;
  217. firstDefiningMember = nextUp.member;
  218. superTypeIterator = null;
  219. return findSignaturesFromSupertypes();
  220. }
  221. couldBeFurtherAsYetUndiscoveredSignatures = false;
  222. return false;
  223. }
  224. /**
  225. * Returns true if the parent member is visible to the child member In the same declaring type this is always true, otherwise if
  226. * parent is private it is false.
  227. *
  228. * @param childMember
  229. * @param parentMember
  230. * @return
  231. */
  232. private boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) {
  233. if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) {
  234. return true;
  235. }
  236. if (Modifier.isPrivate(parentMember.getModifiers())) {
  237. return false;
  238. } else {
  239. return true;
  240. }
  241. }
  242. private void warnOnMissingType(ResolvedType missing) {
  243. if (missing instanceof MissingResolvedTypeWithKnownSignature) {
  244. // which it should be...
  245. MissingResolvedTypeWithKnownSignature mrt = (MissingResolvedTypeWithKnownSignature) missing;
  246. mrt.raiseWarningOnJoinPointSignature(signaturesOfMember.toString());
  247. }
  248. }
  249. private static class SearchPair {
  250. public ResolvedMember member;
  251. public ResolvedType type;
  252. public SearchPair(ResolvedMember member, ResolvedType type) {
  253. this.member = member;
  254. this.type = type;
  255. }
  256. }
  257. }