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.

ThisOrTargetAnnotationPointcut.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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 Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * ******************************************************************/
  10. package org.aspectj.weaver.patterns;
  11. import java.io.DataInputStream;
  12. import java.io.DataOutputStream;
  13. import java.io.IOException;
  14. import java.util.ArrayList;
  15. import java.util.Collections;
  16. import java.util.HashSet;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Set;
  20. import org.aspectj.bridge.IMessage;
  21. import org.aspectj.bridge.ISourceLocation;
  22. import org.aspectj.bridge.Message;
  23. import org.aspectj.bridge.MessageUtil;
  24. import org.aspectj.util.FuzzyBoolean;
  25. import org.aspectj.weaver.ISourceContext;
  26. import org.aspectj.weaver.IntMap;
  27. import org.aspectj.weaver.ResolvedTypeX;
  28. import org.aspectj.weaver.Shadow;
  29. import org.aspectj.weaver.ShadowMunger;
  30. import org.aspectj.weaver.TypeX;
  31. import org.aspectj.weaver.WeaverMessages;
  32. import org.aspectj.weaver.ast.Literal;
  33. import org.aspectj.weaver.ast.Test;
  34. import org.aspectj.weaver.ast.Var;
  35. /**
  36. * @author colyer
  37. *
  38. * TODO To change the template for this generated type comment go to
  39. * Window - Preferences - Java - Code Style - Code Templates
  40. */
  41. public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
  42. private boolean isThis;
  43. private boolean alreadyWarnedAboutDEoW = false;
  44. private ExactAnnotationTypePattern annotationTypePattern;
  45. private ShadowMunger munger;
  46. private static final Set thisKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
  47. private static final Set targetKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
  48. static {
  49. for (Iterator iter = Shadow.ALL_SHADOW_KINDS.iterator(); iter.hasNext();) {
  50. Shadow.Kind kind = (Shadow.Kind) iter.next();
  51. if (kind.neverHasThis()) thisKindSet.remove(kind);
  52. if (kind.neverHasTarget()) targetKindSet.remove(kind);
  53. }
  54. }
  55. /**
  56. *
  57. */
  58. public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type) {
  59. super();
  60. this.isThis = isThis;
  61. this.annotationTypePattern = type;
  62. }
  63. public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type, ShadowMunger munger) {
  64. this(isThis,type);
  65. this.munger = munger;
  66. }
  67. public Set couldMatchKinds() {
  68. return isThis ? thisKindSet : targetKindSet;
  69. }
  70. /* (non-Javadoc)
  71. * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
  72. */
  73. public FuzzyBoolean fastMatch(FastMatchInfo info) {
  74. return FuzzyBoolean.MAYBE;
  75. }
  76. /* (non-Javadoc)
  77. * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
  78. */
  79. protected FuzzyBoolean matchInternal(Shadow shadow) {
  80. if (!couldMatch(shadow)) return FuzzyBoolean.NO;
  81. ResolvedTypeX toMatchAgainst =
  82. (isThis ? shadow.getThisType() : shadow.getTargetType() ).resolve(shadow.getIWorld());
  83. annotationTypePattern.resolve(shadow.getIWorld());
  84. if (annotationTypePattern.matches(toMatchAgainst).alwaysTrue()) {
  85. return FuzzyBoolean.YES;
  86. } else {
  87. // a subtype may match at runtime
  88. return FuzzyBoolean.MAYBE;
  89. }
  90. }
  91. public boolean isThis() { return isThis; }
  92. /* (non-Javadoc)
  93. * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
  94. */
  95. protected void resolveBindings(IScope scope, Bindings bindings) {
  96. annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope,bindings,true);
  97. // must be either a Var, or an annotation type pattern
  98. // if annotationType does not have runtime retention, this is an error
  99. if (annotationTypePattern.annotationType == null) {
  100. // it's a formal with a binding error
  101. return;
  102. }
  103. ResolvedTypeX rAnnotationType = (ResolvedTypeX) annotationTypePattern.annotationType;
  104. if (!(rAnnotationType.isAnnotationWithRuntimeRetention())) {
  105. IMessage m = MessageUtil.error(
  106. WeaverMessages.format(WeaverMessages.BINDING_NON_RUNTIME_RETENTION_ANNOTATION,rAnnotationType.getName()),
  107. getSourceLocation());
  108. scope.getMessageHandler().handleMessage(m);
  109. }
  110. }
  111. /* (non-Javadoc)
  112. * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI()
  113. */
  114. protected void resolveBindingsFromRTTI() {
  115. // TODO Auto-generated method stub
  116. }
  117. /* (non-Javadoc)
  118. * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap)
  119. */
  120. protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
  121. if (isDeclare(bindings.getEnclosingAdvice())) {
  122. // Enforce rule about which designators are supported in declare
  123. if (!alreadyWarnedAboutDEoW) {
  124. inAspect.getWorld().showMessage(IMessage.ERROR,
  125. WeaverMessages.format(WeaverMessages.THIS_OR_TARGET_IN_DECLARE,isThis?"this":"target"),
  126. bindings.getEnclosingAdvice().getSourceLocation(), null);
  127. alreadyWarnedAboutDEoW = true;
  128. }
  129. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  130. }
  131. ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);
  132. ThisOrTargetAnnotationPointcut ret =
  133. new ThisOrTargetAnnotationPointcut(isThis, newType, bindings.getEnclosingAdvice());
  134. ret.alreadyWarnedAboutDEoW = alreadyWarnedAboutDEoW;
  135. ret.copyLocationFrom(this);
  136. return ret;
  137. }
  138. /* (non-Javadoc)
  139. * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
  140. */
  141. protected Test findResidueInternal(Shadow shadow, ExposedState state) {
  142. if (!couldMatch(shadow)) return Literal.FALSE;
  143. boolean alwaysMatches = match(shadow).alwaysTrue();
  144. Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
  145. Var annVar = null;
  146. TypeX annotationType = annotationTypePattern.annotationType;
  147. if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
  148. BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
  149. annotationType = btp.annotationType;
  150. annVar = isThis ? shadow.getThisAnnotationVar(annotationType) :
  151. shadow.getTargetAnnotationVar(annotationType);
  152. if (annVar == null) return Literal.TRUE; // should be exception when we implement properly
  153. // Check if we have already bound something to this formal
  154. if ((state.get(btp.getFormalIndex())!=null) &&(lastMatchedShadowId == shadow.shadowId)) {
  155. // ISourceLocation pcdSloc = getSourceLocation();
  156. // ISourceLocation shadowSloc = shadow.getSourceLocation();
  157. // Message errorMessage = new Message(
  158. // "Cannot use @pointcut to match at this location and bind a formal to type '"+annVar.getType()+
  159. // "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
  160. // ". The secondary source location points to the problematic binding.",
  161. // shadowSloc,true,new ISourceLocation[]{pcdSloc});
  162. // shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
  163. state.setErroneousVar(btp.getFormalIndex());
  164. }
  165. state.set(btp.getFormalIndex(),annVar);
  166. }
  167. if (alwaysMatches && (annVar == null)) {
  168. return Literal.TRUE;
  169. } else {
  170. if (annVar != null) {
  171. // TODO - need to bind it, next line is a placeholder
  172. return Literal.FALSE;
  173. } else {
  174. ResolvedTypeX rType = annotationType.resolve(shadow.getIWorld());
  175. return Test.makeHasAnnotation(var,rType);
  176. }
  177. }
  178. }
  179. private boolean couldMatch(Shadow shadow) {
  180. return isThis ? shadow.hasThis() : shadow.hasTarget();
  181. }
  182. /* (non-Javadoc)
  183. * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
  184. */
  185. public List getBindingAnnotationTypePatterns() {
  186. if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
  187. List l = new ArrayList();
  188. l.add(annotationTypePattern);
  189. return l;
  190. } else return Collections.EMPTY_LIST;
  191. }
  192. /* (non-Javadoc)
  193. * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
  194. */
  195. public List getBindingTypePatterns() {
  196. return Collections.EMPTY_LIST;
  197. }
  198. /* (non-Javadoc)
  199. * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
  200. */
  201. public void write(DataOutputStream s) throws IOException {
  202. s.writeByte(Pointcut.ATTHIS_OR_TARGET);
  203. s.writeBoolean(isThis);
  204. annotationTypePattern.write(s);
  205. writeLocation(s);
  206. }
  207. public static Pointcut read(DataInputStream s, ISourceContext context) throws IOException {
  208. boolean isThis = s.readBoolean();
  209. AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
  210. ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis,(ExactAnnotationTypePattern)type);
  211. ret.readLocation(context, s);
  212. return ret;
  213. }
  214. /* (non-Javadoc)
  215. * @see java.lang.Object#equals(java.lang.Object)
  216. */
  217. public boolean equals(Object obj) {
  218. if (!(obj instanceof ThisOrTargetAnnotationPointcut)) return false;
  219. ThisOrTargetAnnotationPointcut other = (ThisOrTargetAnnotationPointcut) obj;
  220. return ( other.annotationTypePattern.equals(this.annotationTypePattern) &&
  221. (other.isThis == this.isThis) );
  222. }
  223. /* (non-Javadoc)
  224. * @see java.lang.Object#hashCode()
  225. */
  226. public int hashCode() {
  227. return 17 + 37*annotationTypePattern.hashCode() + (isThis ? 49 : 13);
  228. }
  229. /* (non-Javadoc)
  230. * @see java.lang.Object#toString()
  231. */
  232. public String toString() {
  233. StringBuffer buf = new StringBuffer();
  234. buf.append(isThis ? "@this(" : "@target(");
  235. buf.append(annotationTypePattern.toString());
  236. buf.append(")");
  237. return buf.toString();
  238. }
  239. }