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.

PointcutExpressionImpl.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /* *******************************************************************
  2. * Copyright (c) 2004 IBM Corporation.
  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. * ******************************************************************/
  10. package org.aspectj.weaver.internal.tools;
  11. import java.lang.reflect.Constructor;
  12. import java.lang.reflect.Field;
  13. import java.lang.reflect.Member;
  14. import java.lang.reflect.Method;
  15. import org.aspectj.weaver.ResolvedType;
  16. import org.aspectj.weaver.Shadow;
  17. import org.aspectj.weaver.World;
  18. import org.aspectj.weaver.ast.Literal;
  19. import org.aspectj.weaver.ast.Test;
  20. import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor;
  21. import org.aspectj.weaver.patterns.AnnotationPointcut;
  22. import org.aspectj.weaver.patterns.ArgsAnnotationPointcut;
  23. import org.aspectj.weaver.patterns.ArgsPointcut;
  24. import org.aspectj.weaver.patterns.CflowPointcut;
  25. import org.aspectj.weaver.patterns.ExposedState;
  26. import org.aspectj.weaver.patterns.IfPointcut;
  27. import org.aspectj.weaver.patterns.NotAnnotationTypePattern;
  28. import org.aspectj.weaver.patterns.NotPointcut;
  29. import org.aspectj.weaver.patterns.Pointcut;
  30. import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut;
  31. import org.aspectj.weaver.patterns.ThisOrTargetPointcut;
  32. import org.aspectj.weaver.patterns.WithinAnnotationPointcut;
  33. import org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut;
  34. import org.aspectj.weaver.reflect.ReflectionFastMatchInfo;
  35. import org.aspectj.weaver.reflect.ReflectionShadow;
  36. import org.aspectj.weaver.reflect.ReflectionWorld;
  37. import org.aspectj.weaver.reflect.ShadowMatchImpl;
  38. import org.aspectj.weaver.tools.DefaultMatchingContext;
  39. import org.aspectj.weaver.tools.MatchingContext;
  40. import org.aspectj.weaver.tools.PointcutExpression;
  41. import org.aspectj.weaver.tools.PointcutParameter;
  42. import org.aspectj.weaver.tools.ShadowMatch;
  43. /**
  44. * Map from weaver.tools interface to internal Pointcut implementation...
  45. */
  46. public class PointcutExpressionImpl implements PointcutExpression {
  47. private final static boolean MATCH_INFO = false;
  48. private World world;
  49. private Pointcut pointcut;
  50. private String expression;
  51. private PointcutParameter[] parameters;
  52. private MatchingContext matchContext = new DefaultMatchingContext();
  53. public PointcutExpressionImpl(Pointcut pointcut, String expression, PointcutParameter[] params, World inWorld) {
  54. this.pointcut = pointcut;
  55. this.expression = expression;
  56. this.world = inWorld;
  57. this.parameters = params;
  58. if (this.parameters == null) {
  59. this.parameters = new PointcutParameter[0];
  60. }
  61. }
  62. public Pointcut getUnderlyingPointcut() {
  63. return this.pointcut;
  64. }
  65. /*
  66. * (non-Javadoc)
  67. *
  68. * @see org.aspectj.weaver.tools.PointcutExpression#setMatchingContext(org.aspectj.weaver.tools.MatchingContext)
  69. */
  70. public void setMatchingContext(MatchingContext aMatchContext) {
  71. this.matchContext = aMatchContext;
  72. }
  73. public boolean couldMatchJoinPointsInType(Class aClass) {
  74. ResolvedType matchType = world.resolve(aClass.getName());
  75. if (matchType.isMissing() && (world instanceof ReflectionWorld)) {
  76. // Class is a generated class that cannot be 'looked up' via getResource.
  77. // For example a proxy or lambda.
  78. // Use the class itself in this case
  79. matchType = ((ReflectionWorld)world).resolveUsingClass(aClass);
  80. }
  81. ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType, null, this.matchContext, world);
  82. boolean couldMatch = pointcut.fastMatch(info).maybeTrue();
  83. if (MATCH_INFO) {
  84. System.out.println("MATCHINFO: fast match for '" + this.expression + "' against '" + aClass.getName() + "': "
  85. + couldMatch);
  86. }
  87. return couldMatch;
  88. }
  89. public boolean mayNeedDynamicTest() {
  90. HasPossibleDynamicContentVisitor visitor = new HasPossibleDynamicContentVisitor();
  91. pointcut.traverse(visitor, null);
  92. return visitor.hasDynamicContent();
  93. }
  94. private ExposedState getExposedState() {
  95. return new ExposedState(parameters.length);
  96. }
  97. public ShadowMatch matchesMethodExecution(Method aMethod) {
  98. ShadowMatch match = matchesExecution(aMethod);
  99. if (MATCH_INFO && match.maybeMatches()) {
  100. System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "
  101. + (match.alwaysMatches() ? "YES" : "MAYBE"));
  102. }
  103. return match;
  104. }
  105. public ShadowMatch matchesConstructorExecution(Constructor aConstructor) {
  106. ShadowMatch match = matchesExecution(aConstructor);
  107. if (MATCH_INFO && match.maybeMatches()) {
  108. System.out.println("MATCHINFO: constructor execution match on '" + aConstructor + "' for '" + this.expression + "': "
  109. + (match.alwaysMatches() ? "YES" : "MAYBE"));
  110. }
  111. return match;
  112. }
  113. private ShadowMatch matchesExecution(Member aMember) {
  114. Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember, this.matchContext);
  115. ShadowMatchImpl sm = getShadowMatch(s);
  116. sm.setSubject(aMember);
  117. sm.setWithinCode(null);
  118. sm.setWithinType(aMember.getDeclaringClass());
  119. return sm;
  120. }
  121. public ShadowMatch matchesStaticInitialization(Class aClass) {
  122. Shadow s = ReflectionShadow.makeStaticInitializationShadow(world, aClass, this.matchContext);
  123. ShadowMatchImpl sm = getShadowMatch(s);
  124. sm.setSubject(null);
  125. sm.setWithinCode(null);
  126. sm.setWithinType(aClass);
  127. if (MATCH_INFO && sm.maybeMatches()) {
  128. System.out.println("MATCHINFO: static initialization match on '" + aClass.getName() + "' for '" + this.expression
  129. + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  130. }
  131. return sm;
  132. }
  133. public ShadowMatch matchesAdviceExecution(Method aMethod) {
  134. Shadow s = ReflectionShadow.makeAdviceExecutionShadow(world, aMethod, this.matchContext);
  135. ShadowMatchImpl sm = getShadowMatch(s);
  136. sm.setSubject(aMethod);
  137. sm.setWithinCode(null);
  138. sm.setWithinType(aMethod.getDeclaringClass());
  139. if (MATCH_INFO && sm.maybeMatches()) {
  140. System.out.println("MATCHINFO: advice execution match on '" + aMethod + "' for '" + this.expression + "': "
  141. + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  142. }
  143. return sm;
  144. }
  145. public ShadowMatch matchesInitialization(Constructor aConstructor) {
  146. Shadow s = ReflectionShadow.makeInitializationShadow(world, aConstructor, this.matchContext);
  147. ShadowMatchImpl sm = getShadowMatch(s);
  148. sm.setSubject(aConstructor);
  149. sm.setWithinCode(null);
  150. sm.setWithinType(aConstructor.getDeclaringClass());
  151. if (MATCH_INFO && sm.maybeMatches()) {
  152. System.out.println("MATCHINFO: initialization match on '" + aConstructor + "' for '" + this.expression + "': "
  153. + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  154. }
  155. return sm;
  156. }
  157. public ShadowMatch matchesPreInitialization(Constructor aConstructor) {
  158. Shadow s = ReflectionShadow.makePreInitializationShadow(world, aConstructor, this.matchContext);
  159. ShadowMatchImpl sm = getShadowMatch(s);
  160. sm.setSubject(aConstructor);
  161. sm.setWithinCode(null);
  162. sm.setWithinType(aConstructor.getDeclaringClass());
  163. if (MATCH_INFO && sm.maybeMatches()) {
  164. System.out.println("MATCHINFO: preinitialization match on '" + aConstructor + "' for '" + this.expression + "': "
  165. + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  166. }
  167. return sm;
  168. }
  169. public ShadowMatch matchesMethodCall(Method aMethod, Member withinCode) {
  170. Shadow s = ReflectionShadow.makeCallShadow(world, aMethod, withinCode, this.matchContext);
  171. ShadowMatchImpl sm = getShadowMatch(s);
  172. sm.setSubject(aMethod);
  173. sm.setWithinCode(withinCode);
  174. sm.setWithinType(withinCode.getDeclaringClass());
  175. if (MATCH_INFO && sm.maybeMatches()) {
  176. System.out.println("MATCHINFO: method call match on '" + aMethod + "' withinCode='" + withinCode + "' for '"
  177. + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  178. }
  179. return sm;
  180. }
  181. public ShadowMatch matchesMethodCall(Method aMethod, Class callerType) {
  182. Shadow s = ReflectionShadow.makeCallShadow(world, aMethod, callerType, this.matchContext);
  183. ShadowMatchImpl sm = getShadowMatch(s);
  184. sm.setSubject(aMethod);
  185. sm.setWithinCode(null);
  186. sm.setWithinType(callerType);
  187. if (MATCH_INFO && sm.maybeMatches()) {
  188. System.out.println("MATCHINFO: method call match on '" + aMethod + "' callerType='" + callerType.getName() + "' for '"
  189. + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  190. }
  191. return sm;
  192. }
  193. public ShadowMatch matchesConstructorCall(Constructor aConstructor, Class callerType) {
  194. Shadow s = ReflectionShadow.makeCallShadow(world, aConstructor, callerType, this.matchContext);
  195. ShadowMatchImpl sm = getShadowMatch(s);
  196. sm.setSubject(aConstructor);
  197. sm.setWithinCode(null);
  198. sm.setWithinType(callerType);
  199. if (MATCH_INFO && sm.maybeMatches()) {
  200. System.out.println("MATCHINFO: constructor call match on '" + aConstructor + "' callerType='" + callerType.getName()
  201. + "' for '" + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  202. }
  203. return sm;
  204. }
  205. public ShadowMatch matchesConstructorCall(Constructor aConstructor, Member withinCode) {
  206. Shadow s = ReflectionShadow.makeCallShadow(world, aConstructor, withinCode, this.matchContext);
  207. ShadowMatchImpl sm = getShadowMatch(s);
  208. sm.setSubject(aConstructor);
  209. sm.setWithinCode(withinCode);
  210. sm.setWithinType(withinCode.getDeclaringClass());
  211. if (MATCH_INFO && sm.maybeMatches()) {
  212. System.out.println("MATCHINFO: constructor call match on '" + aConstructor + "' withinCode='" + withinCode + "' for '"
  213. + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  214. }
  215. return sm;
  216. }
  217. public ShadowMatch matchesHandler(Class exceptionType, Class handlingType) {
  218. Shadow s = ReflectionShadow.makeHandlerShadow(world, exceptionType, handlingType, this.matchContext);
  219. ShadowMatchImpl sm = getShadowMatch(s);
  220. sm.setSubject(null);
  221. sm.setWithinCode(null);
  222. sm.setWithinType(handlingType);
  223. if (MATCH_INFO && sm.maybeMatches()) {
  224. System.out.println("MATCHINFO: handler match on '" + exceptionType.getName() + "' handlingType='" + handlingType
  225. + "' for '" + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  226. }
  227. return sm;
  228. }
  229. public ShadowMatch matchesHandler(Class exceptionType, Member withinCode) {
  230. Shadow s = ReflectionShadow.makeHandlerShadow(world, exceptionType, withinCode, this.matchContext);
  231. ShadowMatchImpl sm = getShadowMatch(s);
  232. sm.setSubject(null);
  233. sm.setWithinCode(withinCode);
  234. sm.setWithinType(withinCode.getDeclaringClass());
  235. if (MATCH_INFO && sm.maybeMatches()) {
  236. System.out.println("MATCHINFO: handler match on '" + exceptionType.getName() + "' withinCode='" + withinCode
  237. + "' for '" + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  238. }
  239. return sm;
  240. }
  241. public ShadowMatch matchesFieldGet(Field aField, Class withinType) {
  242. Shadow s = ReflectionShadow.makeFieldGetShadow(world, aField, withinType, this.matchContext);
  243. ShadowMatchImpl sm = getShadowMatch(s);
  244. sm.setSubject(aField);
  245. sm.setWithinCode(null);
  246. sm.setWithinType(withinType);
  247. if (MATCH_INFO && sm.maybeMatches()) {
  248. System.out.println("MATCHINFO: field get match on '" + aField + "' withinType='" + withinType.getName() + "' for '"
  249. + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  250. }
  251. return sm;
  252. }
  253. public ShadowMatch matchesFieldGet(Field aField, Member withinCode) {
  254. Shadow s = ReflectionShadow.makeFieldGetShadow(world, aField, withinCode, this.matchContext);
  255. ShadowMatchImpl sm = getShadowMatch(s);
  256. sm.setSubject(aField);
  257. sm.setWithinCode(withinCode);
  258. sm.setWithinType(withinCode.getDeclaringClass());
  259. if (MATCH_INFO && sm.maybeMatches()) {
  260. System.out.println("MATCHINFO: field get match on '" + aField + "' withinCode='" + withinCode + "' for '"
  261. + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  262. }
  263. return sm;
  264. }
  265. public ShadowMatch matchesFieldSet(Field aField, Class withinType) {
  266. Shadow s = ReflectionShadow.makeFieldSetShadow(world, aField, withinType, this.matchContext);
  267. ShadowMatchImpl sm = getShadowMatch(s);
  268. sm.setSubject(aField);
  269. sm.setWithinCode(null);
  270. sm.setWithinType(withinType);
  271. if (MATCH_INFO && sm.maybeMatches()) {
  272. System.out.println("MATCHINFO: field set match on '" + aField + "' withinType='" + withinType.getName() + "' for '"
  273. + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  274. }
  275. return sm;
  276. }
  277. public ShadowMatch matchesFieldSet(Field aField, Member withinCode) {
  278. Shadow s = ReflectionShadow.makeFieldSetShadow(world, aField, withinCode, this.matchContext);
  279. ShadowMatchImpl sm = getShadowMatch(s);
  280. sm.setSubject(aField);
  281. sm.setWithinCode(withinCode);
  282. sm.setWithinType(withinCode.getDeclaringClass());
  283. if (MATCH_INFO && sm.maybeMatches()) {
  284. System.out.println("MATCHINFO: field set match on '" + aField + "' withinCode='" + withinCode + "' for '"
  285. + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE"));
  286. }
  287. return sm;
  288. }
  289. private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
  290. org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
  291. Test residueTest = Literal.TRUE;
  292. ExposedState state = getExposedState();
  293. if (match.maybeTrue()) {
  294. residueTest = pointcut.findResidue(forShadow, state);
  295. }
  296. ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters);
  297. sm.setMatchingContext(this.matchContext);
  298. return sm;
  299. }
  300. /*
  301. * (non-Javadoc)
  302. *
  303. * @see org.aspectj.weaver.tools.PointcutExpression#getPointcutExpression()
  304. */
  305. public String getPointcutExpression() {
  306. return expression;
  307. }
  308. private static class HasPossibleDynamicContentVisitor extends AbstractPatternNodeVisitor {
  309. private boolean hasDynamicContent = false;
  310. public boolean hasDynamicContent() {
  311. return hasDynamicContent;
  312. }
  313. @Override
  314. public Object visit(WithinAnnotationPointcut node, Object data) {
  315. hasDynamicContent = true;
  316. return null;
  317. }
  318. @Override
  319. public Object visit(WithinCodeAnnotationPointcut node, Object data) {
  320. hasDynamicContent = true;
  321. return null;
  322. }
  323. @Override
  324. public Object visit(AnnotationPointcut node, Object data) {
  325. hasDynamicContent = true;
  326. return null;
  327. }
  328. @Override
  329. public Object visit(ArgsAnnotationPointcut node, Object data) {
  330. hasDynamicContent = true;
  331. return null;
  332. }
  333. @Override
  334. public Object visit(ArgsPointcut node, Object data) {
  335. hasDynamicContent = true;
  336. return null;
  337. }
  338. @Override
  339. public Object visit(CflowPointcut node, Object data) {
  340. hasDynamicContent = true;
  341. return null;
  342. }
  343. @Override
  344. public Object visit(IfPointcut node, Object data) {
  345. hasDynamicContent = true;
  346. return null;
  347. }
  348. @Override
  349. public Object visit(NotAnnotationTypePattern node, Object data) {
  350. return node.getNegatedPattern().accept(this, data);
  351. }
  352. @Override
  353. public Object visit(NotPointcut node, Object data) {
  354. return node.getNegatedPointcut().accept(this, data);
  355. }
  356. @Override
  357. public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
  358. hasDynamicContent = true;
  359. return null;
  360. }
  361. @Override
  362. public Object visit(ThisOrTargetPointcut node, Object data) {
  363. hasDynamicContent = true;
  364. return null;
  365. }
  366. }
  367. public static class Handler implements Member {
  368. private Class decClass;
  369. private Class exType;
  370. public Handler(Class decClass, Class exType) {
  371. this.decClass = decClass;
  372. this.exType = exType;
  373. }
  374. public int getModifiers() {
  375. return 0;
  376. }
  377. public Class getDeclaringClass() {
  378. return decClass;
  379. }
  380. public String getName() {
  381. return null;
  382. }
  383. public Class getHandledExceptionType() {
  384. return exType;
  385. }
  386. public boolean isSynthetic() {
  387. return false;
  388. }
  389. }
  390. }