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.

BcelWorld.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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.bcel;
  13. import java.io.File;
  14. import java.io.IOException;
  15. import java.lang.reflect.Modifier;
  16. import java.util.ArrayList;
  17. import java.util.List;
  18. import java.util.StringTokenizer;
  19. import org.aspectj.apache.bcel.classfile.ClassParser;
  20. import org.aspectj.apache.bcel.classfile.JavaClass;
  21. import org.aspectj.apache.bcel.classfile.Method;
  22. import org.aspectj.apache.bcel.generic.ConstantPoolGen;
  23. import org.aspectj.apache.bcel.generic.FieldInstruction;
  24. import org.aspectj.apache.bcel.generic.GETSTATIC;
  25. import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
  26. import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
  27. import org.aspectj.apache.bcel.generic.INVOKESTATIC;
  28. import org.aspectj.apache.bcel.generic.InvokeInstruction;
  29. import org.aspectj.apache.bcel.generic.PUTSTATIC;
  30. import org.aspectj.apache.bcel.generic.Type;
  31. import org.aspectj.apache.bcel.util.ClassPath;
  32. import org.aspectj.bridge.IMessageHandler;
  33. import org.aspectj.weaver.Advice;
  34. import org.aspectj.weaver.AdviceKind;
  35. import org.aspectj.weaver.AjAttribute;
  36. import org.aspectj.weaver.ConcreteTypeMunger;
  37. import org.aspectj.weaver.ICrossReferenceHandler;
  38. import org.aspectj.weaver.Member;
  39. import org.aspectj.weaver.ResolvedMember;
  40. import org.aspectj.weaver.ResolvedTypeMunger;
  41. import org.aspectj.weaver.ResolvedTypeX;
  42. import org.aspectj.weaver.TypeX;
  43. import org.aspectj.weaver.World;
  44. import org.aspectj.weaver.patterns.FormalBinding;
  45. import org.aspectj.weaver.patterns.Pointcut;
  46. import org.aspectj.weaver.patterns.SimpleScope;
  47. public class BcelWorld extends World {
  48. private ClassPathManager classPath;
  49. //private ClassPathManager aspectPath = null;
  50. // private List aspectPathEntries;
  51. // ---- constructors
  52. public BcelWorld() {
  53. this("");
  54. }
  55. public BcelWorld(String cp) {
  56. this(makeDefaultClasspath(cp), IMessageHandler.THROW, null);
  57. }
  58. private static List makeDefaultClasspath(String cp) {
  59. List classPath = new ArrayList();
  60. classPath.addAll(getPathEntries(cp));
  61. classPath.addAll(getPathEntries(ClassPath.getClassPath()));
  62. //System.err.println("classpath: " + classPath);
  63. return classPath;
  64. }
  65. private static List getPathEntries(String s) {
  66. List ret = new ArrayList();
  67. StringTokenizer tok = new StringTokenizer(s, File.pathSeparator);
  68. while(tok.hasMoreTokens()) ret.add(tok.nextToken());
  69. return ret;
  70. }
  71. public BcelWorld(List classPath, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  72. //this.aspectPath = new ClassPathManager(aspectPath, handler);
  73. this.classPath = new ClassPathManager(classPath, handler);
  74. setMessageHandler(handler);
  75. setXRefHandler(xrefHandler);
  76. }
  77. public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  78. this.classPath = cpm;
  79. setMessageHandler(handler);
  80. setXRefHandler(xrefHandler);
  81. }
  82. public void addPath (String name) {
  83. classPath.addPath(name, this.getMessageHandler());
  84. }
  85. /**
  86. * Parse a string into advice.
  87. *
  88. * <blockquote><pre>
  89. * Kind ( Id , ... ) : Pointcut -> MethodSignature
  90. * </pre></blockquote>
  91. */
  92. public Advice shadowMunger(String str, int extraFlag) {
  93. str = str.trim();
  94. int start = 0;
  95. int i = str.indexOf('(');
  96. AdviceKind kind =
  97. AdviceKind.stringToKind(str.substring(start, i));
  98. start = ++i;
  99. i = str.indexOf(')', i);
  100. String[] ids = parseIds(str.substring(start, i).trim());
  101. //start = ++i;
  102. i = str.indexOf(':', i);
  103. start = ++i;
  104. i = str.indexOf("->", i);
  105. Pointcut pointcut = Pointcut.fromString(str.substring(start, i).trim());
  106. Member m = Member.methodFromString(str.substring(i+2, str.length()).trim());
  107. // now, we resolve
  108. TypeX[] types = m.getParameterTypes();
  109. FormalBinding[] bindings = new FormalBinding[ids.length];
  110. for (int j = 0, len = ids.length; j < len; j++) {
  111. bindings[j] = new FormalBinding(types[j], ids[j], j, 0, 0, "fromString");
  112. }
  113. Pointcut p =
  114. pointcut.resolve(new SimpleScope(this, bindings));
  115. return new BcelAdvice(kind, p, m, extraFlag, 0, 0, null, null);
  116. }
  117. private String[] parseIds(String str) {
  118. if (str.length() == 0) return ZERO_STRINGS;
  119. List l = new ArrayList();
  120. int start = 0;
  121. while (true) {
  122. int i = str.indexOf(',', start);
  123. if (i == -1) {
  124. l.add(str.substring(start).trim());
  125. break;
  126. }
  127. l.add(str.substring(start, i).trim());
  128. start = i+1;
  129. }
  130. return (String[]) l.toArray(new String[l.size()]);
  131. }
  132. // ---- various interactions with bcel
  133. public static Type makeBcelType(TypeX type) {
  134. return Type.getType(type.getSignature());
  135. }
  136. static Type[] makeBcelTypes(TypeX[] types) {
  137. Type[] ret = new Type[types.length];
  138. for (int i = 0, len = types.length; i < len; i++) {
  139. ret[i] = makeBcelType(types[i]);
  140. }
  141. return ret;
  142. }
  143. public static TypeX fromBcel(Type t) {
  144. return TypeX.forSignature(t.getSignature());
  145. }
  146. static TypeX[] fromBcel(Type[] ts) {
  147. TypeX[] ret = new TypeX[ts.length];
  148. for (int i = 0, len = ts.length; i < len; i++) {
  149. ret[i] = fromBcel(ts[i]);
  150. }
  151. return ret;
  152. }
  153. public ResolvedTypeX resolve(Type t) {
  154. return resolve(fromBcel(t));
  155. }
  156. protected ResolvedTypeX.ConcreteName resolveObjectType(ResolvedTypeX.Name ty) {
  157. String name = ty.getName();
  158. JavaClass jc = null;
  159. //UnwovenClassFile classFile = (UnwovenClassFile)sourceJavaClasses.get(name);
  160. //if (classFile != null) jc = classFile.getJavaClass();
  161. // if (jc == null) {
  162. // jc = lookupJavaClass(aspectPath, name);
  163. // }
  164. if (jc == null) {
  165. jc = lookupJavaClass(classPath, name);
  166. }
  167. if (jc == null) {
  168. return null;
  169. } else {
  170. return makeBcelObjectType(ty, jc, false);
  171. }
  172. }
  173. private BcelObjectType makeBcelObjectType(ResolvedTypeX.Name resolvedTypeX, JavaClass jc, boolean exposedToWeaver) {
  174. BcelObjectType ret = new BcelObjectType(resolvedTypeX, jc, exposedToWeaver);
  175. resolvedTypeX.setDelegate(ret);
  176. return ret;
  177. }
  178. private JavaClass lookupJavaClass(ClassPathManager classPath, String name) {
  179. if (classPath == null) return null;
  180. try {
  181. ClassPathManager.ClassFile file = classPath.find(TypeX.forName(name));
  182. if (file == null) return null;
  183. ClassParser parser = new ClassParser(file.getInputStream(), file.getPath());
  184. JavaClass jc = parser.parse();
  185. return jc;
  186. } catch (IOException ioe) {
  187. return null;
  188. }
  189. }
  190. public BcelObjectType addSourceObjectType(JavaClass jc) {
  191. String signature = TypeX.forName(jc.getClassName()).getSignature();
  192. ResolvedTypeX.Name nameTypeX = (ResolvedTypeX.Name)typeMap.get(signature);
  193. if (nameTypeX == null) {
  194. nameTypeX = new ResolvedTypeX.Name(signature, this);
  195. }
  196. BcelObjectType ret = makeBcelObjectType(nameTypeX, jc, true);
  197. nameTypeX.setDelegate(ret);
  198. typeMap.put(signature, nameTypeX);
  199. return ret;
  200. }
  201. void deleteSourceObjectType(TypeX ty) {
  202. typeMap.remove(ty.getSignature());
  203. }
  204. public static Member makeFieldSignature(LazyClassGen cg, FieldInstruction fi) {
  205. ConstantPoolGen cpg = cg.getConstantPoolGen();
  206. return
  207. Member.field(
  208. fi.getClassName(cpg),
  209. (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
  210. ? Modifier.STATIC
  211. : 0,
  212. fi.getName(cpg),
  213. fi.getSignature(cpg));
  214. }
  215. public static Member makeFieldSetSignature(LazyClassGen cg, FieldInstruction fi) {
  216. ConstantPoolGen cpg = cg.getConstantPoolGen();
  217. return
  218. Member.field(
  219. fi.getClassName(cpg),
  220. (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
  221. ? Modifier.STATIC
  222. : 0,
  223. fi.getName(cpg),
  224. "(" + fi.getSignature(cpg) + ")" +fi.getSignature(cpg));
  225. }
  226. public Member makeMethodSignature(LazyMethodGen mg) {
  227. return makeMethodSignature(mg, null);
  228. }
  229. public Member makeMethodSignature(LazyMethodGen mg, Member.Kind kind) {
  230. ResolvedMember ret = mg.getMemberView();
  231. if (ret == null) {
  232. int mods = mg.getAccessFlags();
  233. if (mg.getEnclosingClass().isInterface()) {
  234. mods |= Modifier.INTERFACE;
  235. }
  236. if (kind == null) {
  237. if (mg.getName().equals("<init>")) {
  238. kind = Member.CONSTRUCTOR;
  239. } else if (mg.getName().equals("<clinit>")) {
  240. kind = Member.STATIC_INITIALIZATION;
  241. } else {
  242. kind = Member.METHOD;
  243. }
  244. }
  245. return new ResolvedMember(kind,
  246. TypeX.forName(mg.getClassName()),
  247. mods,
  248. fromBcel(mg.getReturnType()),
  249. mg.getName(),
  250. fromBcel(mg.getArgumentTypes())
  251. );
  252. } else {
  253. return ret;
  254. }
  255. }
  256. public static Member makeMethodSignature(LazyClassGen cg, InvokeInstruction ii) {
  257. ConstantPoolGen cpg = cg.getConstantPoolGen();
  258. String declaring = ii.getClassName(cpg);
  259. String name = ii.getName(cpg);
  260. String signature = ii.getSignature(cpg);
  261. int modifier =
  262. (ii instanceof INVOKEINTERFACE)
  263. ? Modifier.INTERFACE
  264. : (ii instanceof INVOKESTATIC)
  265. ? Modifier.STATIC
  266. : (ii instanceof INVOKESPECIAL && ! name.equals("<init>"))
  267. ? Modifier.PRIVATE
  268. : 0;
  269. return Member.method(TypeX.forName(declaring), modifier, name, signature);
  270. }
  271. public static Member makeMungerMethodSignature(JavaClass javaClass, Method method) {
  272. int mods = 0;
  273. if (method.isStatic()) mods = Modifier.STATIC;
  274. else if (javaClass.isInterface()) mods = Modifier.INTERFACE;
  275. else if (method.isPrivate()) mods = Modifier.PRIVATE;
  276. return Member.method(
  277. TypeX.forName(javaClass.getClassName()), mods, method.getName(), method.getSignature());
  278. }
  279. private static final String[] ZERO_STRINGS = new String[0];
  280. public String toString() {
  281. StringBuffer buf = new StringBuffer();
  282. buf.append("BcelWorld(");
  283. //buf.append(shadowMungerMap);
  284. buf.append(")");
  285. return buf.toString();
  286. }
  287. public Advice concreteAdvice(
  288. AjAttribute.AdviceAttribute attribute,
  289. Pointcut pointcut,
  290. Member signature)
  291. {
  292. //System.err.println("concrete advice: " + signature + " context " + sourceContext);
  293. return new BcelAdvice(attribute, pointcut, signature, null);
  294. }
  295. public ConcreteTypeMunger concreteTypeMunger(
  296. ResolvedTypeMunger munger, ResolvedTypeX aspectType)
  297. {
  298. return new BcelTypeMunger(munger, aspectType);
  299. }
  300. public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
  301. return new BcelCflowStackFieldAdder(cflowField);
  302. }
  303. public static BcelObjectType getBcelObjectType(ResolvedTypeX concreteAspect) {
  304. //XXX need error checking
  305. return (BcelObjectType) ((ResolvedTypeX.Name)concreteAspect).getDelegate();
  306. }
  307. }