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.

PerThisOrTargetPointcutVisitor.java 8.2KB

15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
12 yıl önce
15 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*******************************************************************************
  2. * Copyright (c) 2005 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Alexandre Vasseur initial implementation
  11. *******************************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import org.aspectj.weaver.BCException;
  14. import org.aspectj.weaver.ResolvedPointcutDefinition;
  15. import org.aspectj.weaver.ResolvedType;
  16. import org.aspectj.weaver.Shadow;
  17. /**
  18. * A visitor that turns a pointcut into a type pattern equivalent for a perthis or pertarget matching: - pertarget(target(Foo)) →
  19. * Foo+ (this one is a special case..) - pertarget(execution(* Foo.do()) → Foo - perthis(call(* Foo.do()) → * - perthis(!call(*
  20. * Foo.do()) → * (see how the ! has been absorbed here..)
  21. *
  22. * @author Alexandre Vasseur (alex AT gnilux DOT com)
  23. */
  24. public class PerThisOrTargetPointcutVisitor extends AbstractPatternNodeVisitor {
  25. /** A maybe marker */
  26. private final static TypePattern MAYBE = new TypePatternMayBe();
  27. private final boolean m_isTarget;
  28. private final ResolvedType m_fromAspectType;
  29. public PerThisOrTargetPointcutVisitor(boolean isTarget, ResolvedType fromAspectType) {
  30. m_isTarget = isTarget;
  31. m_fromAspectType = fromAspectType;
  32. }
  33. public TypePattern getPerTypePointcut(Pointcut perClausePointcut) {
  34. Object o = perClausePointcut.accept(this, perClausePointcut);
  35. if (o instanceof TypePattern) {
  36. return (TypePattern) o;
  37. } else {
  38. throw new BCException("perClausePointcut visitor did not return a typepattern, it returned " + o
  39. + (o == null ? "" : " of type " + o.getClass()));
  40. }
  41. }
  42. // -- visitor methods, all is like Identity visitor except when it comes to transform pointcuts
  43. public Object visit(WithinPointcut node, Object data) {
  44. if (m_isTarget) {
  45. // pertarget(.. && within(Foo)) => true
  46. // pertarget(.. && !within(Foo)) => true as well !
  47. return MAYBE;
  48. } else {
  49. return node.getTypePattern();
  50. }
  51. }
  52. public Object visit(WithincodePointcut node, Object data) {
  53. if (m_isTarget) {
  54. // pertarget(.. && withincode(* Foo.do())) => true
  55. // pertarget(.. && !withincode(* Foo.do())) => true as well !
  56. return MAYBE;
  57. } else {
  58. return node.getSignature().getDeclaringType();
  59. }
  60. }
  61. public Object visit(WithinAnnotationPointcut node, Object data) {
  62. if (m_isTarget) {
  63. return MAYBE;
  64. } else {
  65. return new AnyWithAnnotationTypePattern(node.getAnnotationTypePattern());
  66. }
  67. }
  68. public Object visit(WithinCodeAnnotationPointcut node, Object data) {
  69. if (m_isTarget) {
  70. return MAYBE;
  71. } else {
  72. return MAYBE;// FIXME AV - can we optimize ? perthis(@withincode(Foo)) = hasmethod(..)
  73. }
  74. }
  75. public Object visit(KindedPointcut node, Object data) {
  76. if (node.getKind().equals(Shadow.AdviceExecution)) {
  77. return MAYBE;// TODO AV - can we do better ?
  78. } else if (node.getKind().equals(Shadow.ConstructorExecution) || node.getKind().equals(Shadow.Initialization)
  79. || node.getKind().equals(Shadow.MethodExecution) || node.getKind().equals(Shadow.PreInitialization)
  80. || node.getKind().equals(Shadow.StaticInitialization)) {
  81. SignaturePattern signaturePattern = node.getSignature();
  82. boolean isStarAnnotation = signaturePattern.isStarAnnotation();
  83. // For a method execution joinpoint, we check for an annotation pattern. If there is one we know it will be matched
  84. // against the 'primary' joinpoint (the one in the type) - 'super'joinpoints can't match it. If this situation occurs
  85. // we can re-use the HasMemberTypePattern to guard on whether the perthis/target should match. pr354470
  86. if (!m_isTarget && node.getKind().equals(Shadow.MethodExecution)) {
  87. if (!isStarAnnotation) {
  88. return new HasMemberTypePatternForPerThisMatching(signaturePattern);
  89. }
  90. }
  91. return signaturePattern.getDeclaringType();
  92. } else if (node.getKind().equals(Shadow.ConstructorCall) || node.getKind().equals(Shadow.FieldGet)
  93. || node.getKind().equals(Shadow.FieldSet) || node.getKind().equals(Shadow.MethodCall)) {
  94. if (m_isTarget) {
  95. return node.getSignature().getDeclaringType();
  96. } else {
  97. return MAYBE;
  98. }
  99. } else if (node.getKind().equals(Shadow.ExceptionHandler)) {
  100. return MAYBE;
  101. } else {
  102. throw new ParserException("Undetermined - should not happen: " + node.getKind().getSimpleName(), null);
  103. }
  104. }
  105. public Object visit(AndPointcut node, Object data) {
  106. return new AndTypePattern(getPerTypePointcut(node.left), getPerTypePointcut(node.right));
  107. }
  108. public Object visit(OrPointcut node, Object data) {
  109. return new OrTypePattern(getPerTypePointcut(node.left), getPerTypePointcut(node.right));
  110. }
  111. public Object visit(NotPointcut node, Object data) {
  112. // TypePattern negated = getPerTypePointcut(node.getNegatedPointcut());
  113. // if (MAYBE.equals(negated)) {
  114. // return MAYBE;
  115. // }
  116. // return new NotTypePattern(negated);
  117. // AMC - the only safe thing to return here is maybe...
  118. // see for example pr114054
  119. return MAYBE;
  120. }
  121. public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
  122. if (m_isTarget && !node.isThis()) {
  123. return new AnyWithAnnotationTypePattern(node.getAnnotationTypePattern());
  124. } else if (!m_isTarget && node.isThis()) {
  125. return new AnyWithAnnotationTypePattern(node.getAnnotationTypePattern());
  126. } else {
  127. // perthis(@target(Foo))
  128. return MAYBE;
  129. }
  130. }
  131. public Object visit(ThisOrTargetPointcut node, Object data) {
  132. if ((m_isTarget && !node.isThis()) || (!m_isTarget && node.isThis())) {
  133. String pointcutString = node.getType().toString();
  134. // see pr115788 "<nothing>" means there was a problem resolving types - that will be reported so dont blow up
  135. // the parser here..
  136. if (pointcutString.equals("<nothing>")) {
  137. return new NoTypePattern();
  138. }
  139. // pertarget(target(Foo)) => Foo+ for type pattern matching
  140. // perthis(this(Foo)) => Foo+ for type pattern matching
  141. // TODO AV - we do like a deep copy by parsing it again.. quite dirty, would need a clean deep copy
  142. TypePattern copy = new PatternParser(pointcutString.replace('$', '.')).parseTypePattern();
  143. // TODO AV - see dirty replace from $ to . here as inner classes are with $ instead (#108488)
  144. copy.includeSubtypes = true;
  145. return copy;
  146. } else {
  147. // perthis(target(Foo)) => maybe
  148. return MAYBE;
  149. }
  150. }
  151. public Object visit(ReferencePointcut node, Object data) {
  152. // && pc_ref()
  153. // we know there is no support for binding in perClause: perthis(pc_ref(java.lang.String))
  154. // TODO AV - may need some work for generics..
  155. ResolvedPointcutDefinition pointcutDec;
  156. ResolvedType searchStart = m_fromAspectType;
  157. if (node.onType != null) {
  158. searchStart = node.onType.resolve(m_fromAspectType.getWorld());
  159. if (searchStart.isMissing()) {
  160. return MAYBE;// this should not happen since concretize will fails but just in case..
  161. }
  162. }
  163. pointcutDec = searchStart.findPointcut(node.name);
  164. return getPerTypePointcut(pointcutDec.getPointcut());
  165. }
  166. public Object visit(IfPointcut node, Object data) {
  167. return TypePattern.ANY;
  168. }
  169. public Object visit(HandlerPointcut node, Object data) {
  170. // quiet unexpected since a KindedPointcut but do as if...
  171. return MAYBE;
  172. }
  173. public Object visit(CflowPointcut node, Object data) {
  174. return MAYBE;
  175. }
  176. public Object visit(ConcreteCflowPointcut node, Object data) {
  177. return MAYBE;
  178. }
  179. public Object visit(ArgsPointcut node, Object data) {
  180. return MAYBE;
  181. }
  182. public Object visit(ArgsAnnotationPointcut node, Object data) {
  183. return MAYBE;
  184. }
  185. public Object visit(AnnotationPointcut node, Object data) {
  186. return MAYBE;
  187. }
  188. public Object visit(Pointcut.MatchesNothingPointcut node, Object data) {
  189. // a small hack since the usual MatchNothing has its toString = "<nothing>" which is not parseable back
  190. // while I use back parsing for check purpose.
  191. return new NoTypePattern() {
  192. public String toString() {
  193. return "false";
  194. }
  195. };
  196. }
  197. /**
  198. * A MayBe type pattern that acts as ANY except that !MAYBE = MAYBE
  199. *
  200. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  201. */
  202. private static class TypePatternMayBe extends AnyTypePattern {
  203. }
  204. }