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.

World.java 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * 2005 Contributors
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Common Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/cpl-v10.html
  9. *
  10. * Contributors:
  11. * PARC initial implementation
  12. * Adrian Colyer, Andy Clement, overhaul for generics
  13. * ******************************************************************/
  14. package org.aspectj.weaver;
  15. import java.util.ArrayList;
  16. import java.util.HashMap;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Map;
  20. import java.util.Set;
  21. import java.util.WeakHashMap;
  22. import org.aspectj.asm.IHierarchy;
  23. import org.aspectj.bridge.IMessage;
  24. import org.aspectj.bridge.IMessageHandler;
  25. import org.aspectj.bridge.ISourceLocation;
  26. import org.aspectj.bridge.Message;
  27. import org.aspectj.bridge.MessageUtil;
  28. import org.aspectj.bridge.IMessage.Kind;
  29. import org.aspectj.bridge.context.PinpointingMessageHandler;
  30. import org.aspectj.weaver.UnresolvedType.TypeKind;
  31. import org.aspectj.weaver.patterns.DeclarePrecedence;
  32. import org.aspectj.weaver.patterns.PerClause;
  33. import org.aspectj.weaver.patterns.Pointcut;
  34. /**
  35. * A World is a collection of known types and crosscutting members.
  36. */
  37. public abstract class World implements Dump.INode {
  38. /** handler for any messages produced during resolution etc. */
  39. private IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR;
  40. /** handler for cross-reference information produced during the weaving process */
  41. private ICrossReferenceHandler xrefHandler = null;
  42. /** Currently 'active' scope in which to lookup (resolve) typevariable references */
  43. private TypeVariableDeclaringElement typeVariableLookupScope;
  44. /** The heart of the world, a map from type signatures to resolved types */
  45. protected TypeMap typeMap = new TypeMap(); // Signature to ResolvedType
  46. /** Calculator for working out aspect precedence */
  47. private AspectPrecedenceCalculator precedenceCalculator;
  48. /** All of the type and shadow mungers known to us */
  49. private CrosscuttingMembersSet crosscuttingMembersSet =
  50. new CrosscuttingMembersSet(this);
  51. /** Model holds ASM relationships */
  52. private IHierarchy model = null;
  53. /** for processing Xlint messages */
  54. private Lint lint = new Lint(this);
  55. /** XnoInline option setting passed down to weaver */
  56. private boolean XnoInline;
  57. /** XlazyTjp option setting passed down to weaver */
  58. private boolean XlazyTjp;
  59. /** XhasMember option setting passed down to weaver */
  60. private boolean XhasMember = false;
  61. /** Xpinpoint controls whether we put out developer info showing the source of messages */
  62. private boolean Xpinpoint = false;
  63. /** When behaving in a Java 5 way autoboxing is considered */
  64. private boolean behaveInJava5Way = false;
  65. /**
  66. * A list of RuntimeExceptions containing full stack information for every
  67. * type we couldn't find.
  68. */
  69. private List dumpState_cantFindTypeExceptions = null;
  70. /**
  71. * Play God.
  72. * On the first day, God created the primitive types and put them in the type
  73. * map.
  74. */
  75. protected World() {
  76. super();
  77. Dump.registerNode(this.getClass(),this);
  78. typeMap.put("B", ResolvedType.BYTE);
  79. typeMap.put("S", ResolvedType.SHORT);
  80. typeMap.put("I", ResolvedType.INT);
  81. typeMap.put("J", ResolvedType.LONG);
  82. typeMap.put("F", ResolvedType.FLOAT);
  83. typeMap.put("D", ResolvedType.DOUBLE);
  84. typeMap.put("C", ResolvedType.CHAR);
  85. typeMap.put("Z", ResolvedType.BOOLEAN);
  86. typeMap.put("V", ResolvedType.VOID);
  87. precedenceCalculator = new AspectPrecedenceCalculator(this);
  88. }
  89. /**
  90. * Dump processing when a fatal error occurs
  91. */
  92. public void accept (Dump.IVisitor visitor) {
  93. visitor.visitString("Shadow mungers:");
  94. visitor.visitList(crosscuttingMembersSet.getShadowMungers());
  95. visitor.visitString("Type mungers:");
  96. visitor.visitList(crosscuttingMembersSet.getTypeMungers());
  97. visitor.visitString("Late Type mungers:");
  98. visitor.visitList(crosscuttingMembersSet.getLateTypeMungers());
  99. if (dumpState_cantFindTypeExceptions!=null) {
  100. visitor.visitString("Cant find type problems:");
  101. visitor.visitList(dumpState_cantFindTypeExceptions);
  102. dumpState_cantFindTypeExceptions = null;
  103. }
  104. }
  105. // =============================================================================
  106. // T Y P E R E S O L U T I O N
  107. // =============================================================================
  108. /**
  109. * Resolve a type that we require to be present in the world
  110. */
  111. public ResolvedType resolve(UnresolvedType ty) {
  112. return resolve(ty, false);
  113. }
  114. /**
  115. * Attempt to resolve a type - the source location gives you some context in which
  116. * resolution is taking place. In the case of an error where we can't find the
  117. * type - we can then at least report why (source location) we were trying to resolve it.
  118. */
  119. public ResolvedType resolve(UnresolvedType ty,ISourceLocation isl) {
  120. ResolvedType ret = resolve(ty,true);
  121. if (ty == ResolvedType.MISSING) {
  122. IMessage msg = null;
  123. if (isl!=null) {
  124. msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()),isl);
  125. } else {
  126. msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()));
  127. }
  128. messageHandler.handleMessage(msg);
  129. }
  130. return ret;
  131. }
  132. /**
  133. * Convenience method for resolving an array of unresolved types
  134. * in one hit. Useful for e.g. resolving type parameters in signatures.
  135. */
  136. public ResolvedType[] resolve(UnresolvedType[] types) {
  137. if (types == null) return new ResolvedType[0];
  138. ResolvedType[] ret = new ResolvedType[types.length];
  139. for (int i=0; i<types.length; i++) {
  140. ret[i] = resolve(types[i]);
  141. }
  142. return ret;
  143. }
  144. /**
  145. * Resolve a type. This the hub of type resolution. The resolved type is added
  146. * to the type map by signature.
  147. */
  148. public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) {
  149. // special resolution processing for already resolved types.
  150. if (ty instanceof ResolvedType) {
  151. ResolvedType rty = (ResolvedType) ty;
  152. rty = resolve(rty);
  153. return rty;
  154. }
  155. // dispatch back to the type variable reference to resolve its constituent parts
  156. // don't do this for other unresolved types otherwise you'll end up in a loop
  157. if (ty.isTypeVariableReference()) {
  158. return ty.resolve(this);
  159. }
  160. // if we've already got a resolved type for the signature, just return it
  161. // after updating the world
  162. String signature = ty.getSignature();
  163. ResolvedType ret = typeMap.get(signature);
  164. if (ret != null) {
  165. ret.world = this; // Set the world for the RTX
  166. return ret;
  167. } else if ( signature.equals("?") || signature.equals("*")) {
  168. // might be a problem here, not sure '?' should make it to here as a signature, the
  169. // proper signature for wildcard '?' is '*'
  170. // fault in generic wildcard, can't be done earlier because of init issues
  171. ResolvedType something = new BoundedReferenceType("?",this);
  172. typeMap.put("?",something);
  173. return something;
  174. }
  175. // no existing resolved type, create one
  176. if (ty.isArray()) {
  177. ret = new ResolvedType.Array(signature,
  178. this,
  179. resolve(ty.getComponentType(),
  180. allowMissing));
  181. } else {
  182. ret = resolveToReferenceType(ty);
  183. if (!allowMissing && ret == ResolvedType.MISSING) {
  184. ret = handleRequiredMissingTypeDuringResolution(ty);
  185. }
  186. }
  187. // Pulling in the type may have already put the right entry in the map
  188. if (typeMap.get(signature)==null && ret != ResolvedType.MISSING) {
  189. typeMap.put(signature, ret);
  190. }
  191. return ret;
  192. }
  193. /**
  194. * We tried to resolve a type and couldn't find it...
  195. */
  196. private ResolvedType handleRequiredMissingTypeDuringResolution(UnresolvedType ty) {
  197. // defer the message until someone asks a question of the type that we can't answer
  198. // just from the signature.
  199. // MessageUtil.error(messageHandler,
  200. // WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()));
  201. if (dumpState_cantFindTypeExceptions==null) {
  202. dumpState_cantFindTypeExceptions = new ArrayList();
  203. }
  204. dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName()));
  205. return new MissingResolvedTypeWithKnownSignature(ty.getSignature(),this);
  206. }
  207. /**
  208. * Some TypeFactory operations create resolved types directly, but these won't be
  209. * in the typeMap - this resolution process puts them there. Resolved types are
  210. * also told their world which is needed for the special autoboxing resolved types.
  211. */
  212. public ResolvedType resolve(ResolvedType ty) {
  213. if (ty.isTypeVariableReference()) return ty; // until type variables have proper sigs...
  214. ResolvedType resolved = typeMap.get(ty.getSignature());
  215. if (resolved == null) {
  216. typeMap.put(ty.getSignature(), ty);
  217. resolved = ty;
  218. }
  219. resolved.world = this;
  220. return resolved;
  221. }
  222. /**
  223. * Convenience method for finding a type by name and resolving it in one step.
  224. */
  225. public ResolvedType resolve(String name) {
  226. return resolve(UnresolvedType.forName(name));
  227. }
  228. public ResolvedType resolve(String name,boolean allowMissing) {
  229. return resolve(UnresolvedType.forName(name),allowMissing);
  230. }
  231. /**
  232. * Resolve to a ReferenceType - simple, raw, parameterized, or generic.
  233. * Raw, parameterized, and generic versions of a type share a delegate.
  234. */
  235. private final ResolvedType resolveToReferenceType(UnresolvedType ty) {
  236. if (ty.isParameterizedType()) {
  237. // ======= parameterized types ================
  238. ReferenceType genericType = (ReferenceType)resolveGenericTypeFor(ty,false);
  239. ReferenceType parameterizedType =
  240. TypeFactory.createParameterizedType(genericType, ty.typeParameters, this);
  241. return parameterizedType;
  242. } else if (ty.isGenericType()) {
  243. // ======= generic types ======================
  244. ReferenceType genericType = (ReferenceType)resolveGenericTypeFor(ty,false);
  245. return genericType;
  246. } else if (ty.isGenericWildcard()) {
  247. // ======= generic wildcard types =============
  248. return resolveGenericWildcardFor(ty);
  249. } else {
  250. // ======= simple and raw types ===============
  251. String erasedSignature = ty.getErasureSignature();
  252. ReferenceType simpleOrRawType = new ReferenceType(erasedSignature, this);
  253. ReferenceTypeDelegate delegate = resolveDelegate(simpleOrRawType);
  254. if (delegate == null) return ResolvedType.MISSING;
  255. if (delegate.isGeneric() && behaveInJava5Way) {
  256. // ======== raw type ===========
  257. simpleOrRawType.typeKind = TypeKind.RAW;
  258. ReferenceType genericType = makeGenericTypeFrom(delegate,simpleOrRawType);
  259. // name = ReferenceType.fromTypeX(UnresolvedType.forRawTypeNames(ty.getName()),this);
  260. simpleOrRawType.setDelegate(delegate);
  261. genericType.setDelegate(delegate);
  262. simpleOrRawType.setGenericType(genericType);
  263. return simpleOrRawType;
  264. } else {
  265. // ======== simple type =========
  266. simpleOrRawType.setDelegate(delegate);
  267. return simpleOrRawType;
  268. }
  269. }
  270. }
  271. /**
  272. * Attempt to resolve a type that should be a generic type.
  273. */
  274. public ResolvedType resolveGenericTypeFor(UnresolvedType anUnresolvedType, boolean allowMissing) {
  275. // Look up the raw type by signature
  276. String rawSignature = anUnresolvedType.getRawType().getSignature();
  277. ResolvedType rawType = (ResolvedType) typeMap.get(rawSignature);
  278. if (rawType==null) {
  279. rawType = resolve(UnresolvedType.forSignature(rawSignature),false);
  280. typeMap.put(rawSignature,rawType);
  281. }
  282. // Does the raw type know its generic form? (It will if we created the
  283. // raw type from a source type, it won't if its been created just through
  284. // being referenced, e.g. java.util.List
  285. ResolvedType genericType = rawType.getGenericType();
  286. // There is a special case to consider here (testGenericsBang_pr95993 highlights it)
  287. // You may have an unresolvedType for a parameterized type but it
  288. // is backed by a simple type rather than a generic type. This occurs for
  289. // inner types of generic types that inherit their enclosing types
  290. // type variables.
  291. if (rawType.isSimpleType() && (anUnresolvedType.typeParameters==null || anUnresolvedType.typeParameters.length==0)) {
  292. rawType.world = this;
  293. return rawType;
  294. }
  295. if (genericType != null) {
  296. genericType.world = this;
  297. return genericType;
  298. } else {
  299. // Fault in the generic that underpins the raw type ;)
  300. ReferenceTypeDelegate delegate = resolveDelegate((ReferenceType)rawType);
  301. ReferenceType genericRefType = makeGenericTypeFrom(delegate,((ReferenceType)rawType));
  302. ((ReferenceType)rawType).setGenericType(genericRefType);
  303. genericRefType.setDelegate(delegate);
  304. ((ReferenceType)rawType).setDelegate(delegate);
  305. return genericRefType;
  306. }
  307. }
  308. private ReferenceType makeGenericTypeFrom(ReferenceTypeDelegate delegate, ReferenceType rawType) {
  309. String genericSig = delegate.getDeclaredGenericSignature();
  310. if (genericSig != null) {
  311. return new ReferenceType(
  312. UnresolvedType.forGenericTypeSignature(rawType.getSignature(),delegate.getDeclaredGenericSignature()),this);
  313. } else {
  314. return new ReferenceType(
  315. UnresolvedType.forGenericTypeVariables(rawType.getSignature(), delegate.getTypeVariables()),this);
  316. }
  317. }
  318. /**
  319. * Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType).
  320. */
  321. private ReferenceType resolveGenericWildcardFor(UnresolvedType aType) {
  322. BoundedReferenceType ret = null;
  323. // FIXME asc doesnt take account of additional interface bounds (e.g. ? super R & Serializable - can you do that?)
  324. if (aType.isExtends()) {
  325. ReferenceType upperBound = (ReferenceType)resolve(aType.getUpperBound());
  326. ret = new BoundedReferenceType(upperBound,true,this);
  327. } else if (aType.isSuper()) {
  328. ReferenceType lowerBound = (ReferenceType) resolve(aType.getLowerBound());
  329. ret = new BoundedReferenceType(lowerBound,false,this);
  330. } else {
  331. // must be ? on its own!
  332. }
  333. return ret;
  334. }
  335. /**
  336. * Find the ReferenceTypeDelegate behind this reference type so that it can
  337. * fulfill its contract.
  338. */
  339. protected abstract ReferenceTypeDelegate resolveDelegate(ReferenceType ty);
  340. /**
  341. * Special resolution for "core" types like OBJECT. These are resolved just like
  342. * any other type, but if they are not found it is more serious and we issue an
  343. * error message immediately.
  344. */
  345. public ResolvedType getCoreType(UnresolvedType tx) {
  346. ResolvedType coreTy = resolve(tx,true);
  347. if (coreTy == ResolvedType.MISSING) {
  348. MessageUtil.error(messageHandler,
  349. WeaverMessages.format(WeaverMessages.CANT_FIND_CORE_TYPE,tx.getName()));
  350. }
  351. return coreTy;
  352. }
  353. /**
  354. * Lookup a type by signature, if not found then build one and put it in the
  355. * map.
  356. */
  357. public ReferenceType lookupOrCreateName(UnresolvedType ty) {
  358. String signature = ty.getSignature();
  359. ReferenceType ret = lookupBySignature(signature);
  360. if (ret == null) {
  361. ret = ReferenceType.fromTypeX(ty, this);
  362. typeMap.put(signature, ret);
  363. }
  364. return ret;
  365. }
  366. /**
  367. * Lookup a reference type in the world by its signature. Returns
  368. * null if not found.
  369. */
  370. public ReferenceType lookupBySignature(String signature) {
  371. return (ReferenceType) typeMap.get(signature);
  372. }
  373. // =============================================================================
  374. // T Y P E R E S O L U T I O N -- E N D
  375. // =============================================================================
  376. /**
  377. * Member resolution is achieved by resolving the declaring type and then
  378. * looking up the member in the resolved declaring type.
  379. */
  380. public ResolvedMember resolve(Member member) {
  381. ResolvedType declaring = member.getDeclaringType().resolve(this);
  382. if (declaring.isRawType()) declaring = declaring.getGenericType();
  383. ResolvedMember ret;
  384. if (member.getKind() == Member.FIELD) {
  385. ret = declaring.lookupField(member);
  386. } else {
  387. ret = declaring.lookupMethod(member);
  388. }
  389. if (ret != null) return ret;
  390. return declaring.lookupSyntheticMember(member);
  391. }
  392. // Methods for creating various cross-cutting members...
  393. // ===========================================================
  394. /**
  395. * Create an advice shadow munger from the given advice attribute
  396. */
  397. public abstract Advice createAdviceMunger(
  398. AjAttribute.AdviceAttribute attribute,
  399. Pointcut pointcut,
  400. Member signature);
  401. /**
  402. * Create an advice shadow munger for the given advice kind
  403. */
  404. public final Advice createAdviceMunger(
  405. AdviceKind kind,
  406. Pointcut p,
  407. Member signature,
  408. int extraParameterFlags,
  409. IHasSourceLocation loc)
  410. {
  411. AjAttribute.AdviceAttribute attribute =
  412. new AjAttribute.AdviceAttribute(kind, p, extraParameterFlags, loc.getStart(), loc.getEnd(), loc.getSourceContext());
  413. return createAdviceMunger(attribute, p, signature);
  414. }
  415. public abstract ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField);
  416. public abstract ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField);
  417. /**
  418. * Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed
  419. * @see org.aspectj.weaver.bcel.BcelWorld#makePerClauseAspect(ResolvedType, org.aspectj.weaver.patterns.PerClause.Kind)
  420. */
  421. public abstract ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind);
  422. public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType);
  423. /**
  424. * Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo
  425. */
  426. public int compareByPrecedence(ResolvedType aspect1, ResolvedType aspect2) {
  427. return precedenceCalculator.compareByPrecedence(aspect1, aspect2);
  428. }
  429. /**
  430. * compares by precedence with the additional rule that a super-aspect is
  431. * sorted before its sub-aspects
  432. */
  433. public int compareByPrecedenceAndHierarchy(ResolvedType aspect1, ResolvedType aspect2) {
  434. return precedenceCalculator.compareByPrecedenceAndHierarchy(aspect1, aspect2);
  435. }
  436. // simple property getter and setters
  437. // ===========================================================
  438. /**
  439. * Nobody should hold onto a copy of this message handler, or setMessageHandler won't
  440. * work right.
  441. */
  442. public IMessageHandler getMessageHandler() {
  443. return messageHandler;
  444. }
  445. public void setMessageHandler(IMessageHandler messageHandler) {
  446. if (this.isInPinpointMode()) {
  447. this.messageHandler = new PinpointingMessageHandler(messageHandler);
  448. } else {
  449. this.messageHandler = messageHandler;
  450. }
  451. }
  452. /**
  453. * convenenience method for creating and issuing messages via the message handler -
  454. * if you supply two locations you will get two messages.
  455. */
  456. public void showMessage(
  457. Kind kind,
  458. String message,
  459. ISourceLocation loc1,
  460. ISourceLocation loc2)
  461. {
  462. if (loc1 != null) {
  463. messageHandler.handleMessage(new Message(message, kind, null, loc1));
  464. if (loc2 != null) {
  465. messageHandler.handleMessage(new Message(message, kind, null, loc2));
  466. }
  467. } else {
  468. messageHandler.handleMessage(new Message(message, kind, null, loc2));
  469. }
  470. }
  471. public void setCrossReferenceHandler(ICrossReferenceHandler xrefHandler) {
  472. this.xrefHandler = xrefHandler;
  473. }
  474. /**
  475. * Get the cross-reference handler for the world, may be null.
  476. */
  477. public ICrossReferenceHandler getCrossReferenceHandler() {
  478. return this.xrefHandler;
  479. }
  480. public void setTypeVariableLookupScope(TypeVariableDeclaringElement scope) {
  481. this.typeVariableLookupScope = scope;
  482. }
  483. public TypeVariableDeclaringElement getTypeVariableLookupScope() {
  484. return typeVariableLookupScope;
  485. }
  486. public List getDeclareParents() {
  487. return crosscuttingMembersSet.getDeclareParents();
  488. }
  489. public List getDeclareAnnotationOnTypes() {
  490. return crosscuttingMembersSet.getDeclareAnnotationOnTypes();
  491. }
  492. public List getDeclareAnnotationOnFields() {
  493. return crosscuttingMembersSet.getDeclareAnnotationOnFields();
  494. }
  495. public List getDeclareAnnotationOnMethods() {
  496. return crosscuttingMembersSet.getDeclareAnnotationOnMethods();
  497. }
  498. public List getDeclareSoft() {
  499. return crosscuttingMembersSet.getDeclareSofts();
  500. }
  501. public CrosscuttingMembersSet getCrosscuttingMembersSet() {
  502. return crosscuttingMembersSet;
  503. }
  504. public IHierarchy getModel() {
  505. return model;
  506. }
  507. public void setModel(IHierarchy model) {
  508. this.model = model;
  509. }
  510. public Lint getLint() {
  511. return lint;
  512. }
  513. public void setLint(Lint lint) {
  514. this.lint = lint;
  515. }
  516. public boolean isXnoInline() {
  517. return XnoInline;
  518. }
  519. public void setXnoInline(boolean xnoInline) {
  520. XnoInline = xnoInline;
  521. }
  522. public boolean isXlazyTjp() {
  523. return XlazyTjp;
  524. }
  525. public void setXlazyTjp(boolean b) {
  526. XlazyTjp = b;
  527. }
  528. public boolean isHasMemberSupportEnabled() {
  529. return XhasMember;
  530. }
  531. public void setXHasMemberSupportEnabled(boolean b) {
  532. XhasMember = b;
  533. }
  534. public boolean isInPinpointMode() {
  535. return Xpinpoint;
  536. }
  537. public void setPinpointMode(boolean b) {
  538. this.Xpinpoint = b;
  539. }
  540. public void setBehaveInJava5Way(boolean b) {
  541. behaveInJava5Way = b;
  542. }
  543. public boolean isInJava5Mode() {
  544. return behaveInJava5Way;
  545. }
  546. /*
  547. * Map of types in the world, with soft links to expendable ones.
  548. * An expendable type is a reference type that is not exposed to the weaver (ie
  549. * just pulled in for type resolution purposes).
  550. */
  551. protected static class TypeMap {
  552. /** Map of types that never get thrown away */
  553. private Map tMap = new HashMap();
  554. /** Map of types that may be ejected from the cache if we need space */
  555. private Map expendableMap = new WeakHashMap();
  556. private static final boolean debug = false;
  557. /**
  558. * Add a new type into the map, the key is the type signature.
  559. * Some types do *not* go in the map, these are ones involving
  560. * *member* type variables. The reason is that when all you have is the
  561. * signature which gives you a type variable name, you cannot
  562. * guarantee you are using the type variable in the same way
  563. * as someone previously working with a similarly
  564. * named type variable. So, these do not go into the map:
  565. * - TypeVariableReferenceType.
  566. * - ParameterizedType where a member type variable is involved.
  567. * - BoundedReferenceType when one of the bounds is a type variable.
  568. *
  569. * definition: "member type variables" - a tvar declared on a generic
  570. * method/ctor as opposed to those you see declared on a generic type.
  571. */
  572. public ResolvedType put(String key, ResolvedType type) {
  573. if (type.isParameterizedType() && type.isParameterizedWithAMemberTypeVariable()) {
  574. if (debug)
  575. System.err.println("Not putting a parameterized type that utilises member declared type variables into the typemap: key="+key+" type="+type);
  576. return type;
  577. }
  578. if (type.isTypeVariableReference()) {
  579. if (debug)
  580. System.err.println("Not putting a type variable reference type into the typemap: key="+key+" type="+type);
  581. return type;
  582. }
  583. // this test should be improved - only avoid putting them in if one of the
  584. // bounds is a member type variable
  585. if (type instanceof BoundedReferenceType) {
  586. if (debug)
  587. System.err.println("Not putting a bounded reference type into the typemap: key="+key+" type="+type);
  588. return type;
  589. }
  590. if (isExpendable(type)) {
  591. return (ResolvedType) expendableMap.put(key,type);
  592. } else {
  593. return (ResolvedType) tMap.put(key,type);
  594. }
  595. }
  596. /** Lookup a type by its signature */
  597. public ResolvedType get(String key) {
  598. ResolvedType ret = (ResolvedType) tMap.get(key);
  599. if (ret == null) ret = (ResolvedType) expendableMap.get(key);
  600. return ret;
  601. }
  602. /** Remove a type from the map */
  603. public ResolvedType remove(String key) {
  604. ResolvedType ret = (ResolvedType) tMap.remove(key);
  605. if (ret == null) ret = (ResolvedType) expendableMap.remove(key);
  606. return ret;
  607. }
  608. /** Reference types we don't intend to weave may be ejected from
  609. * the cache if we need the space.
  610. */
  611. private boolean isExpendable(ResolvedType type) {
  612. return (
  613. (type != null) &&
  614. (!type.isExposedToWeaver()) &&
  615. (!type.isPrimitiveType())
  616. );
  617. }
  618. public String toString() {
  619. StringBuffer sb = new StringBuffer();
  620. sb.append("types:\n");
  621. sb.append(dumpthem(tMap));
  622. sb.append("expendables:\n");
  623. sb.append(dumpthem(expendableMap));
  624. return sb.toString();
  625. }
  626. private String dumpthem(Map m) {
  627. StringBuffer sb = new StringBuffer();
  628. Set keys = m.keySet();
  629. for (Iterator iter = keys.iterator(); iter.hasNext();) {
  630. String k = (String) iter.next();
  631. sb.append(k+"="+m.get(k)).append("\n");
  632. }
  633. return sb.toString();
  634. }
  635. }
  636. /**
  637. * This class is used to compute and store precedence relationships between
  638. * aspects.
  639. */
  640. private static class AspectPrecedenceCalculator {
  641. private World world;
  642. private Map cachedResults;
  643. public AspectPrecedenceCalculator(World forSomeWorld) {
  644. this.world = forSomeWorld;
  645. this.cachedResults = new HashMap();
  646. }
  647. /**
  648. * Ask every declare precedence in the world to order the two aspects.
  649. * If more than one declare precedence gives an ordering, and the orderings
  650. * conflict, then that's an error.
  651. */
  652. public int compareByPrecedence(ResolvedType firstAspect, ResolvedType secondAspect) {
  653. PrecedenceCacheKey key = new PrecedenceCacheKey(firstAspect,secondAspect);
  654. if (cachedResults.containsKey(key)) {
  655. return ((Integer) cachedResults.get(key)).intValue();
  656. } else {
  657. int order = 0;
  658. DeclarePrecedence orderer = null; // Records the declare precedence statement that gives the first ordering
  659. for (Iterator i = world.getCrosscuttingMembersSet().getDeclareDominates().iterator(); i.hasNext(); ) {
  660. DeclarePrecedence d = (DeclarePrecedence)i.next();
  661. int thisOrder = d.compare(firstAspect, secondAspect);
  662. if (thisOrder != 0) {
  663. if (orderer==null) orderer = d;
  664. if (order != 0 && order != thisOrder) {
  665. ISourceLocation[] isls = new ISourceLocation[2];
  666. isls[0]=orderer.getSourceLocation();
  667. isls[1]=d.getSourceLocation();
  668. Message m =
  669. new Message("conflicting declare precedence orderings for aspects: "+
  670. firstAspect.getName()+" and "+secondAspect.getName(),null,true,isls);
  671. world.getMessageHandler().handleMessage(m);
  672. } else {
  673. order = thisOrder;
  674. }
  675. }
  676. }
  677. cachedResults.put(key, new Integer(order));
  678. return order;
  679. }
  680. }
  681. public int compareByPrecedenceAndHierarchy(ResolvedType firstAspect, ResolvedType secondAspect) {
  682. if (firstAspect.equals(secondAspect)) return 0;
  683. int ret = compareByPrecedence(firstAspect, secondAspect);
  684. if (ret != 0) return ret;
  685. if (firstAspect.isAssignableFrom(secondAspect)) return -1;
  686. else if (secondAspect.isAssignableFrom(firstAspect)) return +1;
  687. return 0;
  688. }
  689. private static class PrecedenceCacheKey {
  690. public ResolvedType aspect1;
  691. public ResolvedType aspect2;
  692. public PrecedenceCacheKey(ResolvedType a1, ResolvedType a2) {
  693. this.aspect1 = a1;
  694. this.aspect2 = a2;
  695. }
  696. public boolean equals(Object obj) {
  697. if (!(obj instanceof PrecedenceCacheKey)) return false;
  698. PrecedenceCacheKey other = (PrecedenceCacheKey) obj;
  699. return (aspect1 == other.aspect1 && aspect2 == other.aspect2);
  700. }
  701. public int hashCode() {
  702. return aspect1.hashCode() + aspect2.hashCode();
  703. }
  704. }
  705. }
  706. public void validateType(UnresolvedType type) { }
  707. }