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.

CrosscuttingMembersSet.java 16KB

15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /* *******************************************************************
  2. * Copyright (c) 2002-2009 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://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver;
  13. import java.io.IOException;
  14. import java.util.ArrayList;
  15. import java.util.Collections;
  16. import java.util.HashMap;
  17. import java.util.HashSet;
  18. import java.util.Iterator;
  19. import java.util.LinkedHashSet;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.Set;
  23. import org.aspectj.bridge.IMessage;
  24. import org.aspectj.bridge.MessageUtil;
  25. import org.aspectj.weaver.patterns.Declare;
  26. import org.aspectj.weaver.patterns.DeclareAnnotation;
  27. import org.aspectj.weaver.patterns.DeclareParents;
  28. import org.aspectj.weaver.patterns.DeclareSoft;
  29. import org.aspectj.weaver.patterns.DeclareTypeErrorOrWarning;
  30. import org.aspectj.weaver.patterns.IVerificationRequired;
  31. /**
  32. * This holds on to all CrosscuttingMembers for a world. It handles management of change.
  33. *
  34. * @author Jim Hugunin
  35. * @author Andy Clement
  36. */
  37. public class CrosscuttingMembersSet {
  38. private transient World world;
  39. // FIXME AV - ? we may need a sequencedHashMap there to ensure source based precedence for @AJ advice
  40. private final Map<ResolvedType, CrosscuttingMembers> members = new HashMap<ResolvedType, CrosscuttingMembers>();
  41. // List of things to be verified once the type system is 'complete'
  42. private transient List<IVerificationRequired> verificationList = null;
  43. private List<ShadowMunger> shadowMungers = null;
  44. private List<ConcreteTypeMunger> typeMungers = null;
  45. private List<ConcreteTypeMunger> lateTypeMungers = null;
  46. private List<DeclareSoft> declareSofts = null;
  47. private List<DeclareParents> declareParents = null;
  48. private List<DeclareAnnotation> declareAnnotationOnTypes = null;
  49. private List<DeclareAnnotation> declareAnnotationOnFields = null;
  50. private List<DeclareAnnotation> declareAnnotationOnMethods = null; // includes constructors
  51. private List<DeclareTypeErrorOrWarning> declareTypeEows = null;
  52. private List<Declare> declareDominates = null;
  53. private boolean changedSinceLastReset = false;
  54. public CrosscuttingMembersSet(World world) {
  55. this.world = world;
  56. }
  57. public boolean addOrReplaceAspect(ResolvedType aspectType) {
  58. return addOrReplaceAspect(aspectType, true);
  59. }
  60. /**
  61. * Check if any parent aspects of the supplied aspect have unresolved dependencies (and so
  62. * should cause this aspect to be turned off).
  63. * @param aspectType the aspect whose parents should be checked
  64. * @return true if this aspect should be excluded because of a parents' missing dependencies
  65. */
  66. private boolean excludeDueToParentAspectHavingUnresolvedDependency(ResolvedType aspectType) {
  67. ResolvedType parent = aspectType.getSuperclass();
  68. boolean excludeDueToParent = false;
  69. while (parent != null) {
  70. if (parent.isAspect() && parent.isAbstract() && world.hasUnsatisfiedDependency(parent)) {
  71. if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
  72. world.getMessageHandler().handleMessage(
  73. MessageUtil.info("deactivating aspect '" + aspectType.getName() + "' as the parent aspect '"+parent.getName()+
  74. "' has unsatisfied dependencies"));
  75. }
  76. excludeDueToParent = true;
  77. }
  78. parent = parent.getSuperclass();
  79. }
  80. return excludeDueToParent;
  81. }
  82. /**
  83. * @return whether or not that was a change to the global signature XXX for efficiency we will need a richer representation than
  84. * this
  85. */
  86. public boolean addOrReplaceAspect(ResolvedType aspectType, boolean inWeavingPhase) {
  87. if (!world.isAspectIncluded(aspectType)) {
  88. return false;
  89. }
  90. if (world.hasUnsatisfiedDependency(aspectType)) {
  91. return false;
  92. }
  93. // Abstract super aspects might have unsatisfied dependencies
  94. if (excludeDueToParentAspectHavingUnresolvedDependency(aspectType)) {
  95. return false;
  96. }
  97. boolean change = false;
  98. CrosscuttingMembers xcut = members.get(aspectType);
  99. if (xcut == null) {
  100. members.put(aspectType, aspectType.collectCrosscuttingMembers(inWeavingPhase));
  101. clearCaches();
  102. change = true;
  103. } else {
  104. if (xcut.replaceWith(aspectType.collectCrosscuttingMembers(inWeavingPhase), inWeavingPhase)) {
  105. clearCaches();
  106. change = true;
  107. } else {
  108. if (inWeavingPhase) {
  109. // bug 134541 - even though we haven't changed we may have updated the
  110. // sourcelocation for the shadowMunger which we need to pick up
  111. shadowMungers = null;
  112. }
  113. change = false;
  114. }
  115. }
  116. if (aspectType.isAbstract()) {
  117. // we might have sub-aspects that need to re-collect their crosscutting members from us
  118. boolean ancestorChange = addOrReplaceDescendantsOf(aspectType, inWeavingPhase);
  119. change = change || ancestorChange;
  120. }
  121. changedSinceLastReset = changedSinceLastReset || change;
  122. return change;
  123. }
  124. private boolean addOrReplaceDescendantsOf(ResolvedType aspectType, boolean inWeavePhase) {
  125. // System.err.println("Looking at descendants of "+aspectType.getName());
  126. Set<ResolvedType> knownAspects = members.keySet();
  127. Set<ResolvedType> toBeReplaced = new HashSet<ResolvedType>();
  128. for (Iterator<ResolvedType> it = knownAspects.iterator(); it.hasNext();) {
  129. ResolvedType candidateDescendant = it.next();
  130. // allowMissing = true - if something is missing, it really probably is not a descendant
  131. if ((candidateDescendant != aspectType) && (aspectType.isAssignableFrom(candidateDescendant, true))) {
  132. toBeReplaced.add(candidateDescendant);
  133. }
  134. }
  135. boolean change = false;
  136. for (Iterator<ResolvedType> it = toBeReplaced.iterator(); it.hasNext();) {
  137. ResolvedType next = it.next();
  138. boolean thisChange = addOrReplaceAspect(next, inWeavePhase);
  139. change = change || thisChange;
  140. }
  141. return change;
  142. }
  143. public void addAdviceLikeDeclares(ResolvedType aspectType) {
  144. if (!members.containsKey(aspectType)) {
  145. return;
  146. }
  147. CrosscuttingMembers xcut = members.get(aspectType);
  148. xcut.addDeclares(aspectType.collectDeclares(true));
  149. }
  150. public boolean deleteAspect(UnresolvedType aspectType) {
  151. boolean isAspect = members.remove(aspectType) != null;
  152. clearCaches();
  153. return isAspect;
  154. }
  155. public boolean containsAspect(UnresolvedType aspectType) {
  156. return members.containsKey(aspectType);
  157. }
  158. // XXX only for testing
  159. public void addFixedCrosscuttingMembers(ResolvedType aspectType) {
  160. members.put(aspectType, aspectType.crosscuttingMembers);
  161. clearCaches();
  162. }
  163. private void clearCaches() {
  164. shadowMungers = null;
  165. typeMungers = null;
  166. lateTypeMungers = null;
  167. declareSofts = null;
  168. declareParents = null;
  169. declareAnnotationOnFields = null;
  170. declareAnnotationOnMethods = null;
  171. declareAnnotationOnTypes = null;
  172. declareDominates = null;
  173. }
  174. public List<ShadowMunger> getShadowMungers() {
  175. if (shadowMungers == null) {
  176. List<ShadowMunger> ret = new ArrayList<ShadowMunger>();
  177. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  178. ret.addAll(i.next().getShadowMungers());
  179. }
  180. shadowMungers = ret;
  181. }
  182. return shadowMungers;
  183. }
  184. public List<ConcreteTypeMunger> getTypeMungers() {
  185. if (typeMungers == null) {
  186. List<ConcreteTypeMunger> ret = new ArrayList<ConcreteTypeMunger>();
  187. for (CrosscuttingMembers xmembers : members.values()) {
  188. // With 1.6.9 there is a change that enables use of more optimal accessors (accessors for private fields).
  189. // Here is where we determine if two aspects are asking for access to the same field. If they are
  190. // and
  191. // In the new style multiple aspects can share the same privileged accessors, so here we check if
  192. // two aspects are asking for access to the same field. If they are then we don't add a duplicate
  193. // accessor.
  194. for (ConcreteTypeMunger mungerToAdd : xmembers.getTypeMungers()) {
  195. ResolvedTypeMunger resolvedMungerToAdd = mungerToAdd.getMunger();
  196. if (isNewStylePrivilegedAccessMunger(resolvedMungerToAdd)) {
  197. String newFieldName = resolvedMungerToAdd.getSignature().getName();
  198. boolean alreadyExists = false;
  199. for (ConcreteTypeMunger existingMunger : ret) {
  200. ResolvedTypeMunger existing = existingMunger.getMunger();
  201. if (isNewStylePrivilegedAccessMunger(existing)) {
  202. String existingFieldName = existing.getSignature().getName();
  203. if (existingFieldName.equals(newFieldName)
  204. && existing.getSignature().getDeclaringType().equals(
  205. resolvedMungerToAdd.getSignature().getDeclaringType())) {
  206. alreadyExists = true;
  207. break;
  208. }
  209. }
  210. }
  211. if (!alreadyExists) {
  212. ret.add(mungerToAdd);
  213. }
  214. } else {
  215. ret.add(mungerToAdd);
  216. }
  217. }
  218. }
  219. typeMungers = ret;
  220. }
  221. return typeMungers;
  222. }
  223. /**
  224. * Retrieve a subset of all known mungers, those of a specific kind.
  225. *
  226. * @param kind the kind of munger requested
  227. * @return a list of those mungers (list is empty if none found)
  228. */
  229. public List<ConcreteTypeMunger> getTypeMungersOfKind(ResolvedTypeMunger.Kind kind) {
  230. List<ConcreteTypeMunger> collected = null;
  231. for (ConcreteTypeMunger typeMunger : typeMungers) {
  232. if (typeMunger.getMunger() != null && typeMunger.getMunger().getKind() == kind) {
  233. if (collected == null) {
  234. collected = new ArrayList<ConcreteTypeMunger>();
  235. }
  236. collected.add(typeMunger);
  237. }
  238. }
  239. if (collected == null) {
  240. return Collections.emptyList();
  241. } else {
  242. return collected;
  243. }
  244. }
  245. /**
  246. * Determine if the type munger is: (1) for privileged access (2) for a normally non visible field (3) is from an aspect wanting
  247. * 'old style' (ie. long) accessor names
  248. */
  249. private boolean isNewStylePrivilegedAccessMunger(ResolvedTypeMunger typeMunger) {
  250. boolean b = (typeMunger != null && typeMunger.getKind() == ResolvedTypeMunger.PrivilegedAccess && typeMunger.getSignature()
  251. .getKind() == Member.FIELD);
  252. if (!b) {
  253. return b;
  254. }
  255. PrivilegedAccessMunger privAccessMunger = (PrivilegedAccessMunger) typeMunger;
  256. return privAccessMunger.shortSyntax;
  257. }
  258. public List<ConcreteTypeMunger> getLateTypeMungers() {
  259. if (lateTypeMungers == null) {
  260. List<ConcreteTypeMunger> ret = new ArrayList<ConcreteTypeMunger>();
  261. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  262. ret.addAll(i.next().getLateTypeMungers());
  263. }
  264. lateTypeMungers = ret;
  265. }
  266. return lateTypeMungers;
  267. }
  268. public List<DeclareSoft> getDeclareSofts() {
  269. if (declareSofts == null) {
  270. Set<DeclareSoft> ret = new HashSet<DeclareSoft>();
  271. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  272. ret.addAll(i.next().getDeclareSofts());
  273. }
  274. declareSofts = new ArrayList<DeclareSoft>();
  275. declareSofts.addAll(ret);
  276. }
  277. return declareSofts;
  278. }
  279. public List<DeclareParents> getDeclareParents() {
  280. if (declareParents == null) {
  281. Set<DeclareParents> ret = new HashSet<DeclareParents>();
  282. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  283. ret.addAll(i.next().getDeclareParents());
  284. }
  285. declareParents = new ArrayList<DeclareParents>();
  286. declareParents.addAll(ret);
  287. }
  288. return declareParents;
  289. }
  290. /**
  291. * @return an amalgamation of the declare @type statements.
  292. */
  293. public List<DeclareAnnotation> getDeclareAnnotationOnTypes() {
  294. if (declareAnnotationOnTypes == null) {
  295. Set<DeclareAnnotation> ret = new LinkedHashSet<DeclareAnnotation>();
  296. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  297. ret.addAll(i.next().getDeclareAnnotationOnTypes());
  298. }
  299. declareAnnotationOnTypes = new ArrayList<DeclareAnnotation>();
  300. declareAnnotationOnTypes.addAll(ret);
  301. }
  302. return declareAnnotationOnTypes;
  303. }
  304. /**
  305. * @return an amalgamation of the declare @field statements.
  306. */
  307. public List<DeclareAnnotation> getDeclareAnnotationOnFields() {
  308. if (declareAnnotationOnFields == null) {
  309. Set<DeclareAnnotation> ret = new LinkedHashSet<DeclareAnnotation>();
  310. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  311. ret.addAll(i.next().getDeclareAnnotationOnFields());
  312. }
  313. declareAnnotationOnFields = new ArrayList<DeclareAnnotation>();
  314. declareAnnotationOnFields.addAll(ret);
  315. }
  316. return declareAnnotationOnFields;
  317. }
  318. /**
  319. * @return an amalgamation of the declare @method/@constructor statements.
  320. */
  321. public List<DeclareAnnotation> getDeclareAnnotationOnMethods() {
  322. if (declareAnnotationOnMethods == null) {
  323. Set<DeclareAnnotation> ret = new LinkedHashSet<DeclareAnnotation>();
  324. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  325. ret.addAll(i.next().getDeclareAnnotationOnMethods());
  326. }
  327. declareAnnotationOnMethods = new ArrayList<DeclareAnnotation>();
  328. declareAnnotationOnMethods.addAll(ret);
  329. // world.sortDeclareAnnotations(declareAnnotationOnMethods);
  330. }
  331. return declareAnnotationOnMethods;
  332. }
  333. /**
  334. * Return an amalgamation of the declare type eow statements
  335. */
  336. public List<DeclareTypeErrorOrWarning> getDeclareTypeEows() {
  337. if (declareTypeEows == null) {
  338. Set<DeclareTypeErrorOrWarning> ret = new HashSet<DeclareTypeErrorOrWarning>();
  339. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  340. ret.addAll(i.next().getDeclareTypeErrorOrWarning());
  341. }
  342. declareTypeEows = new ArrayList<DeclareTypeErrorOrWarning>();
  343. declareTypeEows.addAll(ret);
  344. }
  345. return declareTypeEows;
  346. }
  347. public List<Declare> getDeclareDominates() {
  348. if (declareDominates == null) {
  349. List<Declare> ret = new ArrayList<Declare>();
  350. for (Iterator<CrosscuttingMembers> i = members.values().iterator(); i.hasNext();) {
  351. ret.addAll(i.next().getDeclareDominates());
  352. }
  353. declareDominates = ret;
  354. }
  355. return declareDominates;
  356. }
  357. public ResolvedType findAspectDeclaringParents(DeclareParents p) {
  358. Set<ResolvedType> keys = this.members.keySet();
  359. for (Iterator<ResolvedType> iter = keys.iterator(); iter.hasNext();) {
  360. ResolvedType element = iter.next();
  361. for (Iterator i = members.get(element).getDeclareParents().iterator(); i.hasNext();) {
  362. DeclareParents dp = (DeclareParents) i.next();
  363. if (dp.equals(p)) {
  364. return element;
  365. }
  366. }
  367. }
  368. return null;
  369. }
  370. public void reset() {
  371. verificationList = null;
  372. changedSinceLastReset = false;
  373. }
  374. public boolean hasChangedSinceLastReset() {
  375. return changedSinceLastReset;
  376. }
  377. /**
  378. * Record something that needs verifying when we believe the type system is complete. Used for things that can't be verified as
  379. * we go along - for example some recursive type variable references (pr133307)
  380. */
  381. public void recordNecessaryCheck(IVerificationRequired verification) {
  382. if (verificationList == null) {
  383. verificationList = new ArrayList<IVerificationRequired>();
  384. }
  385. verificationList.add(verification);
  386. }
  387. /**
  388. * Called when type bindings are complete - calls all registered verification objects in turn.
  389. */
  390. public void verify() {
  391. if (verificationList == null) {
  392. return;
  393. }
  394. for (Iterator<IVerificationRequired> iter = verificationList.iterator(); iter.hasNext();) {
  395. IVerificationRequired element = iter.next();
  396. element.verify();
  397. }
  398. verificationList = null;
  399. }
  400. public int serializationVersion = 1;
  401. public void write(CompressingDataOutputStream stream) throws IOException {
  402. // stream.writeInt(serializationVersion);
  403. stream.writeInt(shadowMungers.size());
  404. for (Iterator iterator = shadowMungers.iterator(); iterator.hasNext();) {
  405. ShadowMunger shadowMunger = (ShadowMunger) iterator.next();
  406. shadowMunger.write(stream);
  407. }
  408. // // private List /* ShadowMunger */shadowMungers = null;
  409. // // private List typeMungers = null;
  410. // // private List lateTypeMungers = null;
  411. // // private List declareSofts = null;
  412. // // private List declareParents = null;
  413. // // private List declareAnnotationOnTypes = null;
  414. // // private List declareAnnotationOnFields = null;
  415. // // private List declareAnnotationOnMethods = null; // includes constructors
  416. // // private List declareDominates = null;
  417. // // private boolean changedSinceLastReset = false;
  418. //
  419. }
  420. }