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.

SignaturePattern.java 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  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 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. * 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.lang.reflect.Field;
  16. import java.util.ArrayList;
  17. import java.util.Collection;
  18. import java.util.HashMap;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.Set;
  23. import org.aspectj.bridge.ISourceLocation;
  24. import org.aspectj.bridge.MessageUtil;
  25. import org.aspectj.lang.Signature;
  26. import org.aspectj.lang.reflect.FieldSignature;
  27. import org.aspectj.lang.reflect.MethodSignature;
  28. import org.aspectj.util.FuzzyBoolean;
  29. import org.aspectj.weaver.AjAttribute;
  30. import org.aspectj.weaver.AjcMemberMaker;
  31. import org.aspectj.weaver.AnnotationTargetKind;
  32. import org.aspectj.weaver.Constants;
  33. import org.aspectj.weaver.ISourceContext;
  34. import org.aspectj.weaver.JoinPointSignature;
  35. import org.aspectj.weaver.Member;
  36. import org.aspectj.weaver.NameMangler;
  37. import org.aspectj.weaver.NewFieldTypeMunger;
  38. import org.aspectj.weaver.ResolvedMember;
  39. import org.aspectj.weaver.ResolvedType;
  40. import org.aspectj.weaver.UnresolvedType;
  41. import org.aspectj.weaver.VersionedDataInputStream;
  42. import org.aspectj.weaver.World;
  43. import org.aspectj.weaver.bcel.BcelTypeMunger;
  44. public class SignaturePattern extends PatternNode {
  45. private Member.Kind kind;
  46. private ModifiersPattern modifiers;
  47. private TypePattern returnType;
  48. private TypePattern declaringType;
  49. private NamePattern name;
  50. private TypePatternList parameterTypes;
  51. private ThrowsPattern throwsPattern;
  52. private AnnotationTypePattern annotationPattern;
  53. private transient int hashcode = -1;
  54. public SignaturePattern(Member.Kind kind, ModifiersPattern modifiers,
  55. TypePattern returnType, TypePattern declaringType,
  56. NamePattern name, TypePatternList parameterTypes,
  57. ThrowsPattern throwsPattern,
  58. AnnotationTypePattern annotationPattern) {
  59. this.kind = kind;
  60. this.modifiers = modifiers;
  61. this.returnType = returnType;
  62. this.name = name;
  63. this.declaringType = declaringType;
  64. this.parameterTypes = parameterTypes;
  65. this.throwsPattern = throwsPattern;
  66. this.annotationPattern = annotationPattern;
  67. }
  68. public SignaturePattern resolveBindings(IScope scope, Bindings bindings) {
  69. if (returnType != null) {
  70. returnType = returnType.resolveBindings(scope, bindings, false, false);
  71. checkForIncorrectTargetKind(returnType,scope,false);
  72. }
  73. if (declaringType != null) {
  74. declaringType = declaringType.resolveBindings(scope, bindings, false, false);
  75. checkForIncorrectTargetKind(declaringType,scope,false);
  76. }
  77. if (parameterTypes != null) {
  78. parameterTypes = parameterTypes.resolveBindings(scope, bindings, false, false);
  79. checkForIncorrectTargetKind(parameterTypes,scope,false);
  80. }
  81. if (throwsPattern != null) {
  82. throwsPattern = throwsPattern.resolveBindings(scope, bindings);
  83. if (throwsPattern.getForbidden().getTypePatterns().length > 0
  84. || throwsPattern.getRequired().getTypePatterns().length > 0) {
  85. checkForIncorrectTargetKind(throwsPattern,scope,false);
  86. }
  87. }
  88. if (annotationPattern != null) {
  89. annotationPattern = annotationPattern.resolveBindings(scope,bindings,false);
  90. checkForIncorrectTargetKind(annotationPattern,scope,true);
  91. }
  92. hashcode =-1;
  93. return this;
  94. }
  95. // bug 115252 - adding an xlint warning if the annnotation target type is
  96. // wrong. This logic, or similar, may have to be applied elsewhere in the case
  97. // of pointcuts which don't go through SignaturePattern.resolveBindings(..)
  98. private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed) {
  99. // return if we're not in java5 mode, if the unmatchedTargetKind Xlint
  100. // warning has been turned off, or if the patternNode is *
  101. if (!scope.getWorld().isInJava5Mode()
  102. || scope.getWorld().getLint().unmatchedTargetKind == null
  103. || (patternNode instanceof AnyTypePattern)) {
  104. return;
  105. }
  106. if (patternNode instanceof ExactAnnotationTypePattern) {
  107. ResolvedType resolvedType = ((ExactAnnotationTypePattern)patternNode).getAnnotationType().resolve(scope.getWorld());
  108. if (targetsOtherThanTypeAllowed) {
  109. AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
  110. if (targetKinds == null) return;
  111. reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,true);
  112. } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) {
  113. // everything is incorrect since we've already checked whether we have the TYPE target annotation
  114. AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
  115. if (targetKinds == null) return;
  116. reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,false);
  117. }
  118. } else {
  119. TypePatternVisitor visitor = new TypePatternVisitor(scope,targetsOtherThanTypeAllowed);
  120. patternNode.traverse(visitor,null);
  121. if (visitor.containedIncorrectTargetKind()) {
  122. Set keys = visitor.getIncorrectTargetKinds().keySet();
  123. for (Iterator iter = keys.iterator(); iter.hasNext();) {
  124. PatternNode node = (PatternNode)iter.next();
  125. AnnotationTargetKind[] targetKinds = (AnnotationTargetKind[]) visitor.getIncorrectTargetKinds().get(node);
  126. reportUnmatchedTargetKindMessage(targetKinds,node,scope,false);
  127. }
  128. }
  129. }
  130. }
  131. private void reportUnmatchedTargetKindMessage(
  132. AnnotationTargetKind[] annotationTargetKinds,
  133. PatternNode node,
  134. IScope scope,
  135. boolean checkMatchesMemberKindName) {
  136. StringBuffer targetNames = new StringBuffer("{");
  137. for (int i = 0; i < annotationTargetKinds.length; i++) {
  138. AnnotationTargetKind targetKind = annotationTargetKinds[i];
  139. if (checkMatchesMemberKindName && kind.getName().equals(targetKind.getName())) {
  140. return;
  141. }
  142. if (i < (annotationTargetKinds.length - 1)) {
  143. targetNames.append("ElementType." + targetKind.getName() + ",");
  144. } else {
  145. targetNames.append("ElementType." + targetKind.getName() + "}");
  146. }
  147. }
  148. scope.getWorld().getLint().unmatchedTargetKind.signal(new String[] {node.toString(),targetNames.toString()}, getSourceLocation(), new ISourceLocation[0]);
  149. }
  150. /**
  151. * Class which visits the nodes in the TypePattern tree until an
  152. * ExactTypePattern is found. Once this is found it creates a new
  153. * ExactAnnotationTypePattern and checks whether the targetKind
  154. * (created via the @Target annotation) matches ElementType.TYPE if
  155. * this is the only target kind which is allowed, or matches the
  156. * signature pattern kind if there is no restriction.
  157. */
  158. private class TypePatternVisitor extends AbstractPatternNodeVisitor {
  159. private IScope scope;
  160. private Map incorrectTargetKinds /* PatternNode -> AnnotationTargetKind[] */ = new HashMap();
  161. private boolean targetsOtherThanTypeAllowed;
  162. /**
  163. * @param requiredTarget - the signature pattern Kind
  164. * @param scope
  165. */
  166. public TypePatternVisitor(IScope scope, boolean targetsOtherThanTypeAllowed) {
  167. this.scope = scope;
  168. this.targetsOtherThanTypeAllowed = targetsOtherThanTypeAllowed;
  169. }
  170. public Object visit(WildAnnotationTypePattern node, Object data) {
  171. node.getTypePattern().accept(this,data);
  172. return node;
  173. }
  174. /**
  175. * Do the ExactAnnotationTypePatterns have the incorrect target?
  176. */
  177. public Object visit(ExactAnnotationTypePattern node, Object data) {
  178. ResolvedType resolvedType = node.getAnnotationType().resolve(scope.getWorld());
  179. if (targetsOtherThanTypeAllowed) {
  180. AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
  181. if (targetKinds == null) return data;
  182. List incorrectTargets = new ArrayList();
  183. for (int i = 0; i < targetKinds.length; i++) {
  184. if (targetKinds[i].getName().equals(kind.getName())) {
  185. return data;
  186. }
  187. incorrectTargets.add(targetKinds[i]);
  188. }
  189. if (incorrectTargets.isEmpty()) return data;
  190. AnnotationTargetKind[] kinds = new AnnotationTargetKind[incorrectTargets.size()];
  191. incorrectTargetKinds.put(node,(AnnotationTargetKind[]) incorrectTargets.toArray(kinds));
  192. } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) {
  193. AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
  194. if (targetKinds == null) return data;
  195. incorrectTargetKinds.put(node,targetKinds);
  196. }
  197. return data;
  198. }
  199. public Object visit(ExactTypePattern node, Object data) {
  200. ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(node.getExactType().resolve(scope.getWorld()));
  201. eatp.accept(this,data);
  202. return data;
  203. }
  204. public Object visit(AndTypePattern node, Object data) {
  205. node.getLeft().accept(this,data);
  206. node.getRight().accept(this,data);
  207. return node;
  208. }
  209. public Object visit(OrTypePattern node, Object data) {
  210. node.getLeft().accept(this,data);
  211. node.getRight().accept(this,data);
  212. return node;
  213. }
  214. public Object visit(AnyWithAnnotationTypePattern node, Object data) {
  215. node.getAnnotationPattern().accept(this,data);
  216. return node;
  217. }
  218. public boolean containedIncorrectTargetKind() {
  219. return (incorrectTargetKinds.size() != 0);
  220. }
  221. public Map getIncorrectTargetKinds() {
  222. return incorrectTargetKinds;
  223. }
  224. }
  225. public void postRead(ResolvedType enclosingType) {
  226. if (returnType != null) {
  227. returnType.postRead(enclosingType);
  228. }
  229. if (declaringType != null) {
  230. declaringType.postRead(enclosingType);
  231. }
  232. if (parameterTypes != null) {
  233. parameterTypes.postRead(enclosingType);
  234. }
  235. }
  236. /**
  237. * return a copy of this signature pattern in which every type variable reference
  238. * is replaced by the corresponding entry in the map.
  239. */
  240. public SignaturePattern parameterizeWith(Map typeVariableMap,World w) {
  241. SignaturePattern ret = new SignaturePattern(
  242. kind,
  243. modifiers,
  244. returnType.parameterizeWith(typeVariableMap,w),
  245. declaringType.parameterizeWith(typeVariableMap,w),
  246. name,
  247. parameterTypes.parameterizeWith(typeVariableMap,w),
  248. throwsPattern.parameterizeWith(typeVariableMap,w),
  249. annotationPattern.parameterizeWith(typeVariableMap,w));
  250. ret.copyLocationFrom(this);
  251. return ret;
  252. }
  253. public boolean matches(Member joinPointSignature, World world, boolean allowBridgeMethods) {
  254. // fail (or succeed!) fast tests...
  255. if (joinPointSignature == null) return false;
  256. if (kind != joinPointSignature.getKind()) return false;
  257. if (kind == Member.ADVICE) return true;
  258. // do the hard work then...
  259. boolean subjectMatch = true;
  260. Iterator candidateMatches = joinPointSignature.getJoinPointSignatures(world);
  261. while(candidateMatches.hasNext()) {
  262. JoinPointSignature aSig = (JoinPointSignature) candidateMatches.next();
  263. FuzzyBoolean matchResult = matchesExactly(aSig,world,allowBridgeMethods,subjectMatch);
  264. if (matchResult.alwaysTrue()) {
  265. return true;
  266. } else if (matchResult.alwaysFalse()) {
  267. return false;
  268. }
  269. // if we got a "MAYBE" it's worth looking at the other signatures
  270. subjectMatch = false;
  271. }
  272. return false;
  273. }
  274. // Does this pattern match this exact signature (no declaring type mucking about
  275. // or chasing up the hierarchy)
  276. // return YES if it does, NO if it doesn't and no ancester member could match either,
  277. // and MAYBE if it doesn't but an ancester member could.
  278. private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods,boolean subjectMatch) {
  279. // Java5 introduces bridge methods, we match a call to them but nothing else...
  280. if (aMember.isBridgeMethod() && !allowBridgeMethods) {
  281. return FuzzyBoolean.MAYBE;
  282. }
  283. // modifiers match on the *subject*
  284. if (subjectMatch && !modifiers.matches(aMember.getModifiers())) {
  285. return FuzzyBoolean.NO;
  286. // if (aMember.isPrivate()) return FuzzyBoolean.NO;
  287. // else return FuzzyBoolean.MAYBE;
  288. }
  289. FuzzyBoolean matchesIgnoringAnnotations = FuzzyBoolean.YES;
  290. if (kind == Member.STATIC_INITIALIZATION) {
  291. matchesIgnoringAnnotations = matchesExactlyStaticInitialization(aMember, inAWorld);
  292. } else if (kind == Member.FIELD) {
  293. matchesIgnoringAnnotations = matchesExactlyField(aMember,inAWorld);
  294. } else if (kind == Member.METHOD) {
  295. matchesIgnoringAnnotations = matchesExactlyMethod(aMember,inAWorld, subjectMatch);
  296. } else if (kind == Member.CONSTRUCTOR) {
  297. matchesIgnoringAnnotations = matchesExactlyConstructor(aMember, inAWorld);
  298. }
  299. if (matchesIgnoringAnnotations.alwaysFalse()) return FuzzyBoolean.NO;
  300. // last thing to try
  301. if (subjectMatch && modifiers.concernedWithTriviality()) {
  302. if (!inAWorld.isJoinpointTrivialEnabled()) {
  303. inAWorld.getMessageHandler().handleMessage(MessageUtil.warn("pointcuts can not use trivial modifier unless -Xjoinpoints:trivial specified"));
  304. } else {
  305. ResolvedMember rm = aMember.resolve(inAWorld);
  306. boolean isTrivial = rm.isTrivial();
  307. if (!modifiers.matchesTriviality(isTrivial)) return FuzzyBoolean.NO;
  308. }
  309. }
  310. // annotations match on the *subject*
  311. if (subjectMatch && !matchesAnnotations(aMember,inAWorld).alwaysTrue()) {
  312. return FuzzyBoolean.NO;
  313. } else {
  314. return matchesIgnoringAnnotations;
  315. }
  316. }
  317. /**
  318. * Matches on declaring type
  319. */
  320. private FuzzyBoolean matchesExactlyStaticInitialization(JoinPointSignature aMember,World world) {
  321. return FuzzyBoolean.fromBoolean(declaringType.matchesStatically(aMember.getDeclaringType().resolve(world)));
  322. }
  323. /**
  324. * Matches on name, declaring type, field type
  325. */
  326. private FuzzyBoolean matchesExactlyField(JoinPointSignature aField, World world) {
  327. if (!name.matches(aField.getName())) return FuzzyBoolean.NO;
  328. ResolvedType fieldDeclaringType = aField.getDeclaringType().resolve(world);
  329. if (!declaringType.matchesStatically(fieldDeclaringType)) {
  330. return FuzzyBoolean.MAYBE;
  331. }
  332. if (!returnType.matchesStatically(aField.getReturnType().resolve(world))) {
  333. // looking bad, but there might be parameterization to consider...
  334. if (!returnType.matchesStatically(aField.getGenericReturnType().resolve(world))) {
  335. // ok, it's bad.
  336. return FuzzyBoolean.MAYBE;
  337. }
  338. }
  339. // passed all the guards...
  340. return FuzzyBoolean.YES;
  341. }
  342. /**
  343. * Matches on name, declaring type, return type, parameter types, throws types
  344. */
  345. private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) {
  346. if (!name.matches(aMethod.getName())) return FuzzyBoolean.NO;
  347. // Check the throws pattern
  348. if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) return FuzzyBoolean.NO;
  349. if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) return FuzzyBoolean.MAYBE;
  350. if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
  351. // looking bad, but there might be parameterization to consider...
  352. if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
  353. // ok, it's bad.
  354. return FuzzyBoolean.MAYBE;
  355. }
  356. }
  357. if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) return FuzzyBoolean.NO;
  358. ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());
  359. if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC).alwaysTrue()) {
  360. // It could still be a match based on the generic sig parameter types of a parameterized type
  361. if (!parameterTypes.matches(world.resolve(aMethod.getGenericParameterTypes()),TypePattern.STATIC).alwaysTrue()) {
  362. return FuzzyBoolean.MAYBE;
  363. // It could STILL be a match based on the erasure of the parameter types??
  364. // to be determined via test cases...
  365. }
  366. }
  367. // check that varargs specifications match
  368. if (!matchesVarArgs(aMethod,world)) return FuzzyBoolean.MAYBE;
  369. // passed all the guards..
  370. return FuzzyBoolean.YES;
  371. }
  372. /**
  373. * match on declaring type, parameter types, throws types
  374. */
  375. private FuzzyBoolean matchesExactlyConstructor(JoinPointSignature aConstructor, World world) {
  376. if (!declaringType.matchesStatically(aConstructor.getDeclaringType().resolve(world))) return FuzzyBoolean.NO;
  377. if (!parameterTypes.canMatchSignatureWithNParameters(aConstructor.getParameterTypes().length)) return FuzzyBoolean.NO;
  378. ResolvedType[] resolvedParameters = world.resolve(aConstructor.getParameterTypes());
  379. if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC).alwaysTrue()) {
  380. // It could still be a match based on the generic sig parameter types of a parameterized type
  381. if (!parameterTypes.matches(world.resolve(aConstructor.getGenericParameterTypes()),TypePattern.STATIC).alwaysTrue()) {
  382. return FuzzyBoolean.MAYBE;
  383. // It could STILL be a match based on the erasure of the parameter types??
  384. // to be determined via test cases...
  385. }
  386. }
  387. // check that varargs specifications match
  388. if (!matchesVarArgs(aConstructor,world)) return FuzzyBoolean.NO;
  389. // Check the throws pattern
  390. if (!throwsPattern.matches(aConstructor.getExceptions(), world)) return FuzzyBoolean.NO;
  391. // passed all the guards..
  392. return FuzzyBoolean.YES;
  393. }
  394. /**
  395. * We've matched against this method or constructor so far, but without considering
  396. * varargs (which has been matched as a simple array thus far). Now we do the additional
  397. * checks to see if the parties agree on whether the last parameter is varargs or a
  398. * straight array.
  399. */
  400. private boolean matchesVarArgs(JoinPointSignature aMethodOrConstructor, World inAWorld) {
  401. if (parameterTypes.size() == 0) return true;
  402. TypePattern lastPattern = parameterTypes.get(parameterTypes.size()-1);
  403. boolean canMatchVarArgsSignature = lastPattern.isStar() ||
  404. lastPattern.isVarArgs() ||
  405. (lastPattern == TypePattern.ELLIPSIS);
  406. if (aMethodOrConstructor.isVarargsMethod()) {
  407. // we have at least one parameter in the pattern list, and the method has a varargs signature
  408. if (!canMatchVarArgsSignature) {
  409. // XXX - Ideally the shadow would be included in the msg but we don't know it...
  410. inAWorld.getLint().cantMatchArrayTypeOnVarargs.signal(aMethodOrConstructor.toString(),getSourceLocation());
  411. return false;
  412. }
  413. } else {
  414. // the method ends with an array type, check that we don't *require* a varargs
  415. if (lastPattern.isVarArgs()) return false;
  416. }
  417. return true;
  418. }
  419. private FuzzyBoolean matchesAnnotations(ResolvedMember member,World world) {
  420. if (member == null) {
  421. if (member.getName().startsWith(NameMangler.PREFIX)) {
  422. return FuzzyBoolean.NO;
  423. }
  424. world.getLint().unresolvableMember.signal(member.toString(), getSourceLocation());
  425. return FuzzyBoolean.NO;
  426. }
  427. annotationPattern.resolve(world);
  428. // optimization before we go digging around for annotations on ITDs
  429. if (annotationPattern instanceof AnyAnnotationTypePattern) return FuzzyBoolean.YES;
  430. // fake members represent ITD'd fields - for their annotations we should go and look up the
  431. // relevant member in the original aspect
  432. if (member.isAnnotatedElsewhere() && member.getKind()==Member.FIELD) {
  433. // FIXME asc duplicate of code in AnnotationPointcut.matchInternal()? same fixmes apply here.
  434. ResolvedMember [] mems = member.getDeclaringType().resolve(world).getDeclaredFields(); // FIXME asc should include supers with getInterTypeMungersIncludingSupers?
  435. List mungers = member.getDeclaringType().resolve(world).getInterTypeMungers();
  436. for (Iterator iter = mungers.iterator(); iter.hasNext();) {
  437. BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
  438. if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
  439. ResolvedMember fakerm = typeMunger.getSignature();
  440. ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType());
  441. ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
  442. if (fakerm.equals(member)) {
  443. member = rmm;
  444. }
  445. }
  446. }
  447. }
  448. if (annotationPattern.matches(member).alwaysTrue()) {
  449. return FuzzyBoolean.YES;
  450. } else {
  451. return FuzzyBoolean.NO; // do NOT look at ancestor members...
  452. }
  453. }
  454. private ResolvedMember findMethod(ResolvedType aspectType, ResolvedMember ajcMethod) {
  455. ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
  456. for (int i = 0; i < decMethods.length; i++) {
  457. ResolvedMember member = decMethods[i];
  458. if (member.equals(ajcMethod)) return member;
  459. }
  460. return null;
  461. }
  462. public boolean declaringTypeMatchAllowingForCovariance(Member member, UnresolvedType shadowDeclaringType, World world,TypePattern returnTypePattern,ResolvedType sigReturn) {
  463. ResolvedType onType = shadowDeclaringType.resolve(world);
  464. // fastmatch
  465. if (declaringType.matchesStatically(onType) && returnTypePattern.matchesStatically(sigReturn))
  466. return true;
  467. Collection declaringTypes = member.getDeclaringTypes(world);
  468. boolean checkReturnType = true;
  469. // XXX Possible enhancement? Doesn't seem to speed things up
  470. // if (returnTypePattern.isStar()) {
  471. // if (returnTypePattern instanceof WildTypePattern) {
  472. // if (((WildTypePattern)returnTypePattern).getDimensions()==0) checkReturnType = false;
  473. // }
  474. // }
  475. // Sometimes that list includes types that don't explicitly declare the member we are after -
  476. // they are on the list because their supertype is on the list, that's why we use
  477. // lookupMethod rather than lookupMemberNoSupers()
  478. for (Iterator i = declaringTypes.iterator(); i.hasNext(); ) {
  479. ResolvedType type = (ResolvedType)i.next();
  480. if (declaringType.matchesStatically(type)) {
  481. if (!checkReturnType) return true;
  482. ResolvedMember rm = type.lookupMethod(member);
  483. if (rm==null) rm = type.lookupMethodInITDs(member); // It must be in here, or we have *real* problems
  484. if (rm==null) continue; // might be currently looking at the generic type and we need to continue searching in case we hit a parameterized version of this same type...
  485. UnresolvedType returnTypeX = rm.getReturnType();
  486. ResolvedType returnType = returnTypeX.resolve(world);
  487. if (returnTypePattern.matchesStatically(returnType)) return true;
  488. }
  489. }
  490. return false;
  491. }
  492. private Collection getDeclaringTypes(Signature sig) {
  493. List l = new ArrayList();
  494. Class onType = sig.getDeclaringType();
  495. String memberName = sig.getName();
  496. if (sig instanceof FieldSignature) {
  497. Class fieldType = ((FieldSignature)sig).getFieldType();
  498. Class superType = onType;
  499. while(superType != null) {
  500. try {
  501. Field f = (superType.getDeclaredField(memberName));
  502. if (f.getType() == fieldType) {
  503. l.add(superType);
  504. }
  505. } catch (NoSuchFieldException nsf) {}
  506. superType = superType.getSuperclass();
  507. }
  508. } else if (sig instanceof MethodSignature) {
  509. Class[] paramTypes = ((MethodSignature)sig).getParameterTypes();
  510. Class superType = onType;
  511. while(superType != null) {
  512. try {
  513. superType.getDeclaredMethod(memberName,paramTypes);
  514. l.add(superType);
  515. } catch (NoSuchMethodException nsm) {}
  516. superType = superType.getSuperclass();
  517. }
  518. }
  519. return l;
  520. }
  521. public NamePattern getName() { return name; }
  522. public TypePattern getDeclaringType() { return declaringType; }
  523. public Member.Kind getKind() {
  524. return kind;
  525. }
  526. public String toString() {
  527. StringBuffer buf = new StringBuffer();
  528. if (annotationPattern != AnnotationTypePattern.ANY) {
  529. buf.append(annotationPattern.toString());
  530. buf.append(' ');
  531. }
  532. if (modifiers != ModifiersPattern.ANY) {
  533. buf.append(modifiers.toString());
  534. buf.append(' ');
  535. }
  536. if (kind == Member.STATIC_INITIALIZATION) {
  537. buf.append(declaringType.toString());
  538. buf.append(".<clinit>()");//FIXME AV - bad, cannot be parsed again
  539. } else if (kind == Member.HANDLER) {
  540. buf.append("handler(");
  541. buf.append(parameterTypes.get(0));
  542. buf.append(")");
  543. } else {
  544. if (!(kind == Member.CONSTRUCTOR)) {
  545. buf.append(returnType.toString());
  546. buf.append(' ');
  547. }
  548. if (declaringType != TypePattern.ANY) {
  549. buf.append(declaringType.toString());
  550. buf.append('.');
  551. }
  552. if (kind == Member.CONSTRUCTOR) {
  553. buf.append("new");
  554. } else {
  555. buf.append(name.toString());
  556. }
  557. if (kind == Member.METHOD || kind == Member.CONSTRUCTOR) {
  558. buf.append(parameterTypes.toString());
  559. }
  560. //FIXME AV - throws is not printed here, weird
  561. }
  562. return buf.toString();
  563. }
  564. public boolean equals(Object other) {
  565. if (!(other instanceof SignaturePattern)) return false;
  566. SignaturePattern o = (SignaturePattern)other;
  567. return o.kind.equals(this.kind)
  568. && o.modifiers.equals(this.modifiers)
  569. && o.returnType.equals(this.returnType)
  570. && o.declaringType.equals(this.declaringType)
  571. && o.name.equals(this.name)
  572. && o.parameterTypes.equals(this.parameterTypes)
  573. && o.throwsPattern.equals(this.throwsPattern)
  574. && o.annotationPattern.equals(this.annotationPattern);
  575. }
  576. public int hashCode() {
  577. if (hashcode==-1) {
  578. hashcode = 17;
  579. hashcode = 37*hashcode + kind.hashCode();
  580. hashcode = 37*hashcode + modifiers.hashCode();
  581. hashcode = 37*hashcode + returnType.hashCode();
  582. hashcode = 37*hashcode + declaringType.hashCode();
  583. hashcode = 37*hashcode + name.hashCode();
  584. hashcode = 37*hashcode + parameterTypes.hashCode();
  585. hashcode = 37*hashcode + throwsPattern.hashCode();
  586. hashcode = 37*hashcode + annotationPattern.hashCode();
  587. }
  588. return hashcode;
  589. }
  590. public void write(DataOutputStream s) throws IOException {
  591. kind.write(s);
  592. modifiers.write(s);
  593. returnType.write(s);
  594. declaringType.write(s);
  595. name.write(s);
  596. parameterTypes.write(s);
  597. throwsPattern.write(s);
  598. annotationPattern.write(s);
  599. writeLocation(s);
  600. }
  601. public static SignaturePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  602. Member.Kind kind = Member.Kind.read(s);
  603. ModifiersPattern modifiers = ModifiersPattern.read(s);
  604. TypePattern returnType = TypePattern.read(s, context);
  605. TypePattern declaringType = TypePattern.read(s, context);
  606. NamePattern name = NamePattern.read(s);
  607. TypePatternList parameterTypes = TypePatternList.read(s, context);
  608. ThrowsPattern throwsPattern = ThrowsPattern.read(s, context);
  609. AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY;
  610. if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
  611. annotationPattern = AnnotationTypePattern.read(s,context);
  612. }
  613. SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType,
  614. name, parameterTypes, throwsPattern,annotationPattern);
  615. ret.readLocation(context, s);
  616. return ret;
  617. }
  618. /**
  619. * @return
  620. */
  621. public ModifiersPattern getModifiers() {
  622. return modifiers;
  623. }
  624. /**
  625. * @return
  626. */
  627. public TypePatternList getParameterTypes() {
  628. return parameterTypes;
  629. }
  630. /**
  631. * @return
  632. */
  633. public TypePattern getReturnType() {
  634. return returnType;
  635. }
  636. /**
  637. * @return
  638. */
  639. public ThrowsPattern getThrowsPattern() {
  640. return throwsPattern;
  641. }
  642. /**
  643. * return true if last argument in params is an Object[] but the modifiers say this method
  644. * was declared with varargs (Object...). We shouldn't be matching if this is the case.
  645. */
  646. private boolean matchedArrayAgainstVarArgs(TypePatternList params,int modifiers) {
  647. if (params.size()>0 && (modifiers & Constants.ACC_VARARGS)!=0) {
  648. // we have at least one parameter in the pattern list, and the method has a varargs signature
  649. TypePattern lastPattern = params.get(params.size()-1);
  650. if (lastPattern.isArray() && !lastPattern.isVarArgs) return true;
  651. }
  652. return false;
  653. }
  654. public AnnotationTypePattern getAnnotationPattern() {
  655. return annotationPattern;
  656. }
  657. public boolean isStarAnnotation() {
  658. return annotationPattern == AnnotationTypePattern.ANY;
  659. }
  660. public Object accept(PatternNodeVisitor visitor, Object data) {
  661. return visitor.visit(this, data);
  662. }
  663. }