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.

BcelAdvice.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  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. * Alexandre Vasseur support for @AJ aspects
  12. * ******************************************************************/
  13. package org.aspectj.weaver.bcel;
  14. import java.lang.reflect.Modifier;
  15. import java.util.ArrayList;
  16. import java.util.Collection;
  17. import java.util.Collections;
  18. import java.util.Map;
  19. import org.aspectj.apache.bcel.generic.InstructionConstants;
  20. import org.aspectj.apache.bcel.generic.InstructionFactory;
  21. import org.aspectj.apache.bcel.generic.InstructionHandle;
  22. import org.aspectj.apache.bcel.generic.InstructionList;
  23. import org.aspectj.apache.bcel.generic.LineNumberTag;
  24. import org.aspectj.bridge.ISourceLocation;
  25. import org.aspectj.bridge.Message;
  26. import org.aspectj.weaver.Advice;
  27. import org.aspectj.weaver.AdviceKind;
  28. import org.aspectj.weaver.AjAttribute;
  29. import org.aspectj.weaver.BCException;
  30. import org.aspectj.weaver.IEclipseSourceContext;
  31. import org.aspectj.weaver.ISourceContext;
  32. import org.aspectj.weaver.Member;
  33. import org.aspectj.weaver.ResolvedMember;
  34. import org.aspectj.weaver.ResolvedMemberImpl;
  35. import org.aspectj.weaver.ResolvedType;
  36. import org.aspectj.weaver.Shadow;
  37. import org.aspectj.weaver.ShadowMunger;
  38. import org.aspectj.weaver.UnresolvedType;
  39. import org.aspectj.weaver.WeaverMessages;
  40. import org.aspectj.weaver.World;
  41. import org.aspectj.weaver.ast.Literal;
  42. import org.aspectj.weaver.ast.Test;
  43. import org.aspectj.weaver.patterns.ExactTypePattern;
  44. import org.aspectj.weaver.patterns.ExposedState;
  45. import org.aspectj.weaver.patterns.PerClause;
  46. import org.aspectj.weaver.patterns.Pointcut;
  47. /**
  48. * Advice implemented for bcel.
  49. *
  50. * @author Erik Hilsdale
  51. * @author Jim Hugunin
  52. */
  53. public class BcelAdvice extends Advice {
  54. private Test pointcutTest;
  55. private ExposedState exposedState;
  56. private boolean hasMatchedAtLeastOnce = false;
  57. public BcelAdvice(
  58. AjAttribute.AdviceAttribute attribute,
  59. Pointcut pointcut,
  60. Member signature,
  61. ResolvedType concreteAspect)
  62. {
  63. super(attribute, pointcut,shrink(attribute.getKind(),concreteAspect,signature));// (signature==null?null:signature.slimline()));
  64. this.concreteAspect = concreteAspect;
  65. }
  66. /**
  67. * We don't always need to represent the signature with a heavyweight BcelMethod object - only if its around advice
  68. * and inlining is active
  69. * @param concreteAspect
  70. * @param attribute
  71. */
  72. private static Member shrink(AdviceKind kind, ResolvedType concreteAspect, Member m) {
  73. if (m==null) return null;
  74. UnresolvedType dType = m.getDeclaringType();
  75. // if it isnt around advice or it is but inlining is turned off then shrink it to a ResolvedMemberImpl
  76. if (kind!=AdviceKind.Around ||
  77. ((dType instanceof ResolvedType) && ((ResolvedType)dType).getWorld().isXnoInline())) {
  78. if (m instanceof BcelMethod) {
  79. BcelMethod bm = (BcelMethod)m;
  80. if (bm.getMethod()!=null && bm.getMethod().getAnnotations()!=null) return m;
  81. ResolvedMemberImpl simplermember = new ResolvedMemberImpl(bm.getKind(),bm.getDeclaringType(),
  82. bm.getModifiers(),bm.getReturnType(),bm.getName(),
  83. bm.getParameterTypes());//,bm.getExceptions(),bm.getBackingGenericMember());
  84. simplermember.setParameterNames(bm.getParameterNames());
  85. return simplermember;
  86. }
  87. }
  88. return m;
  89. }
  90. // !!! must only be used for testing
  91. public BcelAdvice(AdviceKind kind, Pointcut pointcut, Member signature,
  92. int extraArgumentFlags,
  93. int start, int end, ISourceContext sourceContext, ResolvedType concreteAspect)
  94. {
  95. this(new AjAttribute.AdviceAttribute(kind, pointcut, extraArgumentFlags, start, end, sourceContext),
  96. pointcut, signature, concreteAspect);
  97. thrownExceptions = Collections.EMPTY_LIST; //!!! interaction with unit tests
  98. }
  99. // ---- implementations of ShadowMunger's methods
  100. public ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause) {
  101. suppressLintWarnings(world);
  102. ShadowMunger ret = super.concretize(fromType, world, clause);
  103. clearLintSuppressions(world,this.suppressedLintKinds);
  104. IfFinder ifinder = new IfFinder();
  105. ret.getPointcut().accept(ifinder,null);
  106. boolean hasGuardTest = ifinder.hasIf && getKind() != AdviceKind.Around;
  107. boolean isAround = getKind() == AdviceKind.Around;
  108. if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
  109. if (!isAround && !hasGuardTest && world.getLint().noGuardForLazyTjp.isEnabled()) {
  110. // can't build tjp lazily, no suitable test...
  111. // ... only want to record it once against the advice(bug 133117)
  112. world.getLint().noGuardForLazyTjp.signal("",getSourceLocation());
  113. }
  114. }
  115. return ret;
  116. }
  117. public ShadowMunger parameterizeWith(ResolvedType declaringType,Map typeVariableMap) {
  118. Pointcut pc = getPointcut().parameterizeWith(typeVariableMap,declaringType.getWorld());
  119. BcelAdvice ret = null;
  120. Member adviceSignature = signature;
  121. // allows for around advice where the return value is a type variable (see pr115250)
  122. if (signature instanceof ResolvedMember && signature.getDeclaringType().isGenericType()) {
  123. adviceSignature = ((ResolvedMember)signature).parameterizedWith(declaringType.getTypeParameters(),declaringType,declaringType.isParameterizedType());
  124. }
  125. ret = new BcelAdvice(this.attribute,pc,adviceSignature,this.concreteAspect);
  126. return ret;
  127. }
  128. public boolean match(Shadow shadow, World world) {
  129. suppressLintWarnings(world);
  130. boolean ret = super.match(shadow, world);
  131. clearLintSuppressions(world,this.suppressedLintKinds);
  132. return ret;
  133. }
  134. public void specializeOn(Shadow shadow) {
  135. if (getKind() == AdviceKind.Around) {
  136. ((BcelShadow)shadow).initializeForAroundClosure();
  137. }
  138. //XXX this case is just here for supporting lazy test code
  139. if (getKind() == null) {
  140. exposedState = new ExposedState(0);
  141. return;
  142. }
  143. if (getKind().isPerEntry()) {
  144. exposedState = new ExposedState(0);
  145. } else if (getKind().isCflow()) {
  146. exposedState = new ExposedState(nFreeVars);
  147. } else if (getSignature() != null) {
  148. exposedState = new ExposedState(getSignature());
  149. } else {
  150. exposedState = new ExposedState(0);
  151. return; //XXX this case is just here for supporting lazy test code
  152. }
  153. World world = shadow.getIWorld();
  154. suppressLintWarnings(world);
  155. pointcutTest = getPointcut().findResidue(shadow, exposedState);
  156. clearLintSuppressions(world,this.suppressedLintKinds);
  157. // these initializations won't be performed by findResidue, but need to be
  158. // so that the joinpoint is primed for weaving
  159. if (getKind() == AdviceKind.PerThisEntry) {
  160. shadow.getThisVar();
  161. } else if (getKind() == AdviceKind.PerTargetEntry) {
  162. shadow.getTargetVar();
  163. }
  164. // make sure thisJoinPoint parameters are initialized
  165. if ((getExtraParameterFlags() & ThisJoinPointStaticPart) != 0) {
  166. ((BcelShadow)shadow).getThisJoinPointStaticPartVar();
  167. ((BcelShadow)shadow).getEnclosingClass().warnOnAddedStaticInitializer(shadow,getSourceLocation());
  168. }
  169. if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
  170. boolean hasGuardTest = pointcutTest != Literal.TRUE && getKind() != AdviceKind.Around;
  171. boolean isAround = getKind() == AdviceKind.Around;
  172. ((BcelShadow)shadow).requireThisJoinPoint(hasGuardTest,isAround);
  173. ((BcelShadow)shadow).getEnclosingClass().warnOnAddedStaticInitializer(shadow,getSourceLocation());
  174. if (!hasGuardTest && world.getLint().multipleAdviceStoppingLazyTjp.isEnabled()) {
  175. // collect up the problematic advice
  176. ((BcelShadow)shadow).addAdvicePreventingLazyTjp(this);
  177. }
  178. }
  179. if ((getExtraParameterFlags() & ThisEnclosingJoinPointStaticPart) != 0) {
  180. ((BcelShadow)shadow).getThisEnclosingJoinPointStaticPartVar();
  181. ((BcelShadow)shadow).getEnclosingClass().warnOnAddedStaticInitializer(shadow,getSourceLocation());
  182. }
  183. }
  184. private boolean canInline(Shadow s) {
  185. if (attribute.isProceedInInners()) return false;
  186. //XXX this guard seems to only be needed for bad test cases
  187. if (concreteAspect == null || concreteAspect.isMissing()) return false;
  188. if (concreteAspect.getWorld().isXnoInline()) return false;
  189. //System.err.println("isWoven? " + ((BcelObjectType)concreteAspect).getLazyClassGen().getWeaverState());
  190. return BcelWorld.getBcelObjectType(concreteAspect).getLazyClassGen().isWoven();
  191. }
  192. public void implementOn(Shadow s) {
  193. hasMatchedAtLeastOnce=true;
  194. BcelShadow shadow = (BcelShadow) s;
  195. // remove any unnecessary exceptions if the compiler option is set to
  196. // error or warning and if this piece of advice throws exceptions
  197. // (bug 129282). This may be expanded to include other compiler warnings
  198. // at the moment it only deals with 'declared exception is not thrown'
  199. if (!shadow.getWorld().isIgnoringUnusedDeclaredThrownException()
  200. && !getThrownExceptions().isEmpty()) {
  201. Member member = shadow.getSignature();
  202. if (member instanceof BcelMethod) {
  203. removeUnnecessaryProblems((BcelMethod)member,
  204. ((BcelMethod)member).getDeclarationLineNumber());
  205. } else {
  206. // we're in a call shadow therefore need the line number of the
  207. // declared method (which may be in a different type). However,
  208. // we want to remove the problems from the CompilationResult
  209. // held within the current type's EclipseSourceContext so need
  210. // the enclosing shadow too
  211. ResolvedMember resolvedMember = shadow.getSignature().resolve(shadow.getWorld());
  212. if (resolvedMember instanceof BcelMethod
  213. && shadow.getEnclosingShadow() instanceof BcelShadow) {
  214. Member enclosingMember = shadow.getEnclosingShadow().getSignature();
  215. if (enclosingMember instanceof BcelMethod) {
  216. removeUnnecessaryProblems((BcelMethod)enclosingMember,
  217. ((BcelMethod)resolvedMember).getDeclarationLineNumber());
  218. }
  219. }
  220. }
  221. }
  222. if (shadow.getIWorld().isJoinpointSynchronizationEnabled() &&
  223. shadow.getKind()==Shadow.MethodExecution &&
  224. (s.getSignature().getModifiers() & Modifier.SYNCHRONIZED)!=0) {
  225. shadow.getIWorld().getLint().advisingSynchronizedMethods.signal(new String[]{shadow.toString()},shadow.getSourceLocation(),new ISourceLocation[]{getSourceLocation()});
  226. }
  227. //FIXME AV - see #75442, this logic is not enough so for now comment it out until we fix the bug
  228. // // callback for perObject AJC MightHaveAspect postMunge (#75442)
  229. // if (getConcreteAspect() != null
  230. // && getConcreteAspect().getPerClause() != null
  231. // && PerClause.PEROBJECT.equals(getConcreteAspect().getPerClause().getKind())) {
  232. // final PerObject clause;
  233. // if (getConcreteAspect().getPerClause() instanceof PerFromSuper) {
  234. // clause = (PerObject)((PerFromSuper) getConcreteAspect().getPerClause()).lookupConcretePerClause(getConcreteAspect());
  235. // } else {
  236. // clause = (PerObject) getConcreteAspect().getPerClause();
  237. // }
  238. // if (clause.isThis()) {
  239. // PerObjectInterfaceTypeMunger.registerAsAdvisedBy(s.getThisVar().getType(), getConcreteAspect());
  240. // } else {
  241. // PerObjectInterfaceTypeMunger.registerAsAdvisedBy(s.getTargetVar().getType(), getConcreteAspect());
  242. // }
  243. // }
  244. if (getKind() == AdviceKind.Before) {
  245. shadow.weaveBefore(this);
  246. } else if (getKind() == AdviceKind.AfterReturning) {
  247. shadow.weaveAfterReturning(this);
  248. } else if (getKind() == AdviceKind.AfterThrowing) {
  249. UnresolvedType catchType =
  250. hasExtraParameter()
  251. ? getExtraParameterType()
  252. : UnresolvedType.THROWABLE;
  253. shadow.weaveAfterThrowing(this, catchType);
  254. } else if (getKind() == AdviceKind.After) {
  255. shadow.weaveAfter(this);
  256. } else if (getKind() == AdviceKind.Around) {
  257. // Note: under regular LTW the aspect is usually loaded after the first use of any class affecteted by it
  258. // This means that as long as the aspect has not been thru the LTW, it's woven state is unknown
  259. // and thus canInline(s) will return false.
  260. // To force inlining (test), ones can do Class aspect = FQNAspect.class in the clinit of the target class
  261. // FIXME AV : for AJC compiled @AJ aspect (or any code style aspect), the woven state can never be known
  262. // if the aspect belongs to a parent classloader. In that case the aspect will never be inlined.
  263. // It might be dangerous to change that especially for @AJ aspect non compiled with AJC since if those
  264. // are not weaved (f.e. use of some limiteed LTW etc) then they cannot be prepared for inlining.
  265. // One solution would be to flag @AJ aspect with an annotation as "prepared" and query that one.
  266. if (!canInline(s)) {
  267. shadow.weaveAroundClosure(this, hasDynamicTests());
  268. } else {
  269. shadow.weaveAroundInline(this, hasDynamicTests());
  270. }
  271. } else if (getKind() == AdviceKind.InterInitializer) {
  272. shadow.weaveAfterReturning(this);
  273. } else if (getKind().isCflow()) {
  274. shadow.weaveCflowEntry(this, getSignature());
  275. } else if (getKind() == AdviceKind.PerThisEntry) {
  276. shadow.weavePerObjectEntry(this, (BcelVar)shadow.getThisVar());
  277. } else if (getKind() == AdviceKind.PerTargetEntry) {
  278. shadow.weavePerObjectEntry(this, (BcelVar)shadow.getTargetVar());
  279. } else if (getKind() == AdviceKind.Softener) {
  280. shadow.weaveSoftener(this, ((ExactTypePattern)exceptionType).getType());
  281. } else if (getKind() == AdviceKind.PerTypeWithinEntry) {
  282. // PTWIMPL Entry to ptw is the static initialization of a type that matched the ptw type pattern
  283. shadow.weavePerTypeWithinAspectInitialization(this,shadow.getEnclosingType());
  284. } else {
  285. throw new BCException("unimplemented kind: " + getKind());
  286. }
  287. }
  288. private void removeUnnecessaryProblems(BcelMethod method, int problemLineNumber) {
  289. ISourceContext sourceContext = method.getSourceContext();
  290. if (sourceContext instanceof IEclipseSourceContext) {
  291. if (sourceContext != null
  292. && sourceContext instanceof IEclipseSourceContext) {
  293. ((IEclipseSourceContext)sourceContext).removeUnnecessaryProblems(method, problemLineNumber);
  294. }
  295. }
  296. }
  297. // ---- implementations
  298. private Collection collectCheckedExceptions(UnresolvedType[] excs) {
  299. if (excs == null || excs.length == 0) return Collections.EMPTY_LIST;
  300. Collection ret = new ArrayList();
  301. World world = concreteAspect.getWorld();
  302. ResolvedType runtimeException = world.getCoreType(UnresolvedType.RUNTIME_EXCEPTION);
  303. ResolvedType error = world.getCoreType(UnresolvedType.ERROR);
  304. for (int i=0, len=excs.length; i < len; i++) {
  305. ResolvedType t = world.resolve(excs[i],true);
  306. if (t.isMissing()) {
  307. world.getLint().cantFindType.signal(
  308. WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_EXCEPTION_TYPE,excs[i].getName()),
  309. getSourceLocation()
  310. );
  311. // IMessage msg = new Message(
  312. // WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_EXCEPTION_TYPE,excs[i].getName()),
  313. // "",IMessage.ERROR,getSourceLocation(),null,null);
  314. // world.getMessageHandler().handleMessage(msg);
  315. }
  316. if (!(runtimeException.isAssignableFrom(t) || error.isAssignableFrom(t))) {
  317. ret.add(t);
  318. }
  319. }
  320. return ret;
  321. }
  322. private Collection thrownExceptions = null;
  323. public Collection getThrownExceptions() {
  324. if (thrownExceptions == null) {
  325. //??? can we really lump in Around here, how does this interact with Throwable
  326. if (concreteAspect != null && concreteAspect.getWorld() != null && // null tests for test harness
  327. (getKind().isAfter() || getKind() == AdviceKind.Before || getKind() == AdviceKind.Around))
  328. {
  329. World world = concreteAspect.getWorld();
  330. ResolvedMember m = world.resolve(signature);
  331. if (m == null) {
  332. thrownExceptions = Collections.EMPTY_LIST;
  333. } else {
  334. thrownExceptions = collectCheckedExceptions(m.getExceptions());
  335. }
  336. } else {
  337. thrownExceptions = Collections.EMPTY_LIST;
  338. }
  339. }
  340. return thrownExceptions;
  341. }
  342. /**
  343. * The munger must not check for the advice exceptions to be declared by the shadow in the case
  344. * of @AJ aspects so that around can throws Throwable
  345. *
  346. * @return
  347. */
  348. public boolean mustCheckExceptions() {
  349. if (getConcreteAspect() == null) {
  350. return true;
  351. }
  352. return !getConcreteAspect().isAnnotationStyleAspect();
  353. }
  354. // only call me after prepare has been called
  355. public boolean hasDynamicTests() {
  356. // if (hasExtraParameter() && getKind() == AdviceKind.AfterReturning) {
  357. // UnresolvedType extraParameterType = getExtraParameterType();
  358. // if (! extraParameterType.equals(UnresolvedType.OBJECT)
  359. // && ! extraParameterType.isPrimitive())
  360. // return true;
  361. // }
  362. return pointcutTest != null &&
  363. !(pointcutTest == Literal.TRUE);// || pointcutTest == Literal.NO_TEST);
  364. }
  365. /**
  366. * get the instruction list for the really simple version of this advice.
  367. * Is broken apart
  368. * for other advice, but if you want it in one block, this is the method to call.
  369. *
  370. * @param s The shadow around which these instructions will eventually live.
  371. * @param extraArgVar The var that will hold the return value or thrown exception
  372. * for afterX advice
  373. * @param ifNoAdvice The instructionHandle to jump to if the dynamic
  374. * tests for this munger fails.
  375. */
  376. InstructionList getAdviceInstructions(
  377. BcelShadow s,
  378. BcelVar extraArgVar,
  379. InstructionHandle ifNoAdvice)
  380. {
  381. BcelShadow shadow = (BcelShadow) s;
  382. InstructionFactory fact = shadow.getFactory();
  383. BcelWorld world = shadow.getWorld();
  384. InstructionList il = new InstructionList();
  385. // we test to see if we have the right kind of thing...
  386. // after throwing does this just by the exception mechanism.
  387. if (hasExtraParameter() && getKind() == AdviceKind.AfterReturning) {
  388. UnresolvedType extraParameterType = getExtraParameterType();
  389. if (! extraParameterType.equals(UnresolvedType.OBJECT)
  390. && ! extraParameterType.isPrimitiveType()) {
  391. il.append(
  392. BcelRenderer.renderTest(
  393. fact,
  394. world,
  395. Test.makeInstanceof(
  396. extraArgVar, getExtraParameterType().resolve(world)),
  397. null,
  398. ifNoAdvice,
  399. null));
  400. }
  401. }
  402. il.append(getAdviceArgSetup(shadow, extraArgVar, null));
  403. il.append(getNonTestAdviceInstructions(shadow));
  404. InstructionHandle ifYesAdvice = il.getStart();
  405. il.insert(getTestInstructions(shadow, ifYesAdvice, ifNoAdvice, ifYesAdvice));
  406. // If inserting instructions at the start of a method, we need a nice line number for this entry
  407. // in the stack trace
  408. if (shadow.getKind()==Shadow.MethodExecution && getKind()==AdviceKind.Before) {
  409. int lineNumber=0;
  410. // Uncomment this code if you think we should use the method decl line number when it exists...
  411. // // If the advised join point is in a class built by AspectJ, we can use the declaration line number
  412. // boolean b = shadow.getEnclosingMethod().getMemberView().hasDeclarationLineNumberInfo();
  413. // if (b) {
  414. // lineNumber = shadow.getEnclosingMethod().getMemberView().getDeclarationLineNumber();
  415. // } else { // If it wasn't, the best we can do is the line number of the first instruction in the method
  416. lineNumber = shadow.getEnclosingMethod().getMemberView().getLineNumberOfFirstInstruction();
  417. // }
  418. if (lineNumber>0) il.getStart().addTargeter(new LineNumberTag(lineNumber));
  419. }
  420. return il;
  421. }
  422. public InstructionList getAdviceArgSetup(
  423. BcelShadow shadow,
  424. BcelVar extraVar,
  425. InstructionList closureInstantiation)
  426. {
  427. InstructionFactory fact = shadow.getFactory();
  428. BcelWorld world = shadow.getWorld();
  429. InstructionList il = new InstructionList();
  430. // if (targetAspectField != null) {
  431. // il.append(fact.createFieldAccess(
  432. // targetAspectField.getDeclaringType().getName(),
  433. // targetAspectField.getName(),
  434. // BcelWorld.makeBcelType(targetAspectField.getType()),
  435. // Constants.GETSTATIC));
  436. // }
  437. //
  438. //System.err.println("BcelAdvice: " + exposedState);
  439. if (exposedState.getAspectInstance() != null) {
  440. il.append(BcelRenderer.renderExpr(fact, world, exposedState.getAspectInstance()));
  441. }
  442. // pr121385
  443. boolean x = this.getDeclaringAspect().resolve(world).isAnnotationStyleAspect();
  444. final boolean isAnnotationStyleAspect = getConcreteAspect()!=null && getConcreteAspect().isAnnotationStyleAspect() && x;
  445. boolean previousIsClosure = false;
  446. for (int i = 0, len = exposedState.size(); i < len; i++) {
  447. if (exposedState.isErroneousVar(i)) continue; // Erroneous vars have already had error msgs reported!
  448. BcelVar v = (BcelVar) exposedState.get(i);
  449. if (v == null) {
  450. // if not @AJ aspect, go on with the regular binding handling
  451. if (!isAnnotationStyleAspect) {
  452. ;
  453. } else {
  454. // ATAJ: for @AJ aspects, handle implicit binding of xxJoinPoint
  455. //if (getKind() == AdviceKind.Around) {
  456. // previousIsClosure = true;
  457. // il.append(closureInstantiation);
  458. if ("Lorg/aspectj/lang/ProceedingJoinPoint;".equals(getSignature().getParameterTypes()[i].getSignature())) {
  459. //make sure we are in an around, since we deal with the closure, not the arg here
  460. if (getKind() != AdviceKind.Around) {
  461. previousIsClosure = false;
  462. getConcreteAspect().getWorld().getMessageHandler().handleMessage(
  463. new Message(
  464. "use of ProceedingJoinPoint is allowed only on around advice ("
  465. + "arg " + i + " in " + toString() + ")",
  466. this.getSourceLocation(),
  467. true
  468. )
  469. );
  470. // try to avoid verify error and pass in null
  471. il.append(InstructionConstants.ACONST_NULL);
  472. } else {
  473. if (previousIsClosure) {
  474. il.append(InstructionConstants.DUP);
  475. } else {
  476. previousIsClosure = true;
  477. il.append(closureInstantiation.copy());
  478. }
  479. }
  480. } else if ("Lorg/aspectj/lang/JoinPoint$StaticPart;".equals(getSignature().getParameterTypes()[i].getSignature())) {
  481. previousIsClosure = false;
  482. if ((getExtraParameterFlags() & ThisJoinPointStaticPart) != 0) {
  483. shadow.getThisJoinPointStaticPartBcelVar().appendLoad(il, fact);
  484. }
  485. } else if ("Lorg/aspectj/lang/JoinPoint;".equals(getSignature().getParameterTypes()[i].getSignature())) {
  486. previousIsClosure = false;
  487. if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
  488. il.append(shadow.loadThisJoinPoint());
  489. }
  490. } else if ("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;".equals(getSignature().getParameterTypes()[i].getSignature())) {
  491. previousIsClosure = false;
  492. if ((getExtraParameterFlags() & ThisEnclosingJoinPointStaticPart) != 0) {
  493. shadow.getThisEnclosingJoinPointStaticPartBcelVar().appendLoad(il, fact);
  494. }
  495. } else if (hasExtraParameter()) {
  496. previousIsClosure = false;
  497. extraVar.appendLoadAndConvert(
  498. il,
  499. fact,
  500. getExtraParameterType().resolve(world));
  501. } else {
  502. previousIsClosure = false;
  503. getConcreteAspect().getWorld().getMessageHandler().handleMessage(
  504. new Message(
  505. "use of ProceedingJoinPoint is allowed only on around advice ("
  506. + "arg " + i + " in " + toString() + ")",
  507. this.getSourceLocation(),
  508. true
  509. )
  510. );
  511. // try to avoid verify error and pass in null
  512. il.append(InstructionConstants.ACONST_NULL);
  513. }
  514. }
  515. } else {
  516. UnresolvedType desiredTy = getBindingParameterTypes()[i];
  517. v.appendLoadAndConvert(il, fact, desiredTy.resolve(world));
  518. }
  519. }
  520. // ATAJ: for code style aspect, handles the extraFlag as usual ie not
  521. // in the middle of the formal bindings but at the end, in a rock solid ordering
  522. if (!isAnnotationStyleAspect) {
  523. if (getKind() == AdviceKind.Around) {
  524. il.append(closureInstantiation);
  525. } else if (hasExtraParameter()) {
  526. extraVar.appendLoadAndConvert(
  527. il,
  528. fact,
  529. getExtraParameterType().resolve(world));
  530. }
  531. // handle thisJoinPoint parameters
  532. // these need to be in that same order as parameters in
  533. // org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration
  534. if ((getExtraParameterFlags() & ThisJoinPointStaticPart) != 0) {
  535. shadow.getThisJoinPointStaticPartBcelVar().appendLoad(il, fact);
  536. }
  537. if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
  538. il.append(shadow.loadThisJoinPoint());
  539. }
  540. if ((getExtraParameterFlags() & ThisEnclosingJoinPointStaticPart) != 0) {
  541. shadow.getThisEnclosingJoinPointStaticPartBcelVar().appendLoad(il, fact);
  542. }
  543. }
  544. return il;
  545. }
  546. public InstructionList getNonTestAdviceInstructions(BcelShadow shadow) {
  547. return new InstructionList(
  548. Utility.createInvoke(shadow.getFactory(), shadow.getWorld(), getOriginalSignature()));
  549. }
  550. public Member getOriginalSignature() {
  551. Member sig = getSignature();
  552. if (sig instanceof ResolvedMember) {
  553. ResolvedMember rsig = (ResolvedMember)sig;
  554. if (rsig.hasBackingGenericMember()) return rsig.getBackingGenericMember();
  555. }
  556. return sig;
  557. }
  558. public InstructionList getTestInstructions(
  559. BcelShadow shadow,
  560. InstructionHandle sk,
  561. InstructionHandle fk,
  562. InstructionHandle next)
  563. {
  564. //System.err.println("test: " + pointcutTest);
  565. return BcelRenderer.renderTest(
  566. shadow.getFactory(),
  567. shadow.getWorld(),
  568. pointcutTest,
  569. sk,
  570. fk,
  571. next);
  572. }
  573. public int compareTo(Object other) {
  574. if (!(other instanceof BcelAdvice)) return 0;
  575. BcelAdvice o = (BcelAdvice)other;
  576. //System.err.println("compareTo: " + this + ", " + o);
  577. if (kind.getPrecedence() != o.kind.getPrecedence()) {
  578. if (kind.getPrecedence() > o.kind.getPrecedence()) return +1;
  579. else return -1;
  580. }
  581. if (kind.isCflow()) {
  582. // System.err.println("sort: " + this + " innerCflowEntries " + innerCflowEntries);
  583. // System.err.println(" " + o + " innerCflowEntries " + o.innerCflowEntries);
  584. boolean isBelow = (kind == AdviceKind.CflowBelowEntry);
  585. if (this.innerCflowEntries.contains(o)) return isBelow ? +1 : -1;
  586. else if (o.innerCflowEntries.contains(this)) return isBelow ? -1 : +1;
  587. else return 0;
  588. }
  589. if (kind.isPerEntry() || kind == AdviceKind.Softener) {
  590. return 0;
  591. }
  592. //System.out.println("compare: " + this + " with " + other);
  593. World world = concreteAspect.getWorld();
  594. int ret =
  595. concreteAspect.getWorld().compareByPrecedence(
  596. concreteAspect,
  597. o.concreteAspect);
  598. if (ret != 0) return ret;
  599. ResolvedType declaringAspect = getDeclaringAspect().resolve(world);
  600. ResolvedType o_declaringAspect = o.getDeclaringAspect().resolve(world);
  601. if (declaringAspect == o_declaringAspect) {
  602. if (kind.isAfter() || o.kind.isAfter()) {
  603. return this.getStart() < o.getStart() ? -1: +1;
  604. } else {
  605. return this.getStart()< o.getStart() ? +1: -1;
  606. }
  607. } else if (declaringAspect.isAssignableFrom(o_declaringAspect)) {
  608. return -1;
  609. } else if (o_declaringAspect.isAssignableFrom(declaringAspect)) {
  610. return +1;
  611. } else {
  612. return 0;
  613. }
  614. }
  615. public BcelVar[] getExposedStateAsBcelVars(boolean isAround) {
  616. // ATAJ aspect
  617. if (isAround) {
  618. // the closure instantiation has the same mapping as the extracted method from wich it is called
  619. if (getConcreteAspect()!= null && getConcreteAspect().isAnnotationStyleAspect()) {
  620. return BcelVar.NONE;
  621. }
  622. }
  623. //System.out.println("vars: " + Arrays.asList(exposedState.vars));
  624. if (exposedState == null) return BcelVar.NONE;
  625. int len = exposedState.vars.length;
  626. BcelVar[] ret = new BcelVar[len];
  627. for (int i=0; i < len; i++) {
  628. ret[i] = (BcelVar)exposedState.vars[i];
  629. }
  630. return ret; //(BcelVar[]) exposedState.vars;
  631. }
  632. public boolean hasMatchedSomething() {
  633. return hasMatchedAtLeastOnce;
  634. }
  635. public void setHasMatchedSomething(boolean hasMatchedSomething) {
  636. hasMatchedAtLeastOnce = hasMatchedSomething;
  637. }
  638. protected void suppressLintWarnings(World inWorld) {
  639. if (suppressedLintKinds == null) {
  640. if (signature instanceof BcelMethod) {
  641. this.suppressedLintKinds = Utility.getSuppressedWarnings(((BcelMethod)signature).getAnnotations(), inWorld.getLint());
  642. } else {
  643. this.suppressedLintKinds = Collections.EMPTY_LIST;
  644. }
  645. }
  646. inWorld.getLint().suppressKinds(suppressedLintKinds);
  647. }
  648. protected void clearLintSuppressions(World inWorld,Collection toClear) {
  649. inWorld.getLint().clearSuppressions(toClear);
  650. }
  651. }