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.

ReferencePointcut.java 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. * Xerox/PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.io.*;
  14. import java.lang.reflect.Modifier;
  15. import java.util.*;
  16. import java.util.Map;
  17. import org.apache.bcel.classfile.*;
  18. import org.aspectj.weaver.*;
  19. import org.aspectj.weaver.ast.*;
  20. import org.aspectj.bridge.*;
  21. import org.aspectj.bridge.MessageUtil;
  22. import org.aspectj.util.*;
  23. /**
  24. */
  25. //XXX needs check that arguments contains no WildTypePatterns
  26. public class ReferencePointcut extends Pointcut {
  27. public TypeX onType;
  28. public TypePattern onTypeSymbolic;
  29. public String name;
  30. public TypePatternList arguments;
  31. //public ResolvedPointcut binding;
  32. public ReferencePointcut(TypePattern onTypeSymbolic, String name, TypePatternList arguments) {
  33. this.onTypeSymbolic = onTypeSymbolic;
  34. this.name = name;
  35. this.arguments = arguments;
  36. }
  37. public ReferencePointcut(TypeX onType, String name, TypePatternList arguments) {
  38. this.onType = onType;
  39. this.name = name;
  40. this.arguments = arguments;
  41. }
  42. /**
  43. * Could I match any shadows in this JavaClass
  44. */
  45. public boolean fastMatch(JavaClass jc) { return true; }
  46. /**
  47. * Do I really match this shadow?
  48. */
  49. public FuzzyBoolean match(Shadow shadow) {
  50. return FuzzyBoolean.NO;
  51. }
  52. public String toString() {
  53. StringBuffer buf = new StringBuffer();
  54. if (onType != null) {
  55. buf.append(onType);
  56. buf.append(".");
  57. // for (int i=0, len=fromType.length; i < len; i++) {
  58. // buf.append(fromType[i]);
  59. // buf.append(".");
  60. // }
  61. }
  62. buf.append(name);
  63. buf.append(arguments.toString());
  64. return buf.toString();
  65. }
  66. public void write(DataOutputStream s) throws IOException {
  67. //XXX ignores onType
  68. s.writeByte(Pointcut.REFERENCE);
  69. if (onType != null) {
  70. s.writeBoolean(true);
  71. onType.write(s);
  72. } else {
  73. s.writeBoolean(false);
  74. }
  75. s.writeUTF(name);
  76. arguments.write(s);
  77. writeLocation(s);
  78. }
  79. public static Pointcut read(DataInputStream s, ISourceContext context) throws IOException {
  80. TypeX onType = null;
  81. if (s.readBoolean()) {
  82. onType = TypeX.read(s);
  83. }
  84. ReferencePointcut ret = new ReferencePointcut(onType, s.readUTF(),
  85. TypePatternList.read(s, context));
  86. ret.readLocation(context, s);
  87. return ret;
  88. }
  89. public void resolveBindings(IScope scope, Bindings bindings) {
  90. if (onTypeSymbolic != null) {
  91. onType = onTypeSymbolic.resolveExactType(scope, bindings);
  92. }
  93. ResolvedTypeX searchType;
  94. if (onType != null) {
  95. searchType = scope.getWorld().resolve(onType);
  96. } else {
  97. searchType = scope.getEnclosingType();
  98. }
  99. arguments.resolveBindings(scope, bindings, true, true);
  100. //XXX ensure that arguments has no ..'s in it
  101. // check that I refer to a real pointcut declaration and that I match
  102. ResolvedPointcutDefinition pointcutDef = searchType.findPointcut(name);
  103. // if we're not a static reference, then do a lookup of outers
  104. if (onType == null) {
  105. while (true) {
  106. TypeX declaringType = searchType.getDeclaringType();
  107. if (declaringType == null) break;
  108. searchType = declaringType.resolve(scope.getWorld());
  109. pointcutDef = searchType.findPointcut(name);
  110. if (pointcutDef != null) {
  111. // make this a static reference
  112. onType = searchType;
  113. break;
  114. }
  115. }
  116. }
  117. if (pointcutDef == null) {
  118. scope.message(IMessage.ERROR, this, "can't find referenced pointcut");
  119. return;
  120. }
  121. if (Modifier.isAbstract(pointcutDef.getModifiers())) {
  122. if (onType != null) {
  123. scope.message(IMessage.ERROR, this,
  124. "can't make static reference to abstract pointcut");
  125. return;
  126. } else if (!searchType.isAbstract()) {
  127. scope.message(IMessage.ERROR, this,
  128. "can't use abstract pointcut in concrete context");
  129. return;
  130. }
  131. }
  132. ResolvedTypeX[] parameterTypes =
  133. scope.getWorld().resolve(pointcutDef.getParameterTypes());
  134. if (parameterTypes.length != arguments.size()) {
  135. scope.message(IMessage.ERROR, this, "incompatible number of arguments to pointcut, expected " +
  136. parameterTypes.length + " found " + arguments.size());
  137. return;
  138. }
  139. for (int i=0,len=arguments.size(); i < len; i++) {
  140. TypePattern p = arguments.get(i);
  141. //we are allowed to bind to pointcuts which use subtypes as this is type safe
  142. if (!p.matchesSubtypes(parameterTypes[i])) {
  143. scope.message(IMessage.ERROR, p, "incompatible type, expected " +
  144. parameterTypes[i] + " found " + p);
  145. return;
  146. }
  147. }
  148. }
  149. public void postRead(ResolvedTypeX enclosingType) {
  150. arguments.postRead(enclosingType);
  151. }
  152. public Test findResidue(Shadow shadow, ExposedState state) {
  153. throw new RuntimeException("shouldn't happen");
  154. }
  155. //??? This is not thread safe, but this class is not designed for multi-threading
  156. private boolean concretizing = false;
  157. public Pointcut concretize1(ResolvedTypeX searchStart, IntMap bindings) {
  158. if (concretizing) {
  159. Thread.currentThread().dumpStack();
  160. searchStart.getWorld().getMessageHandler().handleMessage(
  161. MessageUtil.error("circular pointcut declaration involving: " + this,
  162. getSourceLocation()));
  163. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  164. }
  165. try {
  166. concretizing = true;
  167. ResolvedPointcutDefinition pointcutDec;
  168. if (onType != null) {
  169. searchStart = onType.resolve(searchStart.getWorld());
  170. if (searchStart == ResolvedTypeX.MISSING) {
  171. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  172. }
  173. }
  174. pointcutDec = searchStart.findPointcut(name);
  175. if (pointcutDec == null) {
  176. searchStart.getWorld().getMessageHandler().handleMessage(
  177. MessageUtil.error("can't find pointcut \'" + name + "\' on " + searchStart.getName(),
  178. getSourceLocation())
  179. );
  180. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  181. }
  182. //??? error if we don't find
  183. //System.err.println("start: " + searchStart);
  184. ResolvedTypeX[] parameterTypes = searchStart.getWorld().resolve(pointcutDec.getParameterTypes());
  185. arguments = arguments.resolveReferences(bindings);
  186. IntMap newBindings = new IntMap();
  187. for (int i=0,len=arguments.size(); i < len; i++) {
  188. TypePattern p = arguments.get(i);
  189. //we are allowed to bind to pointcuts which use subtypes as this is type safe
  190. if (!p.matchesSubtypes(parameterTypes[i])) {
  191. throw new BCException("illegal change to pointcut declaration: " + this);
  192. }
  193. if (p instanceof BindingTypePattern) {
  194. newBindings.put(i, ((BindingTypePattern)p).getFormalIndex());
  195. }
  196. }
  197. newBindings.copyContext(bindings);
  198. newBindings.pushEnclosingDefinition(pointcutDec);
  199. try {
  200. return pointcutDec.getPointcut().concretize1(searchStart, newBindings);
  201. } finally {
  202. newBindings.popEnclosingDefinitition();
  203. }
  204. } finally {
  205. concretizing = false;
  206. }
  207. }
  208. public boolean equals(Object other) {
  209. if (!(other instanceof ReferencePointcut)) return false;
  210. ReferencePointcut o = (ReferencePointcut)other;
  211. return o.name.equals(name) && o.arguments.equals(arguments)
  212. && ((o.onType == null) ? (onType == null) : o.onType.equals(onType));
  213. }
  214. public int hashCode() {
  215. int result = 17;
  216. result = 37*result + ((onType == null) ? 0 : onType.hashCode());
  217. result = 37*result + arguments.hashCode();
  218. result = 37*result + name.hashCode();
  219. return result;
  220. }
  221. }