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 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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.patterns;
  11. import java.io.IOException;
  12. import java.util.ArrayList;
  13. import java.util.Collections;
  14. import java.util.List;
  15. import java.util.Map;
  16. import org.aspectj.bridge.IMessage;
  17. import org.aspectj.bridge.MessageUtil;
  18. import org.aspectj.util.FuzzyBoolean;
  19. import org.aspectj.weaver.CompressingDataOutputStream;
  20. import org.aspectj.weaver.ISourceContext;
  21. import org.aspectj.weaver.IntMap;
  22. import org.aspectj.weaver.ResolvedType;
  23. import org.aspectj.weaver.Shadow;
  24. import org.aspectj.weaver.ShadowMunger;
  25. import org.aspectj.weaver.UnresolvedType;
  26. import org.aspectj.weaver.VersionedDataInputStream;
  27. import org.aspectj.weaver.WeaverMessages;
  28. import org.aspectj.weaver.World;
  29. import org.aspectj.weaver.ast.Literal;
  30. import org.aspectj.weaver.ast.Test;
  31. import org.aspectj.weaver.ast.Var;
  32. /**
  33. * @author colyer
  34. *
  35. * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code
  36. * Templates
  37. */
  38. public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
  39. private boolean isThis;
  40. private boolean alreadyWarnedAboutDEoW = false;
  41. private ExactAnnotationTypePattern annotationTypePattern;
  42. private String declarationText;
  43. private static final int thisKindSet;
  44. private static final int targetKindSet;
  45. static {
  46. int thisFlags = Shadow.ALL_SHADOW_KINDS_BITS;
  47. int targFlags = Shadow.ALL_SHADOW_KINDS_BITS;
  48. for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
  49. Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
  50. if (kind.neverHasThis()) {
  51. thisFlags -= kind.bit;
  52. }
  53. if (kind.neverHasTarget()) {
  54. targFlags -= kind.bit;
  55. }
  56. }
  57. thisKindSet = thisFlags;
  58. targetKindSet = targFlags;
  59. }
  60. /**
  61. *
  62. */
  63. public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type) {
  64. super();
  65. this.isThis = isThis;
  66. this.annotationTypePattern = type;
  67. this.pointcutKind = ATTHIS_OR_TARGET;
  68. buildDeclarationText();
  69. }
  70. public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type, ShadowMunger munger) {
  71. this(isThis, type);
  72. }
  73. public ExactAnnotationTypePattern getAnnotationTypePattern() {
  74. return annotationTypePattern;
  75. }
  76. @Override
  77. public int couldMatchKinds() {
  78. return isThis ? thisKindSet : targetKindSet;
  79. }
  80. @Override
  81. public Pointcut parameterizeWith(Map<String,UnresolvedType> typeVariableMap, World w) {
  82. ExactAnnotationTypePattern newPattern = (ExactAnnotationTypePattern) this.annotationTypePattern.parameterizeWith(
  83. typeVariableMap, w);
  84. if (newPattern.getAnnotationType() instanceof ResolvedType) {
  85. verifyRuntimeRetention(newPattern.getResolvedAnnotationType());
  86. }
  87. ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis,
  88. (ExactAnnotationTypePattern) annotationTypePattern.parameterizeWith(typeVariableMap, w));
  89. ret.copyLocationFrom(this);
  90. return ret;
  91. }
  92. /*
  93. * (non-Javadoc)
  94. *
  95. * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
  96. */
  97. @Override
  98. public FuzzyBoolean fastMatch(FastMatchInfo info) {
  99. return FuzzyBoolean.MAYBE;
  100. }
  101. /*
  102. * (non-Javadoc)
  103. *
  104. * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
  105. */
  106. @Override
  107. protected FuzzyBoolean matchInternal(Shadow shadow) {
  108. if (!couldMatch(shadow)) {
  109. return FuzzyBoolean.NO;
  110. }
  111. ResolvedType toMatchAgainst = (isThis ? shadow.getThisType() : shadow.getTargetType()).resolve(shadow.getIWorld());
  112. annotationTypePattern.resolve(shadow.getIWorld());
  113. if (annotationTypePattern.matchesRuntimeType(toMatchAgainst).alwaysTrue()) {
  114. return FuzzyBoolean.YES;
  115. } else {
  116. // a subtype may match at runtime
  117. return FuzzyBoolean.MAYBE;
  118. }
  119. }
  120. public boolean isThis() {
  121. return isThis;
  122. }
  123. /*
  124. * (non-Javadoc)
  125. *
  126. * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope,
  127. * org.aspectj.weaver.patterns.Bindings)
  128. */
  129. @Override
  130. protected void resolveBindings(IScope scope, Bindings bindings) {
  131. if (!scope.getWorld().isInJava5Mode()) {
  132. scope.message(MessageUtil.error(WeaverMessages.format(isThis ? WeaverMessages.ATTHIS_ONLY_SUPPORTED_AT_JAVA5_LEVEL
  133. : WeaverMessages.ATTARGET_ONLY_SUPPORTED_AT_JAVA5_LEVEL), getSourceLocation()));
  134. return;
  135. }
  136. annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope, bindings, true);
  137. // must be either a Var, or an annotation type pattern
  138. // if annotationType does not have runtime retention, this is an error
  139. if (annotationTypePattern.annotationType == null) {
  140. // it's a formal with a binding error
  141. return;
  142. }
  143. ResolvedType rAnnotationType = (ResolvedType) annotationTypePattern.annotationType;
  144. if (rAnnotationType.isTypeVariableReference()) {
  145. return; // we'll deal with this next check when the type var is actually bound...
  146. }
  147. verifyRuntimeRetention(rAnnotationType);
  148. }
  149. private void verifyRuntimeRetention(ResolvedType rAnnotationType) {
  150. if (!(rAnnotationType.isAnnotationWithRuntimeRetention())) {
  151. IMessage m = MessageUtil.error(WeaverMessages.format(WeaverMessages.BINDING_NON_RUNTIME_RETENTION_ANNOTATION,
  152. rAnnotationType.getName()), getSourceLocation());
  153. rAnnotationType.getWorld().getMessageHandler().handleMessage(m);
  154. }
  155. }
  156. /*
  157. * (non-Javadoc)
  158. *
  159. * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
  160. */
  161. @Override
  162. protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
  163. if (isDeclare(bindings.getEnclosingAdvice())) {
  164. // Enforce rule about which designators are supported in declare
  165. if (!alreadyWarnedAboutDEoW) {
  166. inAspect.getWorld().showMessage(IMessage.ERROR,
  167. WeaverMessages.format(WeaverMessages.THIS_OR_TARGET_IN_DECLARE, isThis ? "this" : "target"),
  168. bindings.getEnclosingAdvice().getSourceLocation(), null);
  169. alreadyWarnedAboutDEoW = true;
  170. }
  171. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  172. }
  173. ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);
  174. ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis, newType, bindings.getEnclosingAdvice());
  175. ret.alreadyWarnedAboutDEoW = alreadyWarnedAboutDEoW;
  176. ret.copyLocationFrom(this);
  177. return ret;
  178. }
  179. /*
  180. * (non-Javadoc)
  181. *
  182. * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
  183. */
  184. /**
  185. * The guard here is going to be the hasAnnotation() test - if it gets through (which we cannot determine until runtime) then we
  186. * must have a TypeAnnotationAccessVar in place - this means we must *always* have one in place.
  187. */
  188. @Override
  189. protected Test findResidueInternal(Shadow shadow, ExposedState state) {
  190. if (!couldMatch(shadow)) {
  191. return Literal.FALSE;
  192. }
  193. boolean alwaysMatches = match(shadow).alwaysTrue();
  194. Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
  195. Var annVar = null;
  196. // Are annotations being bound?
  197. UnresolvedType annotationType = annotationTypePattern.annotationType;
  198. if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
  199. BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern) annotationTypePattern;
  200. annotationType = btp.annotationType;
  201. annVar = isThis ? shadow.getThisAnnotationVar(annotationType) : shadow.getTargetAnnotationVar(annotationType);
  202. if (annVar == null) {
  203. throw new RuntimeException("Impossible!");
  204. }
  205. state.set(btp.getFormalIndex(), annVar);
  206. }
  207. if (alwaysMatches && (annVar == null)) {// change check to verify if its the 'generic' annVar that is being used
  208. return Literal.TRUE;
  209. } else {
  210. ResolvedType rType = annotationType.resolve(shadow.getIWorld());
  211. return Test.makeHasAnnotation(var, rType);
  212. }
  213. }
  214. private boolean couldMatch(Shadow shadow) {
  215. return isThis ? shadow.hasThis() : shadow.hasTarget();
  216. }
  217. /*
  218. * (non-Javadoc)
  219. *
  220. * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
  221. */
  222. @Override
  223. public List<BindingPattern> getBindingAnnotationTypePatterns() {
  224. if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
  225. List<BindingPattern> l = new ArrayList<BindingPattern>();
  226. l.add((BindingPattern)annotationTypePattern);
  227. return l;
  228. } else {
  229. return Collections.emptyList();
  230. }
  231. }
  232. /*
  233. * (non-Javadoc)
  234. *
  235. * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
  236. */
  237. @Override
  238. public List<BindingTypePattern> getBindingTypePatterns() {
  239. return Collections.emptyList();
  240. }
  241. /*
  242. * (non-Javadoc)
  243. *
  244. * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
  245. */
  246. @Override
  247. public void write(CompressingDataOutputStream s) throws IOException {
  248. s.writeByte(Pointcut.ATTHIS_OR_TARGET);
  249. s.writeBoolean(isThis);
  250. annotationTypePattern.write(s);
  251. writeLocation(s);
  252. }
  253. public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  254. boolean isThis = s.readBoolean();
  255. AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
  256. ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis, (ExactAnnotationTypePattern) type);
  257. ret.readLocation(context, s);
  258. return ret;
  259. }
  260. /*
  261. * (non-Javadoc)
  262. *
  263. * @see java.lang.Object#equals(java.lang.Object)
  264. */
  265. @Override
  266. public boolean equals(Object obj) {
  267. if (!(obj instanceof ThisOrTargetAnnotationPointcut)) {
  268. return false;
  269. }
  270. ThisOrTargetAnnotationPointcut other = (ThisOrTargetAnnotationPointcut) obj;
  271. return (other.annotationTypePattern.equals(this.annotationTypePattern) && (other.isThis == this.isThis));
  272. }
  273. /*
  274. * (non-Javadoc)
  275. *
  276. * @see java.lang.Object#hashCode()
  277. */
  278. @Override
  279. public int hashCode() {
  280. return 17 + 37 * annotationTypePattern.hashCode() + (isThis ? 49 : 13);
  281. }
  282. /*
  283. * (non-Javadoc)
  284. *
  285. * @see java.lang.Object#toString()
  286. */
  287. private void buildDeclarationText() {
  288. StringBuffer buf = new StringBuffer();
  289. buf.append(isThis ? "@this(" : "@target(");
  290. String annPatt = annotationTypePattern.toString();
  291. buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt);
  292. buf.append(")");
  293. this.declarationText = buf.toString();
  294. }
  295. @Override
  296. public String toString() {
  297. return this.declarationText;
  298. }
  299. @Override
  300. public Object accept(PatternNodeVisitor visitor, Object data) {
  301. return visitor.visit(this, data);
  302. }
  303. }