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.

IfPointcut.java 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Alexandre Vasseur if() implementation for @AJ style
  12. * ******************************************************************/
  13. package org.aspectj.weaver.patterns;
  14. import java.io.IOException;
  15. import java.util.ArrayList;
  16. import java.util.Iterator;
  17. import java.util.List;
  18. import java.util.Map;
  19. import org.aspectj.bridge.IMessage;
  20. import org.aspectj.bridge.MessageUtil;
  21. import org.aspectj.util.FuzzyBoolean;
  22. import org.aspectj.weaver.Advice;
  23. import org.aspectj.weaver.AjcMemberMaker;
  24. import org.aspectj.weaver.BCException;
  25. import org.aspectj.weaver.CompressingDataOutputStream;
  26. import org.aspectj.weaver.ISourceContext;
  27. import org.aspectj.weaver.IntMap;
  28. import org.aspectj.weaver.ResolvedMember;
  29. import org.aspectj.weaver.ResolvedMemberImpl;
  30. import org.aspectj.weaver.ResolvedPointcutDefinition;
  31. import org.aspectj.weaver.ResolvedType;
  32. import org.aspectj.weaver.Shadow;
  33. import org.aspectj.weaver.ShadowMunger;
  34. import org.aspectj.weaver.UnresolvedType;
  35. import org.aspectj.weaver.VersionedDataInputStream;
  36. import org.aspectj.weaver.WeaverMessages;
  37. import org.aspectj.weaver.World;
  38. import org.aspectj.weaver.ast.Expr;
  39. import org.aspectj.weaver.ast.Literal;
  40. import org.aspectj.weaver.ast.Test;
  41. import org.aspectj.weaver.ast.Var;
  42. public class IfPointcut extends Pointcut {
  43. public ResolvedMember testMethod;
  44. public int extraParameterFlags;
  45. /**
  46. * A token source dump that looks like a pointcut (but is NOT parseable at all - just here to help debugging etc)
  47. */
  48. private final String enclosingPointcutHint;
  49. public Pointcut residueSource;
  50. int baseArgsCount;
  51. // XXX some way to compute args
  52. public IfPointcut(ResolvedMember testMethod, int extraParameterFlags) {
  53. this.testMethod = testMethod;
  54. this.extraParameterFlags = extraParameterFlags;
  55. this.pointcutKind = IF;
  56. this.enclosingPointcutHint = null;
  57. }
  58. /**
  59. * No-arg constructor for @AJ style, where the if() body is actually the @Pointcut annotated method
  60. */
  61. public IfPointcut(String enclosingPointcutHint) {
  62. this.pointcutKind = IF;
  63. this.enclosingPointcutHint = enclosingPointcutHint;
  64. this.testMethod = null;// resolved during concretize
  65. this.extraParameterFlags = -1;// allows to keep track of the @Aj style
  66. }
  67. @Override
  68. public int couldMatchKinds() {
  69. return Shadow.ALL_SHADOW_KINDS_BITS;
  70. }
  71. @Override
  72. public FuzzyBoolean fastMatch(FastMatchInfo type) {
  73. return FuzzyBoolean.MAYBE;
  74. }
  75. @Override
  76. protected FuzzyBoolean matchInternal(Shadow shadow) {
  77. if ((extraParameterFlags & Advice.ConstantReference) != 0) {
  78. if ((extraParameterFlags & Advice.ConstantValue) != 0) {
  79. return FuzzyBoolean.YES;
  80. } else {
  81. return FuzzyBoolean.NO;
  82. }
  83. }
  84. // ??? this is not maximally efficient
  85. return FuzzyBoolean.MAYBE;
  86. }
  87. public boolean alwaysFalse() {
  88. return false;
  89. }
  90. public boolean alwaysTrue() {
  91. return false;
  92. }
  93. // enh 76055
  94. public Pointcut getResidueSource() {
  95. return residueSource;
  96. }
  97. @Override
  98. public void write(CompressingDataOutputStream s) throws IOException {
  99. s.writeByte(Pointcut.IF);
  100. s.writeBoolean(testMethod != null); // do we have a test method?
  101. if (testMethod != null) {
  102. testMethod.write(s);
  103. }
  104. s.writeByte(extraParameterFlags);
  105. writeLocation(s);
  106. }
  107. public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  108. boolean hasTestMethod = s.readBoolean();
  109. ResolvedMember resolvedTestMethod = null;
  110. if (hasTestMethod) { // should always have a test method unless @AJ style
  111. resolvedTestMethod = ResolvedMemberImpl.readResolvedMember(s, context);
  112. }
  113. IfPointcut ret = new IfPointcut(resolvedTestMethod, s.readByte());
  114. ret.readLocation(context, s);
  115. return ret;
  116. }
  117. @Override
  118. public void resolveBindings(IScope scope, Bindings bindings) {
  119. // ??? all we need is good error messages in here in cflow contexts
  120. }
  121. @Override
  122. public boolean equals(Object other) {
  123. if (!(other instanceof IfPointcut)) {
  124. return false;
  125. }
  126. IfPointcut o = (IfPointcut) other;
  127. if (o.testMethod == null) {
  128. return (this.testMethod == null);
  129. }
  130. return o.testMethod.equals(this.testMethod);
  131. }
  132. @Override
  133. public int hashCode() {
  134. int result = 17;
  135. result = 37 * result + testMethod.hashCode();
  136. return result;
  137. }
  138. @Override
  139. public String toString() {
  140. if (extraParameterFlags < 0) {
  141. // @AJ style
  142. return "if()";
  143. } else {
  144. return "if(" + testMethod + ")";// FIXME AV - bad, this makes it unparsable. Perhaps we can use if() for code style
  145. // behind the scene!
  146. }
  147. }
  148. // ??? The implementation of name binding and type checking in if PCDs is very convoluted
  149. // There has to be a better way...
  150. private boolean findingResidue = false;
  151. // Similar to lastMatchedShadowId - but only for if PCDs.
  152. private int ifLastMatchedShadowId;
  153. private Test ifLastMatchedShadowResidue;
  154. /**
  155. * At each shadow that matched, the residue can be different.
  156. */
  157. @Override
  158. protected Test findResidueInternal(Shadow shadow, ExposedState state) {
  159. if (findingResidue) {
  160. return Literal.TRUE;
  161. }
  162. findingResidue = true;
  163. try {
  164. // Have we already been asked this question?
  165. if (shadow.shadowId == ifLastMatchedShadowId) {
  166. return ifLastMatchedShadowResidue;
  167. }
  168. Test ret = Literal.TRUE;
  169. List<Var> args = new ArrayList<>();
  170. // code style
  171. if (extraParameterFlags >= 0) {
  172. if ((extraParameterFlags & Advice.ConstantReference) != 0) {
  173. // it is either always true or always false, no need for test
  174. if ((extraParameterFlags & Advice.ConstantValue) != 0) {
  175. ret = Literal.TRUE;
  176. ifLastMatchedShadowId = shadow.shadowId;
  177. ifLastMatchedShadowResidue = ret;
  178. return ret;
  179. } else {
  180. // Dont think we should be in here as the match cannot have succeeded...
  181. ret = Literal.FALSE;
  182. ifLastMatchedShadowId = shadow.shadowId;
  183. ifLastMatchedShadowResidue = ret;
  184. return ret;
  185. }
  186. }
  187. // If there are no args to sort out, don't bother with the recursive call
  188. if (baseArgsCount > 0) {
  189. ExposedState myState = new ExposedState(baseArgsCount);
  190. myState.setConcreteAspect(state.getConcreteAspect());
  191. // ??? we throw out the test that comes from this walk. All we want here
  192. // is bindings for the arguments
  193. residueSource.findResidue(shadow, myState);
  194. UnresolvedType[] pTypes = (testMethod == null ? null : testMethod.getParameterTypes());
  195. if (pTypes != null && baseArgsCount > pTypes.length) { // pr155347
  196. throw new BCException("Unexpected problem with testMethod " + testMethod + ": expecting " + baseArgsCount
  197. + " arguments");
  198. }
  199. // pr118149
  200. // It is possible for vars in myState (which would normally be set
  201. // in the call to residueSource.findResidue) to not be set (be null)
  202. // in an Or pointcut with if expressions in both branches, and where
  203. // one branch is known statically to not match. In this situation we
  204. // simply return Test.
  205. for (int i = 0; i < baseArgsCount; i++) {
  206. Var v = myState.get(i);
  207. if (v == null) {
  208. continue; // pr118149
  209. }
  210. args.add(v);
  211. ret = Test.makeAnd(ret, Test.makeInstanceof(v, pTypes[i].resolve(shadow.getIWorld())));
  212. }
  213. }
  214. // handle thisJoinPoint parameters
  215. if ((extraParameterFlags & Advice.ThisJoinPoint) != 0) {
  216. args.add(shadow.getThisJoinPointVar());
  217. }
  218. if ((extraParameterFlags & Advice.ThisJoinPointStaticPart) != 0) {
  219. args.add(shadow.getThisJoinPointStaticPartVar());
  220. }
  221. if ((extraParameterFlags & Advice.ThisEnclosingJoinPointStaticPart) != 0) {
  222. args.add(shadow.getThisEnclosingJoinPointStaticPartVar());
  223. }
  224. if ((extraParameterFlags & Advice.ThisAspectInstance) != 0) {
  225. args.add(shadow.getThisAspectInstanceVar(state.getConcreteAspect()));
  226. }
  227. } else {
  228. // @style is slightly different
  229. int currentStateIndex = 0;
  230. // FIXME AV - "args(jp)" test(jp, thejp) will fail here
  231. for (int i = 0; i < testMethod.getParameterTypes().length; i++) {
  232. String argSignature = testMethod.getParameterTypes()[i].getSignature();
  233. if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature)) {
  234. args.add(shadow.getThisJoinPointVar());
  235. } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature)) {
  236. args.add(shadow.getThisJoinPointVar());
  237. } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature)) {
  238. args.add(shadow.getThisJoinPointStaticPartVar());
  239. } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) {
  240. args.add(shadow.getThisEnclosingJoinPointStaticPartVar());
  241. } else {
  242. if (state.size() == 0 || currentStateIndex > state.size()) {
  243. String[] paramNames = testMethod.getParameterNames();
  244. StringBuilder errorParameter = new StringBuilder();
  245. if (paramNames != null) {
  246. errorParameter.append(testMethod.getParameterTypes()[i].getName()).append(" ");
  247. errorParameter.append(paramNames[i]);
  248. shadow.getIWorld()
  249. .getMessageHandler()
  250. .handleMessage(
  251. MessageUtil.error("Missing binding for if() pointcut method. Parameter " + (i + 1)
  252. + "(" + errorParameter.toString()
  253. + ") must be bound - even in reference pointcuts (compiler limitation)",
  254. testMethod.getSourceLocation()));
  255. } else {
  256. shadow.getIWorld()
  257. .getMessageHandler()
  258. .handleMessage(
  259. MessageUtil.error("Missing binding for if() pointcut method. Parameter " + (i + 1)
  260. + " must be bound - even in reference pointcuts (compiler limitation)",
  261. testMethod.getSourceLocation()));
  262. }
  263. return Literal.TRUE; // exit quickly
  264. }
  265. // we don't use i as JoinPoint.* can be anywhere in the signature in @style
  266. Var v = state.get(currentStateIndex++);
  267. while (v == null && currentStateIndex < state.size()) { // pr162135
  268. v = state.get(currentStateIndex++);
  269. }
  270. args.add(v);
  271. ret = Test.makeAnd(ret,
  272. Test.makeInstanceof(v, testMethod.getParameterTypes()[i].resolve(shadow.getIWorld())));
  273. }
  274. }
  275. }
  276. ret = Test.makeAnd(ret, Test.makeCall(testMethod, (Expr[]) args.toArray(Expr.NONE)));
  277. // Remember...
  278. ifLastMatchedShadowId = shadow.shadowId;
  279. ifLastMatchedShadowResidue = ret;
  280. return ret;
  281. } finally {
  282. findingResidue = false;
  283. }
  284. }
  285. // amc - the only reason this override seems to be here is to stop the copy, but
  286. // that can be prevented by overriding shouldCopyLocationForConcretization,
  287. // allowing me to make the method final in Pointcut.
  288. // public Pointcut concretize(ResolvedType inAspect, IntMap bindings) {
  289. // return this.concretize1(inAspect, bindings);
  290. // }
  291. @Override
  292. protected boolean shouldCopyLocationForConcretize() {
  293. return false;
  294. }
  295. private IfPointcut partiallyConcretized = null;
  296. @Override
  297. public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
  298. // System.err.println("concretize: " + this + " already: " + partiallyConcretized);
  299. if (isDeclare(bindings.getEnclosingAdvice())) {
  300. // Enforce rule about which designators are supported in declare
  301. inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
  302. bindings.getEnclosingAdvice().getSourceLocation(), null);
  303. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  304. }
  305. if (partiallyConcretized != null) {
  306. return partiallyConcretized;
  307. }
  308. final IfPointcut ret;
  309. if (extraParameterFlags < 0 && testMethod == null) {
  310. // @AJ style, we need to find the testMethod in the aspect defining the "if()" enclosing pointcut
  311. ResolvedPointcutDefinition def = bindings.peekEnclosingDefinition();
  312. if (def != null) {
  313. ResolvedType aspect = inAspect.getWorld().resolve(def.getDeclaringType());
  314. for (Iterator memberIter = aspect.getMethods(true, true); memberIter.hasNext();) {
  315. ResolvedMember method = (ResolvedMember) memberIter.next();
  316. if (def.getName().equals(method.getName())
  317. && def.getParameterTypes().length == method.getParameterTypes().length) {
  318. boolean sameSig = true;
  319. for (int j = 0; j < method.getParameterTypes().length; j++) {
  320. UnresolvedType argJ = method.getParameterTypes()[j];
  321. if (!argJ.equals(def.getParameterTypes()[j])) {
  322. sameSig = false;
  323. break;
  324. }
  325. }
  326. if (sameSig) {
  327. testMethod = method;
  328. break;
  329. }
  330. }
  331. }
  332. if (testMethod == null) {
  333. inAspect.getWorld().showMessage(IMessage.ERROR,
  334. "Cannot find if() body from '" + def.toString() + "' for '" + enclosingPointcutHint + "'",
  335. this.getSourceLocation(), null);
  336. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  337. }
  338. } else {
  339. testMethod = inAspect.getWorld().resolve(bindings.getAdviceSignature());
  340. }
  341. ret = new IfPointcut(enclosingPointcutHint);
  342. ret.testMethod = testMethod;
  343. } else {
  344. ret = new IfPointcut(testMethod, extraParameterFlags);
  345. }
  346. ret.copyLocationFrom(this);
  347. partiallyConcretized = ret;
  348. // It is possible to directly code your pointcut expression in a per clause
  349. // rather than defining a pointcut declaration and referencing it in your
  350. // per clause. If you do this, we have problems (bug #62458). For now,
  351. // let's police that you are trying to code a pointcut in a per clause and
  352. // put out a compiler error.
  353. if (bindings.directlyInAdvice() && bindings.getEnclosingAdvice() == null) {
  354. // Assumption: if() is in a per clause if we say we are directly in advice
  355. // but we have no enclosing advice.
  356. inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_PERCLAUSE),
  357. this.getSourceLocation(), null);
  358. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  359. }
  360. if (bindings.directlyInAdvice()) {
  361. ShadowMunger advice = bindings.getEnclosingAdvice();
  362. if (advice instanceof Advice) {
  363. ret.baseArgsCount = ((Advice) advice).getBaseParameterCount();
  364. } else {
  365. ret.baseArgsCount = 0;
  366. }
  367. ret.residueSource = advice.getPointcut().concretize(inAspect, inAspect, ret.baseArgsCount, advice);
  368. } else {
  369. ResolvedPointcutDefinition def = bindings.peekEnclosingDefinition();
  370. if (def == CflowPointcut.CFLOW_MARKER) {
  371. inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_LEXICALLY_IN_CFLOW),
  372. getSourceLocation(), null);
  373. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  374. }
  375. ret.baseArgsCount = def.getParameterTypes().length;
  376. // for @style, we have implicit binding for JoinPoint.* things
  377. // FIXME AV - will lead to failure for "args(jp)" test(jp, thejp) / see args() implementation
  378. if (ret.extraParameterFlags < 0) {
  379. ret.baseArgsCount = 0;
  380. for (int i = 0; i < testMethod.getParameterTypes().length; i++) {
  381. String argSignature = testMethod.getParameterTypes()[i].getSignature();
  382. if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature)
  383. || AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature)
  384. || AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature)
  385. || AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) {
  386. } else {
  387. ret.baseArgsCount++;
  388. }
  389. }
  390. }
  391. IntMap newBindings = IntMap.idMap(ret.baseArgsCount);
  392. newBindings.copyContext(bindings);
  393. ret.residueSource = def.getPointcut().concretize(inAspect, declaringType, newBindings);
  394. }
  395. return ret;
  396. }
  397. // we can't touch "if" methods
  398. @Override
  399. public Pointcut parameterizeWith(Map typeVariableMap, World w) {
  400. return this;
  401. }
  402. // public static Pointcut MatchesNothing = new MatchesNothingPointcut();
  403. // ??? there could possibly be some good optimizations to be done at this point
  404. public static IfPointcut makeIfFalsePointcut(State state) {
  405. IfPointcut ret = new IfFalsePointcut();
  406. ret.state = state;
  407. return ret;
  408. }
  409. @Override
  410. public Object accept(PatternNodeVisitor visitor, Object data) {
  411. return visitor.visit(this, data);
  412. }
  413. public static class IfFalsePointcut extends IfPointcut {
  414. public IfFalsePointcut() {
  415. super(null, 0);
  416. this.pointcutKind = Pointcut.IF_FALSE;
  417. }
  418. @Override
  419. public int couldMatchKinds() {
  420. return Shadow.NO_SHADOW_KINDS_BITS;
  421. }
  422. @Override
  423. public boolean alwaysFalse() {
  424. return true;
  425. }
  426. @Override
  427. protected Test findResidueInternal(Shadow shadow, ExposedState state) {
  428. return Literal.FALSE; // can only get here if an earlier error occurred
  429. }
  430. @Override
  431. public FuzzyBoolean fastMatch(FastMatchInfo type) {
  432. return FuzzyBoolean.NO;
  433. }
  434. @Override
  435. protected FuzzyBoolean matchInternal(Shadow shadow) {
  436. return FuzzyBoolean.NO;
  437. }
  438. @Override
  439. public void resolveBindings(IScope scope, Bindings bindings) {
  440. }
  441. @Override
  442. public void postRead(ResolvedType enclosingType) {
  443. }
  444. @Override
  445. public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
  446. if (isDeclare(bindings.getEnclosingAdvice())) {
  447. // Enforce rule about which designators are supported in declare
  448. inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
  449. bindings.getEnclosingAdvice().getSourceLocation(), null);
  450. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  451. }
  452. return makeIfFalsePointcut(state);
  453. }
  454. @Override
  455. public void write(CompressingDataOutputStream s) throws IOException {
  456. s.writeByte(Pointcut.IF_FALSE);
  457. }
  458. @Override
  459. public int hashCode() {
  460. int result = 17;
  461. return result;
  462. }
  463. @Override
  464. public String toString() {
  465. return "if(false)";
  466. }
  467. }
  468. public static IfPointcut makeIfTruePointcut(State state) {
  469. IfPointcut ret = new IfTruePointcut();
  470. ret.state = state;
  471. return ret;
  472. }
  473. public static class IfTruePointcut extends IfPointcut {
  474. public IfTruePointcut() {
  475. super(null, 0);
  476. this.pointcutKind = Pointcut.IF_TRUE;
  477. }
  478. @Override
  479. public boolean alwaysTrue() {
  480. return true;
  481. }
  482. @Override
  483. protected Test findResidueInternal(Shadow shadow, ExposedState state) {
  484. return Literal.TRUE; // can only get here if an earlier error occurred
  485. }
  486. @Override
  487. public FuzzyBoolean fastMatch(FastMatchInfo type) {
  488. return FuzzyBoolean.YES;
  489. }
  490. @Override
  491. protected FuzzyBoolean matchInternal(Shadow shadow) {
  492. return FuzzyBoolean.YES;
  493. }
  494. @Override
  495. public void resolveBindings(IScope scope, Bindings bindings) {
  496. }
  497. @Override
  498. public void postRead(ResolvedType enclosingType) {
  499. }
  500. @Override
  501. public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
  502. if (isDeclare(bindings.getEnclosingAdvice())) {
  503. // Enforce rule about which designators are supported in declare
  504. inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
  505. bindings.getEnclosingAdvice().getSourceLocation(), null);
  506. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  507. }
  508. return makeIfTruePointcut(state);
  509. }
  510. @Override
  511. public void write(CompressingDataOutputStream s) throws IOException {
  512. s.writeByte(IF_TRUE);
  513. }
  514. @Override
  515. public int hashCode() {
  516. int result = 37;
  517. return result;
  518. }
  519. @Override
  520. public String toString() {
  521. return "if(true)";
  522. }
  523. }
  524. /**
  525. * Called when it is determined that the pointcut refers to a constant value of TRUE or FALSE - enabling exact matching and no
  526. * unnecessary calls to the method representing the if body.
  527. */
  528. public void setAlways(boolean matches) {
  529. extraParameterFlags |= Advice.ConstantReference;
  530. if (matches) {
  531. extraParameterFlags |= Advice.ConstantValue;
  532. }
  533. }
  534. }