Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

TypePattern.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  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. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.io.DataOutputStream;
  14. import java.io.IOException;
  15. import java.util.Iterator;
  16. import org.aspectj.bridge.MessageUtil;
  17. import org.aspectj.util.FuzzyBoolean;
  18. import org.aspectj.weaver.BCException;
  19. import org.aspectj.weaver.ISourceContext;
  20. import org.aspectj.weaver.IntMap;
  21. import org.aspectj.weaver.ResolvedTypeX;
  22. import org.aspectj.weaver.TypeX;
  23. import org.aspectj.weaver.VersionedDataInputStream;
  24. import org.aspectj.weaver.WeaverMessages;
  25. import org.aspectj.weaver.World;
  26. /**
  27. * On creation, type pattern only contains WildTypePattern nodes, not BindingType or ExactType.
  28. *
  29. * <p>Then we call resolveBindings() during compilation
  30. * During concretization of enclosing pointcuts, we call remapAdviceFormals
  31. *
  32. * @author Erik Hilsdale
  33. * @author Jim Hugunin
  34. */
  35. public abstract class TypePattern extends PatternNode {
  36. public static class MatchKind {
  37. private String name;
  38. public MatchKind(String name) { this.name = name; }
  39. public String toString() { return name; }
  40. }
  41. public static final MatchKind STATIC = new MatchKind("STATIC");
  42. public static final MatchKind DYNAMIC = new MatchKind("DYNAMIC");
  43. public static final TypePattern ELLIPSIS = new EllipsisTypePattern();
  44. public static final TypePattern ANY = new AnyTypePattern();
  45. public static final TypePattern NO = new NoTypePattern();
  46. protected boolean includeSubtypes;
  47. protected boolean isVarArgs = false;
  48. protected AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY;
  49. protected TypePattern(boolean includeSubtypes,boolean isVarArgs) {
  50. this.includeSubtypes = includeSubtypes;
  51. this.isVarArgs = isVarArgs;
  52. }
  53. protected TypePattern(boolean includeSubtypes) {
  54. this(includeSubtypes,false);
  55. }
  56. public void setAnnotationTypePattern(AnnotationTypePattern annPatt) {
  57. this.annotationPattern = annPatt;
  58. }
  59. // answer conservatively...
  60. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  61. if (this.includeSubtypes || other.includeSubtypes) return true;
  62. if (this.annotationPattern != AnnotationTypePattern.ANY) return true;
  63. if (other.annotationPattern != AnnotationTypePattern.ANY) return true;
  64. return false;
  65. }
  66. //XXX non-final for Not, && and ||
  67. public boolean matchesStatically(ResolvedTypeX type) {
  68. if (includeSubtypes) {
  69. return matchesSubtypes(type);
  70. } else {
  71. return matchesExactly(type);
  72. }
  73. }
  74. public abstract FuzzyBoolean matchesInstanceof(ResolvedTypeX type);
  75. public final FuzzyBoolean matches(ResolvedTypeX type, MatchKind kind) {
  76. FuzzyBoolean typeMatch = null;
  77. //??? This is part of gracefully handling missing references
  78. if (type == ResolvedTypeX.MISSING) return FuzzyBoolean.NO;
  79. if (kind == STATIC) {
  80. // typeMatch = FuzzyBoolean.fromBoolean(matchesStatically(type));
  81. // return typeMatch.and(annotationPattern.matches(type));
  82. return FuzzyBoolean.fromBoolean(matchesStatically(type));
  83. } else if (kind == DYNAMIC) {
  84. //System.err.println("matching: " + this + " with " + type);
  85. // typeMatch = matchesInstanceof(type);
  86. //System.err.println(" got: " + ret);
  87. // return typeMatch.and(annotationPattern.matches(type));
  88. return matchesInstanceof(type);
  89. } else {
  90. throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
  91. }
  92. }
  93. // methods for dynamic pc matching...
  94. public final FuzzyBoolean matches(Class toMatch, MatchKind kind) {
  95. if (kind == STATIC) {
  96. return FuzzyBoolean.fromBoolean(matchesStatically(toMatch));
  97. } else if (kind == DYNAMIC) {
  98. //System.err.println("matching: " + this + " with " + type);
  99. FuzzyBoolean ret = matchesInstanceof(toMatch);
  100. //System.err.println(" got: " + ret);
  101. return ret;
  102. } else {
  103. throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
  104. }
  105. }
  106. /**
  107. * This variant is only called by the args and handler pcds when doing runtime
  108. * matching. We need to handle primitive types correctly in this case (an Integer
  109. * should match an int,...).
  110. */
  111. public final FuzzyBoolean matches(Object o, MatchKind kind) {
  112. if (kind == STATIC) { // handler pcd
  113. return FuzzyBoolean.fromBoolean(matchesStatically(o.getClass()));
  114. } else if (kind == DYNAMIC) { // args pcd
  115. // Class clazz = o.getClass();
  116. // FuzzyBoolean ret = FuzzyBoolean.fromBoolean(matchesSubtypes(clazz));
  117. // if (ret == FuzzyBoolean.NO) {
  118. // // try primitive type instead
  119. // if (clazz == Integer.class) ret = FuzzyBoolean.fromBoolean(matchesExactly(int.class));
  120. // }
  121. // return ret;
  122. return matchesInstanceof(o.getClass());
  123. } else {
  124. throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
  125. }
  126. }
  127. public boolean matchesStatically(Class toMatch) {
  128. if (includeSubtypes) {
  129. return matchesSubtypes(toMatch);
  130. } else {
  131. return matchesExactly(toMatch);
  132. }
  133. }
  134. public abstract FuzzyBoolean matchesInstanceof(Class toMatch);
  135. protected abstract boolean matchesExactly(Class toMatch);
  136. protected boolean matchesSubtypes(Class toMatch) {
  137. if (matchesExactly(toMatch)) {
  138. return true;
  139. }
  140. Class superClass = toMatch.getSuperclass();
  141. if (superClass != null) {
  142. return matchesSubtypes(superClass);
  143. }
  144. return false;
  145. }
  146. protected abstract boolean matchesExactly(ResolvedTypeX type);
  147. protected boolean matchesSubtypes(ResolvedTypeX type) {
  148. //System.out.println("matching: " + this + " to " + type);
  149. if (matchesExactly(type)) {
  150. //System.out.println(" true");
  151. return true;
  152. }
  153. // FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
  154. for (Iterator i = type.getDirectSupertypes(); i.hasNext(); ) {
  155. ResolvedTypeX superType = (ResolvedTypeX)i.next();
  156. if (matchesSubtypes(superType)) return true;
  157. }
  158. return false;
  159. }
  160. public TypeX resolveExactType(IScope scope, Bindings bindings) {
  161. TypePattern p = resolveBindings(scope, bindings, false, true);
  162. if (p == NO) return ResolvedTypeX.MISSING;
  163. return ((ExactTypePattern)p).getType();
  164. }
  165. public TypeX getExactType() {
  166. if (this instanceof ExactTypePattern) return ((ExactTypePattern)this).getType();
  167. else return ResolvedTypeX.MISSING;
  168. }
  169. protected TypePattern notExactType(IScope s) {
  170. s.getMessageHandler().handleMessage(MessageUtil.error(
  171. WeaverMessages.format(WeaverMessages.EXACT_TYPE_PATTERN_REQD), getSourceLocation()));
  172. return NO;
  173. }
  174. // public boolean assertExactType(IMessageHandler m) {
  175. // if (this instanceof ExactTypePattern) return true;
  176. //
  177. // //XXX should try harder to avoid multiple errors for one problem
  178. // m.handleMessage(MessageUtil.error("exact type pattern required", getSourceLocation()));
  179. // return false;
  180. // }
  181. /**
  182. * This can modify in place, or return a new TypePattern if the type changes.
  183. */
  184. public TypePattern resolveBindings(IScope scope, Bindings bindings,
  185. boolean allowBinding, boolean requireExactType)
  186. {
  187. annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
  188. return this;
  189. }
  190. public TypePattern resolveBindingsFromRTTI(boolean allowBindng, boolean requireExactType) {
  191. return this;
  192. }
  193. public void resolve(World world) {
  194. annotationPattern.resolve(world);
  195. }
  196. public void postRead(ResolvedTypeX enclosingType) {
  197. }
  198. public boolean isStar() {
  199. return false;
  200. }
  201. /**
  202. * This is called during concretization of pointcuts, it is used by BindingTypePattern
  203. * to return a new BindingTypePattern with a formal index appropiate for the advice,
  204. * rather than for the lexical declaration, i.e. this handles transforamtions through
  205. * named pointcuts.
  206. * <pre>
  207. * pointcut foo(String name): args(name);
  208. * --&gt; This makes a BindingTypePattern(0) pointing to the 0th formal
  209. *
  210. * before(Foo f, String n): this(f) && foo(n) { ... }
  211. * --&gt; when resolveReferences is called on the args from the above, it
  212. * will return a BindingTypePattern(1)
  213. *
  214. * before(Foo f): this(f) && foo(*) { ... }
  215. * --&gt; when resolveReferences is called on the args from the above, it
  216. * will return an ExactTypePattern(String)
  217. * </pre>
  218. */
  219. public TypePattern remapAdviceFormals(IntMap bindings) {
  220. return this;
  221. }
  222. public static final byte WILD = 1;
  223. public static final byte EXACT = 2;
  224. public static final byte BINDING = 3;
  225. public static final byte ELLIPSIS_KEY = 4;
  226. public static final byte ANY_KEY = 5;
  227. public static final byte NOT = 6;
  228. public static final byte OR = 7;
  229. public static final byte AND = 8;
  230. public static final byte NO_KEY = 9;
  231. public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  232. byte key = s.readByte();
  233. switch(key) {
  234. case WILD: return WildTypePattern.read(s, context);
  235. case EXACT: return ExactTypePattern.read(s, context);
  236. case BINDING: return BindingTypePattern.read(s, context);
  237. case ELLIPSIS_KEY: return ELLIPSIS;
  238. case ANY_KEY: return ANY;
  239. case NO_KEY: return NO;
  240. case NOT: return NotTypePattern.read(s, context);
  241. case OR: return OrTypePattern.read(s, context);
  242. case AND: return AndTypePattern.read(s, context);
  243. }
  244. throw new BCException("unknown TypePattern kind: " + key);
  245. }
  246. public boolean isIncludeSubtypes() {
  247. return includeSubtypes;
  248. }
  249. }
  250. class EllipsisTypePattern extends TypePattern {
  251. /**
  252. * Constructor for EllipsisTypePattern.
  253. * @param includeSubtypes
  254. */
  255. public EllipsisTypePattern() {
  256. super(false,false);
  257. }
  258. /* (non-Javadoc)
  259. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  260. */
  261. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  262. return true;
  263. }
  264. /**
  265. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  266. */
  267. protected boolean matchesExactly(ResolvedTypeX type) {
  268. return false;
  269. }
  270. /**
  271. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  272. */
  273. public FuzzyBoolean matchesInstanceof(ResolvedTypeX type) {
  274. return FuzzyBoolean.NO;
  275. }
  276. /**
  277. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  278. */
  279. protected boolean matchesExactly(Class type) {
  280. return false;
  281. }
  282. /**
  283. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  284. */
  285. public FuzzyBoolean matchesInstanceof(Class type) {
  286. return FuzzyBoolean.NO;
  287. }
  288. /**
  289. * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
  290. */
  291. public void write(DataOutputStream s) throws IOException {
  292. s.writeByte(ELLIPSIS_KEY);
  293. }
  294. public String toString() { return ".."; }
  295. /* (non-Javadoc)
  296. * @see java.lang.Object#equals(java.lang.Object)
  297. */
  298. public boolean equals(Object obj) {
  299. return (obj instanceof EllipsisTypePattern);
  300. }
  301. /* (non-Javadoc)
  302. * @see java.lang.Object#hashCode()
  303. */
  304. public int hashCode() {
  305. return 17 * 37;
  306. }
  307. }
  308. class AnyTypePattern extends TypePattern {
  309. /**
  310. * Constructor for EllipsisTypePattern.
  311. * @param includeSubtypes
  312. */
  313. public AnyTypePattern() {
  314. super(false,false);
  315. }
  316. /* (non-Javadoc)
  317. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  318. */
  319. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  320. return true;
  321. }
  322. /**
  323. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  324. */
  325. protected boolean matchesExactly(ResolvedTypeX type) {
  326. return true;
  327. }
  328. /**
  329. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  330. */
  331. public FuzzyBoolean matchesInstanceof(ResolvedTypeX type) {
  332. return FuzzyBoolean.YES;
  333. }
  334. /**
  335. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  336. */
  337. protected boolean matchesExactly(Class type) {
  338. return true;
  339. }
  340. /**
  341. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  342. */
  343. public FuzzyBoolean matchesInstanceof(Class type) {
  344. return FuzzyBoolean.YES;
  345. }
  346. /**
  347. * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
  348. */
  349. public void write(DataOutputStream s) throws IOException {
  350. s.writeByte(ANY_KEY);
  351. }
  352. /**
  353. * @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
  354. */
  355. // public FuzzyBoolean matches(IType type, MatchKind kind) {
  356. // return FuzzyBoolean.YES;
  357. // }
  358. /**
  359. * @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
  360. */
  361. protected boolean matchesSubtypes(ResolvedTypeX type) {
  362. return true;
  363. }
  364. public boolean isStar() {
  365. return true;
  366. }
  367. public String toString() { return "*"; }
  368. public boolean equals(Object obj) {
  369. return (obj instanceof AnyTypePattern);
  370. }
  371. public int hashCode() {
  372. return 37;
  373. }
  374. }
  375. class NoTypePattern extends TypePattern {
  376. public NoTypePattern() {
  377. super(false,false);
  378. }
  379. /* (non-Javadoc)
  380. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  381. */
  382. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  383. return false;
  384. }
  385. /**
  386. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  387. */
  388. protected boolean matchesExactly(ResolvedTypeX type) {
  389. return false;
  390. }
  391. /**
  392. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  393. */
  394. public FuzzyBoolean matchesInstanceof(ResolvedTypeX type) {
  395. return FuzzyBoolean.NO;
  396. }
  397. /**
  398. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  399. */
  400. protected boolean matchesExactly(Class type) {
  401. return false;
  402. }
  403. /**
  404. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  405. */
  406. public FuzzyBoolean matchesInstanceof(Class type) {
  407. return FuzzyBoolean.NO;
  408. }
  409. /**
  410. * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
  411. */
  412. public void write(DataOutputStream s) throws IOException {
  413. s.writeByte(NO_KEY);
  414. }
  415. /**
  416. * @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
  417. */
  418. // public FuzzyBoolean matches(IType type, MatchKind kind) {
  419. // return FuzzyBoolean.YES;
  420. // }
  421. /**
  422. * @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
  423. */
  424. protected boolean matchesSubtypes(ResolvedTypeX type) {
  425. return false;
  426. }
  427. public boolean isStar() {
  428. return false;
  429. }
  430. public String toString() { return "<nothing>"; }
  431. /* (non-Javadoc)
  432. * @see java.lang.Object#equals(java.lang.Object)
  433. */
  434. public boolean equals(Object obj) {
  435. return (obj instanceof NoTypePattern);
  436. }
  437. /* (non-Javadoc)
  438. * @see java.lang.Object#hashCode()
  439. */
  440. public int hashCode() {
  441. return 17 * 37 * 37;
  442. }
  443. }