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.

DeclareAnnotation.java 15KB

15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /* *******************************************************************
  2. * Copyright (c) 2005 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 v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * Adrian Colyer initial implementation
  11. * Andy Clement got it working
  12. * ******************************************************************/
  13. package org.aspectj.weaver.patterns;
  14. import java.io.IOException;
  15. import java.util.ArrayList;
  16. import java.util.Iterator;
  17. import java.util.List;
  18. import java.util.Map;
  19. import org.aspectj.bridge.MessageUtil;
  20. import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  21. import org.aspectj.weaver.AnnotationAJ;
  22. import org.aspectj.weaver.CompressingDataOutputStream;
  23. import org.aspectj.weaver.ISourceContext;
  24. import org.aspectj.weaver.ResolvedMember;
  25. import org.aspectj.weaver.ResolvedType;
  26. import org.aspectj.weaver.UnresolvedType;
  27. import org.aspectj.weaver.VersionedDataInputStream;
  28. import org.aspectj.weaver.WeaverMessages;
  29. import org.aspectj.weaver.World;
  30. /**
  31. * Represents a declare annotation statement, one of atField, atMethod, atConstructor or atType.
  32. *
  33. * @author Andy Clement
  34. */
  35. public class DeclareAnnotation extends Declare {
  36. public static final Kind AT_TYPE = new Kind(1, "type");
  37. public static final Kind AT_FIELD = new Kind(2, "field");
  38. public static final Kind AT_METHOD = new Kind(3, "method");
  39. public static final Kind AT_CONSTRUCTOR = new Kind(4, "constructor");
  40. public static final Kind AT_REMOVE_FROM_FIELD = new Kind(5, "removeFromField");
  41. private Kind kind;
  42. // for declare @type
  43. private TypePattern typePattern;
  44. // for declare @field,@method,@constructor
  45. private ISignaturePattern signaturePattern;
  46. private ResolvedType containingAspect;
  47. private List<String> annotationMethods;
  48. private List<String> annotationStrings;
  49. private AnnotationAJ annotation; // discovered when required
  50. private ResolvedType annotationType; // discovered when required
  51. // not serialized:
  52. private int annotationStart;
  53. private int annotationEnd;
  54. /**
  55. * Constructor for declare atType.
  56. */
  57. public DeclareAnnotation(Kind kind, TypePattern typePattern) {
  58. this.typePattern = typePattern;
  59. this.kind = kind;
  60. init();
  61. }
  62. /**
  63. * Constructor for declare atMethod/atField/atConstructor.
  64. */
  65. public DeclareAnnotation(Kind kind, ISignaturePattern sigPattern) {
  66. this.signaturePattern = sigPattern;
  67. this.kind = kind;
  68. init();
  69. }
  70. private void init() {
  71. this.annotationMethods = new ArrayList<>();
  72. annotationMethods.add("unknown");
  73. this.annotationStrings = new ArrayList<>();
  74. annotationStrings.add("@<annotation>");
  75. }
  76. /**
  77. * Returns the string, useful before the real annotation has been resolved
  78. */
  79. public String getAnnotationString() {
  80. return annotationStrings.get(0);
  81. }
  82. public boolean isExactPattern() {
  83. return typePattern instanceof ExactTypePattern;
  84. }
  85. public String getAnnotationMethod() {
  86. return annotationMethods.get(0);
  87. }
  88. @Override
  89. public String toString() {
  90. StringBuilder ret = new StringBuilder();
  91. ret.append("declare @");
  92. ret.append(kind);
  93. ret.append(" : ");
  94. ret.append(typePattern != null ? typePattern.toString() : signaturePattern.toString());
  95. ret.append(" : ");
  96. ret.append(annotationStrings.get(0));
  97. return ret.toString();
  98. }
  99. @Override
  100. public Object accept(PatternNodeVisitor visitor, Object data) {
  101. return visitor.visit(this, data);
  102. }
  103. @Override
  104. public void resolve(IScope scope) {
  105. if (!scope.getWorld().isInJava5Mode()) {
  106. String msg = null;
  107. if (kind == AT_TYPE) {
  108. msg = WeaverMessages.DECLARE_ATTYPE_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
  109. } else if (kind == AT_METHOD) {
  110. msg = WeaverMessages.DECLARE_ATMETHOD_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
  111. } else if (kind == AT_FIELD) {
  112. msg = WeaverMessages.DECLARE_ATFIELD_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
  113. } else if (kind == AT_CONSTRUCTOR) {
  114. msg = WeaverMessages.DECLARE_ATCONS_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
  115. }
  116. scope.message(MessageUtil.error(WeaverMessages.format(msg), getSourceLocation()));
  117. return;
  118. }
  119. if (typePattern != null) {
  120. typePattern = typePattern.resolveBindings(scope, Bindings.NONE, false, false);
  121. }
  122. if (signaturePattern != null) {
  123. signaturePattern = signaturePattern.resolveBindings(scope, Bindings.NONE);
  124. }
  125. this.containingAspect = scope.getEnclosingType();
  126. }
  127. @Override
  128. public Declare parameterizeWith(Map<String, UnresolvedType> typeVariableBindingMap, World w) {
  129. DeclareAnnotation ret;
  130. if (this.kind == AT_TYPE) {
  131. ret = new DeclareAnnotation(kind, this.typePattern.parameterizeWith(typeVariableBindingMap, w));
  132. } else {
  133. ret = new DeclareAnnotation(kind, this.signaturePattern.parameterizeWith(typeVariableBindingMap, w));
  134. }
  135. ret.annotationMethods = this.annotationMethods;
  136. ret.annotationStrings = this.annotationStrings;
  137. ret.annotation = this.annotation;
  138. ret.containingAspect = this.containingAspect;
  139. ret.copyLocationFrom(this);
  140. return ret;
  141. }
  142. @Override
  143. public boolean isAdviceLike() {
  144. return false;
  145. }
  146. public void setAnnotationString(String annotationString) {
  147. this.annotationStrings.set(0, annotationString);
  148. }
  149. public void setAnnotationLocation(int start, int end) {
  150. this.annotationStart = start;
  151. this.annotationEnd = end;
  152. }
  153. public int getAnnotationSourceStart() {
  154. return annotationStart;
  155. }
  156. public int getAnnotationSourceEnd() {
  157. return annotationEnd;
  158. }
  159. public void setAnnotationMethod(String methodName) {
  160. this.annotationMethods.set(0, methodName);
  161. }
  162. @Override
  163. public boolean equals(Object obj) {
  164. if (!(obj instanceof DeclareAnnotation)) {
  165. return false;
  166. }
  167. DeclareAnnotation other = (DeclareAnnotation) obj;
  168. if (!this.kind.equals(other.kind)) {
  169. return false;
  170. }
  171. if (!this.annotationStrings.get(0).equals(other.annotationStrings.get(0))) {
  172. return false;
  173. }
  174. if (!this.annotationMethods.get(0).equals(other.annotationMethods.get(0))) {
  175. return false;
  176. }
  177. if (this.typePattern != null) {
  178. if (!typePattern.equals(other.typePattern)) {
  179. return false;
  180. }
  181. }
  182. if (this.signaturePattern != null) {
  183. if (!signaturePattern.equals(other.signaturePattern)) {
  184. return false;
  185. }
  186. }
  187. return true;
  188. }
  189. @Override
  190. public int hashCode() {
  191. int result = 19;
  192. result = 37 * result + kind.hashCode();
  193. result = 37 * result + annotationStrings.get(0).hashCode();
  194. result = 37 * result + annotationMethods.get(0).hashCode();
  195. if (typePattern != null) {
  196. result = 37 * result + typePattern.hashCode();
  197. }
  198. if (signaturePattern != null) {
  199. result = 37 * result + signaturePattern.hashCode();
  200. }
  201. return result;
  202. }
  203. @Override
  204. public void write(CompressingDataOutputStream s) throws IOException {
  205. s.writeByte(Declare.ANNOTATION);
  206. if (kind.id == AT_FIELD.id && isRemover) {
  207. s.writeInt(AT_REMOVE_FROM_FIELD.id);
  208. } else {
  209. s.writeInt(kind.id);
  210. }
  211. int max = 0;
  212. s.writeByte(max = annotationStrings.size());
  213. for (int i = 0; i < max; i++) {
  214. s.writeUTF(annotationStrings.get(i));
  215. }
  216. s.writeByte(max = annotationMethods.size());
  217. for (int i = 0; i < max; i++) {
  218. s.writeUTF(annotationMethods.get(i));
  219. }
  220. if (typePattern != null) {
  221. typePattern.write(s);
  222. }
  223. if (signaturePattern != null) {
  224. AbstractSignaturePattern.writeCompoundSignaturePattern(s, signaturePattern);
  225. }
  226. writeLocation(s);
  227. }
  228. public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  229. DeclareAnnotation ret = null;
  230. boolean isRemover = false;
  231. int kind = s.readInt();
  232. if (kind == AT_REMOVE_FROM_FIELD.id) {
  233. kind = AT_FIELD.id;
  234. isRemover = true;
  235. }
  236. // old format was just a single string and method
  237. if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_AJ169) {
  238. // int numAnnotationStrings =
  239. s.readByte();
  240. }
  241. String annotationString = s.readUTF();
  242. if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_AJ169) {
  243. // int numAnnotationMethods =
  244. s.readByte();
  245. }
  246. String annotationMethod = s.readUTF();
  247. TypePattern tp = null;
  248. SignaturePattern sp = null;
  249. switch (kind) {
  250. case 1:
  251. tp = TypePattern.read(s, context);
  252. ret = new DeclareAnnotation(AT_TYPE, tp);
  253. break;
  254. case 2:
  255. if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_AJ169) {
  256. ret = new DeclareAnnotation(AT_FIELD, AbstractSignaturePattern.readCompoundSignaturePattern(s, context));
  257. } else {
  258. sp = SignaturePattern.read(s, context);
  259. ret = new DeclareAnnotation(AT_FIELD, sp);
  260. }
  261. if (isRemover) {
  262. ret.setRemover(true);
  263. }
  264. break;
  265. case 3:
  266. if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_AJ169) {
  267. ret = new DeclareAnnotation(AT_METHOD, AbstractSignaturePattern.readCompoundSignaturePattern(s, context));
  268. } else {
  269. sp = SignaturePattern.read(s, context);
  270. ret = new DeclareAnnotation(AT_METHOD, sp);
  271. }
  272. break;
  273. case 4:
  274. if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_AJ169) {
  275. ret = new DeclareAnnotation(AT_CONSTRUCTOR, AbstractSignaturePattern.readCompoundSignaturePattern(s, context));
  276. } else {
  277. sp = SignaturePattern.read(s, context);
  278. ret = new DeclareAnnotation(AT_CONSTRUCTOR, sp);
  279. }
  280. break;
  281. }
  282. ret.setAnnotationString(annotationString);
  283. ret.setAnnotationMethod(annotationMethod);
  284. ret.readLocation(context, s);
  285. return ret;
  286. }
  287. /**
  288. * For declare atConstructor, atMethod, atField
  289. */
  290. public boolean matches(ResolvedMember resolvedmember, World world) {
  291. if (kind == AT_METHOD || kind == AT_CONSTRUCTOR) {
  292. if (resolvedmember != null && resolvedmember.getName().charAt(0) == '<') {
  293. // <clinit> or <init>
  294. if (kind == AT_METHOD) {
  295. return false;
  296. }
  297. }
  298. }
  299. return signaturePattern.matches(resolvedmember, world, false);
  300. }
  301. /**
  302. * For declare atType.
  303. */
  304. public boolean matches(ResolvedType type) {
  305. if (!typePattern.matchesStatically(type)) {
  306. return false;
  307. }
  308. if (type.getWorld().getLint().typeNotExposedToWeaver.isEnabled() && !type.isExposedToWeaver()) {
  309. type.getWorld().getLint().typeNotExposedToWeaver.signal(type.getName(), getSourceLocation());
  310. }
  311. return true;
  312. }
  313. public void setAspect(ResolvedType typeX) {
  314. containingAspect = typeX;
  315. }
  316. public UnresolvedType getAspect() {
  317. return containingAspect;
  318. }
  319. public void copyAnnotationTo(ResolvedType onType) {
  320. ensureAnnotationDiscovered();
  321. if (!onType.hasAnnotation(annotation.getType())) {
  322. onType.addAnnotation(annotation);
  323. }
  324. }
  325. public AnnotationAJ getAnnotation() {
  326. ensureAnnotationDiscovered();
  327. return annotation;
  328. }
  329. /**
  330. * The annotation specified in the declare @type is stored against a simple method of the form "ajc$declare_<NN>", this method
  331. * finds that method and retrieves the annotation
  332. */
  333. private void ensureAnnotationDiscovered() {
  334. if (annotation != null) {
  335. return;
  336. }
  337. String annotationMethod = annotationMethods.get(0);
  338. for (Iterator<ResolvedMember> iter = containingAspect.getMethods(true, true); iter.hasNext();) {
  339. ResolvedMember member = iter.next();
  340. if (member.getName().equals(annotationMethod)) {
  341. AnnotationAJ[] annos = member.getAnnotations();
  342. if (annos == null) {
  343. // if weaving broken code, this can happen
  344. return;
  345. }
  346. int idx = 0;
  347. if (annos.length > 0
  348. && annos[0].getType().getSignature().equals("Lorg/aspectj/internal/lang/annotation/ajcDeclareAnnotation;")) {
  349. if (annos.length < 2)
  350. continue;
  351. idx = 1;
  352. }
  353. annotation = annos[idx];
  354. break;
  355. }
  356. }
  357. }
  358. public TypePattern getTypePattern() {
  359. return typePattern;
  360. }
  361. public ISignaturePattern getSignaturePattern() {
  362. return signaturePattern;
  363. }
  364. public boolean isStarredAnnotationPattern() {
  365. if (typePattern != null) {
  366. return typePattern.isStarAnnotation();
  367. } else {
  368. return signaturePattern.isStarAnnotation();
  369. }
  370. }
  371. public Kind getKind() {
  372. return kind;
  373. }
  374. public boolean isDeclareAtConstuctor() {
  375. return kind.equals(AT_CONSTRUCTOR);
  376. }
  377. public boolean isDeclareAtMethod() {
  378. return kind.equals(AT_METHOD);
  379. }
  380. public boolean isDeclareAtType() {
  381. return kind.equals(AT_TYPE);
  382. }
  383. public boolean isDeclareAtField() {
  384. return kind.equals(AT_FIELD);
  385. }
  386. /**
  387. * @return the type of the annotation
  388. */
  389. public ResolvedType getAnnotationType() {
  390. if (annotationType == null) {
  391. String annotationMethod = annotationMethods.get(0);
  392. for (Iterator<ResolvedMember> iter = containingAspect.getMethods(true, true); iter.hasNext();) {
  393. ResolvedMember member = iter.next();
  394. if (member.getName().equals(annotationMethod)) {
  395. ResolvedType[] annoTypes = member.getAnnotationTypes();
  396. if (annoTypes == null) {
  397. // if weaving broken code, this can happen
  398. return null;
  399. }
  400. int idx = 0;
  401. if (annoTypes[0].getSignature().equals("Lorg/aspectj/internal/lang/annotation/ajcDeclareAnnotation;")) {
  402. idx = 1;
  403. if (annoTypes.length < 2)
  404. continue;
  405. }
  406. annotationType = annoTypes[idx];
  407. break;
  408. }
  409. }
  410. }
  411. return annotationType;
  412. }
  413. /**
  414. * @return true if the annotation specified is allowed on a field
  415. */
  416. public boolean isAnnotationAllowedOnField() {
  417. ensureAnnotationDiscovered();
  418. return annotation.allowedOnField();
  419. }
  420. public String getPatternAsString() {
  421. if (signaturePattern != null) {
  422. return signaturePattern.toString();
  423. }
  424. if (typePattern != null) {
  425. return typePattern.toString();
  426. }
  427. return "DONT KNOW";
  428. }
  429. /**
  430. * Return true if this declare annotation could ever match something in the specified type - only really able to make
  431. * intelligent decision if a type was specified in the sig/type pattern signature.
  432. */
  433. public boolean couldEverMatch(ResolvedType type) {
  434. // Haven't implemented variant for typePattern (doesn't seem worth it!)
  435. // BUGWARNING This test might not be sufficient for funny cases relating
  436. // to interfaces and the use of '+' - but it seems really important to
  437. // do something here so we don't iterate over all fields and all methods
  438. // in all types exposed to the weaver! So look out for bugs here and
  439. // we can update the test as appropriate.
  440. if (signaturePattern != null) {
  441. return signaturePattern.couldEverMatch(type);
  442. }
  443. return true;
  444. }
  445. /**
  446. * Provide a name suffix so that we can tell the different declare annotations forms apart in the AjProblemReporter
  447. */
  448. @Override
  449. public String getNameSuffix() {
  450. return getKind().toString();
  451. }
  452. /**
  453. * Captures type of declare annotation (method/type/field/constructor)
  454. */
  455. public static class Kind {
  456. private final int id;
  457. private String s;
  458. private Kind(int n, String name) {
  459. id = n;
  460. s = name;
  461. }
  462. @Override
  463. public int hashCode() {
  464. return (19 + 37 * id);
  465. }
  466. @Override
  467. public boolean equals(Object obj) {
  468. if (!(obj instanceof Kind)) {
  469. return false;
  470. }
  471. Kind other = (Kind) obj;
  472. return other.id == id;
  473. }
  474. @Override
  475. public String toString() {
  476. return "at_" + s;
  477. }
  478. }
  479. boolean isRemover = false;
  480. public void setRemover(boolean b) {
  481. isRemover = b;
  482. }
  483. public boolean isRemover() {
  484. return isRemover;
  485. }
  486. }