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.6KB

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