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 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  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. * Alexandre Vasseur perClause support for @AJ aspects
  12. * ******************************************************************/
  13. package org.aspectj.weaver.bcel;
  14. import java.io.ByteArrayInputStream;
  15. import java.io.File;
  16. import java.io.IOException;
  17. import java.lang.reflect.Modifier;
  18. import java.util.ArrayList;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.Properties;
  22. import java.util.StringTokenizer;
  23. import org.aspectj.apache.bcel.classfile.Attribute;
  24. import org.aspectj.apache.bcel.classfile.ClassParser;
  25. import org.aspectj.apache.bcel.classfile.JavaClass;
  26. import org.aspectj.apache.bcel.classfile.Method;
  27. import org.aspectj.apache.bcel.classfile.annotation.Annotation;
  28. import org.aspectj.apache.bcel.generic.ANEWARRAY;
  29. import org.aspectj.apache.bcel.generic.ConstantPoolGen;
  30. import org.aspectj.apache.bcel.generic.FieldInstruction;
  31. import org.aspectj.apache.bcel.generic.GETSTATIC;
  32. import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
  33. import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
  34. import org.aspectj.apache.bcel.generic.INVOKESTATIC;
  35. import org.aspectj.apache.bcel.generic.Instruction;
  36. import org.aspectj.apache.bcel.generic.InstructionHandle;
  37. import org.aspectj.apache.bcel.generic.InvokeInstruction;
  38. import org.aspectj.apache.bcel.generic.MONITORENTER;
  39. import org.aspectj.apache.bcel.generic.MONITOREXIT;
  40. import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
  41. import org.aspectj.apache.bcel.generic.NEWARRAY;
  42. import org.aspectj.apache.bcel.generic.ObjectType;
  43. import org.aspectj.apache.bcel.generic.PUTSTATIC;
  44. import org.aspectj.apache.bcel.generic.Type;
  45. import org.aspectj.apache.bcel.util.ClassLoaderRepository;
  46. import org.aspectj.apache.bcel.util.ClassPath;
  47. import org.aspectj.apache.bcel.util.Repository;
  48. import org.aspectj.bridge.IMessageHandler;
  49. import org.aspectj.weaver.Advice;
  50. import org.aspectj.weaver.AdviceKind;
  51. import org.aspectj.weaver.AjAttribute;
  52. import org.aspectj.weaver.AnnotationOnTypeMunger;
  53. import org.aspectj.weaver.AnnotationX;
  54. import org.aspectj.weaver.BCException;
  55. import org.aspectj.weaver.ConcreteTypeMunger;
  56. import org.aspectj.weaver.ICrossReferenceHandler;
  57. import org.aspectj.weaver.Member;
  58. import org.aspectj.weaver.MemberImpl;
  59. import org.aspectj.weaver.NewParentTypeMunger;
  60. import org.aspectj.weaver.ReferenceType;
  61. import org.aspectj.weaver.ReferenceTypeDelegate;
  62. import org.aspectj.weaver.ResolvedMember;
  63. import org.aspectj.weaver.ResolvedMemberImpl;
  64. import org.aspectj.weaver.ResolvedType;
  65. import org.aspectj.weaver.ResolvedTypeMunger;
  66. import org.aspectj.weaver.UnresolvedType;
  67. import org.aspectj.weaver.World;
  68. import org.aspectj.weaver.AjAttribute.Aspect;
  69. import org.aspectj.weaver.asm.AsmDelegate;
  70. import org.aspectj.weaver.patterns.DeclareAnnotation;
  71. import org.aspectj.weaver.patterns.DeclareParents;
  72. import org.aspectj.weaver.patterns.FormalBinding;
  73. import org.aspectj.weaver.patterns.PerClause;
  74. import org.aspectj.weaver.patterns.Pointcut;
  75. import org.aspectj.weaver.patterns.SimpleScope;
  76. public class BcelWorld extends World implements Repository {
  77. private ClassPathManager classPath;
  78. protected Repository delegate;
  79. //private ClassPathManager aspectPath = null;
  80. // private List aspectPathEntries;
  81. // ---- constructors
  82. public BcelWorld() {
  83. this("");
  84. }
  85. public BcelWorld(String cp) {
  86. this(makeDefaultClasspath(cp), IMessageHandler.THROW, null);
  87. }
  88. private static List makeDefaultClasspath(String cp) {
  89. List classPath = new ArrayList();
  90. classPath.addAll(getPathEntries(cp));
  91. classPath.addAll(getPathEntries(ClassPath.getClassPath()));
  92. //System.err.println("classpath: " + classPath);
  93. return classPath;
  94. }
  95. private static List getPathEntries(String s) {
  96. List ret = new ArrayList();
  97. StringTokenizer tok = new StringTokenizer(s, File.pathSeparator);
  98. while(tok.hasMoreTokens()) ret.add(tok.nextToken());
  99. return ret;
  100. }
  101. public BcelWorld(List classPath, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  102. //this.aspectPath = new ClassPathManager(aspectPath, handler);
  103. this.classPath = new ClassPathManager(classPath, handler);
  104. setMessageHandler(handler);
  105. setCrossReferenceHandler(xrefHandler);
  106. // Tell BCEL to use us for resolving any classes
  107. delegate = this;
  108. // TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
  109. // if so, how can that be safe in J2EE ?? (static stuff in Bcel)
  110. }
  111. public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  112. this.classPath = cpm;
  113. setMessageHandler(handler);
  114. setCrossReferenceHandler(xrefHandler);
  115. // Tell BCEL to use us for resolving any classes
  116. delegate = this;
  117. // TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
  118. // if so, how can that be safe in J2EE ?? (static stuff in Bcel)
  119. }
  120. /**
  121. * Build a World from a ClassLoader, for LTW support
  122. *
  123. * @param loader
  124. * @param handler
  125. * @param xrefHandler
  126. */
  127. public BcelWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  128. this.classPath = null;
  129. setMessageHandler(handler);
  130. setCrossReferenceHandler(xrefHandler);
  131. // Tell BCEL to use us for resolving any classes
  132. delegate = new ClassLoaderRepository(loader);
  133. // TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
  134. // if so, how can that be safe in J2EE ?? (static stuff in Bcel)
  135. }
  136. public void addPath (String name) {
  137. classPath.addPath(name, this.getMessageHandler());
  138. }
  139. /**
  140. * Parse a string into advice.
  141. *
  142. * <blockquote><pre>
  143. * Kind ( Id , ... ) : Pointcut -> MethodSignature
  144. * </pre></blockquote>
  145. */
  146. public Advice shadowMunger(String str, int extraFlag) {
  147. str = str.trim();
  148. int start = 0;
  149. int i = str.indexOf('(');
  150. AdviceKind kind =
  151. AdviceKind.stringToKind(str.substring(start, i));
  152. start = ++i;
  153. i = str.indexOf(')', i);
  154. String[] ids = parseIds(str.substring(start, i).trim());
  155. //start = ++i;
  156. i = str.indexOf(':', i);
  157. start = ++i;
  158. i = str.indexOf("->", i);
  159. Pointcut pointcut = Pointcut.fromString(str.substring(start, i).trim());
  160. Member m = MemberImpl.methodFromString(str.substring(i+2, str.length()).trim());
  161. // now, we resolve
  162. UnresolvedType[] types = m.getParameterTypes();
  163. FormalBinding[] bindings = new FormalBinding[ids.length];
  164. for (int j = 0, len = ids.length; j < len; j++) {
  165. bindings[j] = new FormalBinding(types[j], ids[j], j, 0, 0, "fromString");
  166. }
  167. Pointcut p =
  168. pointcut.resolve(new SimpleScope(this, bindings));
  169. return new BcelAdvice(kind, p, m, extraFlag, 0, 0, null, null);
  170. }
  171. private String[] parseIds(String str) {
  172. if (str.length() == 0) return ZERO_STRINGS;
  173. List l = new ArrayList();
  174. int start = 0;
  175. while (true) {
  176. int i = str.indexOf(',', start);
  177. if (i == -1) {
  178. l.add(str.substring(start).trim());
  179. break;
  180. }
  181. l.add(str.substring(start, i).trim());
  182. start = i+1;
  183. }
  184. return (String[]) l.toArray(new String[l.size()]);
  185. }
  186. // ---- various interactions with bcel
  187. public static Type makeBcelType(UnresolvedType type) {
  188. return Type.getType(type.getErasureSignature());
  189. }
  190. static Type[] makeBcelTypes(UnresolvedType[] types) {
  191. Type[] ret = new Type[types.length];
  192. for (int i = 0, len = types.length; i < len; i++) {
  193. ret[i] = makeBcelType(types[i]);
  194. }
  195. return ret;
  196. }
  197. static String[] makeBcelTypesAsClassNames(UnresolvedType[] types) {
  198. String[] ret = new String[types.length];
  199. for (int i = 0, len = types.length; i < len; i++) {
  200. ret[i] = types[i].getName();
  201. }
  202. return ret;
  203. }
  204. public static UnresolvedType fromBcel(Type t) {
  205. return UnresolvedType.forSignature(t.getSignature());
  206. }
  207. static UnresolvedType[] fromBcel(Type[] ts) {
  208. UnresolvedType[] ret = new UnresolvedType[ts.length];
  209. for (int i = 0, len = ts.length; i < len; i++) {
  210. ret[i] = fromBcel(ts[i]);
  211. }
  212. return ret;
  213. }
  214. public ResolvedType resolve(Type t) {
  215. return resolve(fromBcel(t));
  216. }
  217. // SECRETAPI: used for testing ASM loading of delegates...
  218. public boolean fallbackToLoadingBcelDelegatesForAspects = true;
  219. private int packageRestrictionsForFastDelegates = 0; // 0=dontknow 1=no 2=yes
  220. private List packagePrefixRestrictionList = null;
  221. public boolean isNotOnPackageRestrictedList(String s) {
  222. if (packageRestrictionsForFastDelegates==0) {
  223. Properties p = getExtraConfiguration();
  224. String possiblePackageRestrictions = (p==null?null:p.getProperty("fastDelegateRestrictions"));
  225. if (possiblePackageRestrictions==null) {
  226. packageRestrictionsForFastDelegates=1;
  227. } else {
  228. packageRestrictionsForFastDelegates=2;
  229. packagePrefixRestrictionList=new ArrayList();
  230. StringTokenizer st = new StringTokenizer(possiblePackageRestrictions,":");
  231. while (st.hasMoreTokens()) {
  232. packagePrefixRestrictionList.add(st.nextToken());
  233. }
  234. }
  235. }
  236. if (packageRestrictionsForFastDelegates==1) return true;
  237. if (packageRestrictionsForFastDelegates==2) {
  238. for (Iterator iter = packagePrefixRestrictionList.iterator(); iter.hasNext();) {
  239. String element = (String) iter.next();
  240. if (s.startsWith(element)) {
  241. // System.err.println("Not creating fast delegate for "+s);
  242. return false;
  243. }
  244. }
  245. }
  246. return true;
  247. }
  248. protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
  249. String name = ty.getName();
  250. JavaClass jc = null;
  251. ensureAdvancedConfigurationProcessed();
  252. //UnwovenClassFile classFile = (UnwovenClassFile)sourceJavaClasses.get(name);
  253. //if (classFile != null) jc = classFile.getJavaClass();
  254. if (isFastDelegateSupportEnabled() && classPath!=null && !ty.needsModifiableDelegate() && isNotOnPackageRestrictedList(name)) {
  255. ClassPathManager.ClassFile cf = classPath.find(ty);
  256. if (cf==null) {
  257. return null;
  258. } else {
  259. ReferenceTypeDelegate delegate = buildAsmDelegate(ty,cf);
  260. if (fallbackToLoadingBcelDelegatesForAspects && delegate.isAspect()) {
  261. // bugger - pr135001 - we can't inline around advice from an aspect because we don't load the instructions.
  262. // fixing this quick to get AJDT upgraded with a good 1.5.2dev build.
  263. // other fixes would be:
  264. // 1. record that we are loading the superclass for an aspect, so we know to make it a BCEL delegate
  265. //
  266. // the 'fix' here is only reasonable because there are many less aspects than classes!
  267. // Create a BCEL delegate
  268. if (jc == null) jc = lookupJavaClass(classPath, name);
  269. if (jc == null) return delegate; // worrying situation ?!?
  270. else return buildBcelDelegate(ty, jc, false);
  271. } else {
  272. return delegate;
  273. }
  274. }
  275. } else {
  276. if (jc == null) {
  277. jc = lookupJavaClass(classPath, name);
  278. }
  279. if (jc == null) {
  280. return null;
  281. } else {
  282. return buildBcelDelegate(ty, jc, false);
  283. }
  284. }
  285. }
  286. private ReferenceTypeDelegate buildAsmDelegate(ReferenceType type,ClassPathManager.ClassFile t) {
  287. AsmDelegate asmDelegate;
  288. try {
  289. asmDelegate = new AsmDelegate(type,t.getInputStream());
  290. } catch (IOException e) {
  291. e.printStackTrace();
  292. return null;
  293. }
  294. return asmDelegate;
  295. }
  296. public BcelObjectType buildBcelDelegate(ReferenceType resolvedTypeX, JavaClass jc, boolean exposedToWeaver) {
  297. BcelObjectType ret = new BcelObjectType(resolvedTypeX, jc, exposedToWeaver);
  298. return ret;
  299. }
  300. private JavaClass lookupJavaClass(ClassPathManager classPath, String name) {
  301. if (classPath == null) {
  302. try {
  303. return delegate.loadClass(name);
  304. } catch (ClassNotFoundException e) {
  305. return null;
  306. }
  307. }
  308. try {
  309. ClassPathManager.ClassFile file = classPath.find(UnresolvedType.forName(name));
  310. if (file == null) return null;
  311. ClassParser parser = new ClassParser(file.getInputStream(), file.getPath());
  312. JavaClass jc = parser.parse();
  313. file.close();
  314. return jc;
  315. } catch (IOException ioe) {
  316. return null;
  317. }
  318. }
  319. public BcelObjectType addSourceObjectType(JavaClass jc) {
  320. BcelObjectType ret = null;
  321. String signature = UnresolvedType.forName(jc.getClassName()).getSignature();
  322. Object fromTheMap = typeMap.get(signature);
  323. if (fromTheMap!=null && !(fromTheMap instanceof ReferenceType)) {
  324. // what on earth is it then? See pr 112243
  325. StringBuffer exceptionText = new StringBuffer();
  326. exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. ");
  327. exceptionText.append("Signature=["+signature+"] Found=["+fromTheMap+"] Class=["+fromTheMap.getClass()+"]");
  328. throw new BCException(exceptionText.toString());
  329. }
  330. ReferenceType nameTypeX = (ReferenceType)fromTheMap;
  331. if (nameTypeX == null) {
  332. if (jc.isGeneric() && isInJava5Mode()) {
  333. nameTypeX = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()),this);
  334. ret = buildBcelDelegate(nameTypeX, jc, true);
  335. ReferenceType genericRefType = new ReferenceType(
  336. UnresolvedType.forGenericTypeSignature(signature,ret.getDeclaredGenericSignature()),this);
  337. nameTypeX.setDelegate(ret);
  338. genericRefType.setDelegate(ret);
  339. nameTypeX.setGenericType(genericRefType);
  340. typeMap.put(signature, nameTypeX);
  341. } else {
  342. nameTypeX = new ReferenceType(signature, this);
  343. ret = buildBcelDelegate(nameTypeX, jc, true);
  344. typeMap.put(signature, nameTypeX);
  345. }
  346. } else {
  347. ret = buildBcelDelegate(nameTypeX, jc, true);
  348. }
  349. return ret;
  350. }
  351. void deleteSourceObjectType(UnresolvedType ty) {
  352. typeMap.remove(ty.getSignature());
  353. }
  354. public static Member makeFieldJoinPointSignature(LazyClassGen cg, FieldInstruction fi) {
  355. ConstantPoolGen cpg = cg.getConstantPoolGen();
  356. return
  357. MemberImpl.field(
  358. fi.getClassName(cpg),
  359. (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
  360. ? Modifier.STATIC: 0,
  361. fi.getName(cpg),
  362. fi.getSignature(cpg));
  363. }
  364. // public static Member makeFieldSetSignature(LazyClassGen cg, FieldInstruction fi) {
  365. // ConstantPoolGen cpg = cg.getConstantPoolGen();
  366. // return
  367. // MemberImpl.field(
  368. // fi.getClassName(cpg),
  369. // (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
  370. // ? Modifier.STATIC
  371. // : 0,
  372. // fi.getName(cpg),
  373. // "(" + fi.getSignature(cpg) + ")" +fi.getSignature(cpg));
  374. // }
  375. public Member makeJoinPointSignature(LazyMethodGen mg) {
  376. return makeJoinPointSignatureFromMethod(mg, null);
  377. }
  378. public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberImpl.Kind kind) {
  379. Member ret = mg.getMemberView();
  380. if (ret == null) {
  381. int mods = mg.getAccessFlags();
  382. if (mg.getEnclosingClass().isInterface()) {
  383. mods |= Modifier.INTERFACE;
  384. }
  385. if (kind == null) {
  386. if (mg.getName().equals("<init>")) {
  387. kind = Member.CONSTRUCTOR;
  388. } else if (mg.getName().equals("<clinit>")) {
  389. kind = Member.STATIC_INITIALIZATION;
  390. } else {
  391. kind = Member.METHOD;
  392. }
  393. }
  394. return new ResolvedMemberImpl(kind,
  395. UnresolvedType.forName(mg.getClassName()),
  396. mods,
  397. fromBcel(mg.getReturnType()),
  398. mg.getName(),
  399. fromBcel(mg.getArgumentTypes())
  400. );
  401. } else {
  402. return ret;
  403. }
  404. }
  405. public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg,InstructionHandle h) {
  406. MONITORENTER i = (MONITORENTER)h.getInstruction();
  407. return MemberImpl.monitorEnter();
  408. }
  409. public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg,InstructionHandle h) {
  410. MONITOREXIT i = (MONITOREXIT)h.getInstruction();
  411. return MemberImpl.monitorExit();
  412. }
  413. public Member makeJoinPointSignatureForArrayConstruction(LazyClassGen cg, InstructionHandle handle) {
  414. Instruction i = handle.getInstruction();
  415. ConstantPoolGen cpg = cg.getConstantPoolGen();
  416. Member retval = null;
  417. if (i instanceof ANEWARRAY) {
  418. ANEWARRAY arrayInstruction = (ANEWARRAY)i;
  419. Type ot = arrayInstruction.getType(cpg);
  420. UnresolvedType ut = fromBcel(ot);
  421. ut = UnresolvedType.makeArray(ut,1);
  422. retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", new ResolvedType[]{ResolvedType.INT});
  423. } else if (i instanceof MULTIANEWARRAY) {
  424. MULTIANEWARRAY arrayInstruction = (MULTIANEWARRAY)i;
  425. UnresolvedType ut = null;
  426. short dimensions = arrayInstruction.getDimensions();
  427. ObjectType ot = arrayInstruction.getLoadClassType(cpg);
  428. if (ot!=null) {
  429. ut = fromBcel(ot);
  430. ut = UnresolvedType.makeArray(ut,dimensions);
  431. } else {
  432. Type t = arrayInstruction.getType(cpg);
  433. ut = fromBcel(t);
  434. }
  435. ResolvedType[] parms = new ResolvedType[dimensions];
  436. for (int ii=0;ii<dimensions;ii++) parms[ii] = ResolvedType.INT;
  437. retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", parms);
  438. } else if (i instanceof NEWARRAY) {
  439. NEWARRAY arrayInstruction = (NEWARRAY)i;
  440. Type ot = arrayInstruction.getType();
  441. UnresolvedType ut = fromBcel(ot);
  442. retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", new ResolvedType[]{ResolvedType.INT});
  443. } else {
  444. throw new BCException("Cannot create array construction signature for this non-array instruction:"+i);
  445. }
  446. return retval;
  447. }
  448. public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, InvokeInstruction ii) {
  449. ConstantPoolGen cpg = cg.getConstantPoolGen();
  450. String name = ii.getName(cpg);
  451. String declaring = ii.getClassName(cpg);
  452. UnresolvedType declaringType = null;
  453. String signature = ii.getSignature(cpg);
  454. int modifier =
  455. (ii instanceof INVOKEINTERFACE)
  456. ? Modifier.INTERFACE
  457. : (ii instanceof INVOKESTATIC)
  458. ? Modifier.STATIC
  459. : (ii instanceof INVOKESPECIAL && ! name.equals("<init>"))
  460. ? Modifier.PRIVATE
  461. : 0;
  462. // in Java 1.4 and after, static method call of super class within subclass method appears
  463. // as declared by the subclass in the bytecode - but they are not
  464. // see #104212
  465. if (ii instanceof INVOKESTATIC) {
  466. ResolvedType appearsDeclaredBy = resolve(declaring);
  467. // look for the method there
  468. for (Iterator iterator = appearsDeclaredBy.getMethods(); iterator.hasNext();) {
  469. ResolvedMember method = (ResolvedMember) iterator.next();
  470. if (method.isStatic()) {
  471. if (name.equals(method.getName()) && signature.equals(method.getSignature())) {
  472. // we found it
  473. declaringType = method.getDeclaringType();
  474. break;
  475. }
  476. }
  477. }
  478. }
  479. if (declaringType == null) {
  480. if (declaring.charAt(0)=='[') declaringType = UnresolvedType.forSignature(declaring);
  481. else declaringType = UnresolvedType.forName(declaring);
  482. }
  483. return MemberImpl.method(declaringType, modifier, name, signature);
  484. }
  485. public static Member makeMungerMethodSignature(JavaClass javaClass, Method method) {
  486. int mods = 0;
  487. if (method.isStatic()) mods = Modifier.STATIC;
  488. else if (javaClass.isInterface()) mods = Modifier.INTERFACE;
  489. else if (method.isPrivate()) mods = Modifier.PRIVATE;
  490. return MemberImpl.method(
  491. UnresolvedType.forName(javaClass.getClassName()), mods, method.getName(), method.getSignature());
  492. }
  493. private static final String[] ZERO_STRINGS = new String[0];
  494. public String toString() {
  495. StringBuffer buf = new StringBuffer();
  496. buf.append("BcelWorld(");
  497. //buf.append(shadowMungerMap);
  498. buf.append(")");
  499. return buf.toString();
  500. }
  501. public Advice createAdviceMunger(
  502. AjAttribute.AdviceAttribute attribute,
  503. Pointcut pointcut,
  504. Member signature)
  505. {
  506. //System.err.println("concrete advice: " + signature + " context " + sourceContext);
  507. return new BcelAdvice(attribute, pointcut, signature, null);
  508. }
  509. public ConcreteTypeMunger concreteTypeMunger(
  510. ResolvedTypeMunger munger, ResolvedType aspectType)
  511. {
  512. return new BcelTypeMunger(munger, aspectType);
  513. }
  514. public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
  515. return new BcelCflowStackFieldAdder(cflowField);
  516. }
  517. public ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField) {
  518. return new BcelCflowCounterFieldAdder(cflowField);
  519. }
  520. /**
  521. * Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed
  522. *
  523. * @param aspect
  524. * @param kind
  525. * @return munger
  526. */
  527. public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind) {
  528. return new BcelPerClauseAspectAdder(aspect, kind);
  529. }
  530. /**
  531. * Retrieve a bcel delegate for an aspect - this will return NULL if the
  532. * delegate is an EclipseSourceType and not a BcelObjectType - this happens
  533. * quite often when incrementally compiling.
  534. */
  535. public static BcelObjectType getBcelObjectType(ResolvedType concreteAspect) {
  536. ReferenceTypeDelegate rtDelegate = ((ReferenceType)concreteAspect).getDelegate();
  537. if (rtDelegate instanceof BcelObjectType) {
  538. return (BcelObjectType)rtDelegate;
  539. } else {
  540. return null;
  541. }
  542. }
  543. public void tidyUp() {
  544. // At end of compile, close any open files so deletion of those archives is possible
  545. classPath.closeArchives();
  546. typeMap.report();
  547. ResolvedType.resetPrimitives();
  548. }
  549. /// The repository interface methods
  550. public JavaClass findClass(String className) {
  551. return lookupJavaClass(classPath,className);
  552. }
  553. public JavaClass loadClass(String className) throws ClassNotFoundException {
  554. return lookupJavaClass(classPath,className);
  555. }
  556. public void storeClass(JavaClass clazz) {
  557. // doesn't need to do anything
  558. }
  559. public void removeClass(JavaClass clazz) {
  560. throw new RuntimeException("Not implemented");
  561. }
  562. public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
  563. throw new RuntimeException("Not implemented");
  564. }
  565. public void clear() {
  566. throw new RuntimeException("Not implemented");
  567. }
  568. // @Override
  569. /**
  570. * The aim of this method is to make sure a particular type is 'ok'. Some
  571. * operations on the delegate for a type modify it and this method is
  572. * intended to undo that... see pr85132
  573. */
  574. public void validateType(UnresolvedType type) {
  575. ResolvedType result = typeMap.get(type.getSignature());
  576. if (result==null) return; // We haven't heard of it yet
  577. if (!result.isExposedToWeaver()) return; // cant need resetting
  578. ReferenceType rt = (ReferenceType)result;
  579. rt.getDelegate().ensureDelegateConsistent();
  580. // If we want to rebuild it 'from scratch' then:
  581. // ClassParser cp = new ClassParser(new ByteArrayInputStream(newbytes),new String(cs));
  582. // try {
  583. // rt.setDelegate(makeBcelObjectType(rt,cp.parse(),true));
  584. // } catch (ClassFormatException e) {
  585. // e.printStackTrace();
  586. // } catch (IOException e) {
  587. // e.printStackTrace();
  588. // }
  589. }
  590. /**
  591. * Checks if given bytecode is an @AspectJ aspect
  592. *
  593. * @param name
  594. * @param bytes
  595. * @return true if so
  596. */
  597. public boolean isAnnotationStyleAspect(String name, byte[] bytes) {
  598. try {
  599. ClassParser cp = new ClassParser(new ByteArrayInputStream(bytes), null);
  600. JavaClass jc = cp.parse();
  601. if (!jc.isClass()) {
  602. return false;
  603. }
  604. Annotation anns[] = jc.getAnnotations();
  605. if (anns.length == 0) {
  606. return false;
  607. }
  608. boolean couldBeAtAspectJStyle = false;
  609. for (int i = 0; i < anns.length; i++) {
  610. Annotation ann = anns[i];
  611. if ("Lorg/aspectj/lang/annotation/Aspect;".equals(ann.getTypeSignature())) {
  612. couldBeAtAspectJStyle = true;
  613. }
  614. }
  615. if (!couldBeAtAspectJStyle) return false;
  616. // ok, so it has the annotation, but it could have been put
  617. // on a code style aspect by the annotation visitor
  618. Attribute[] attributes = jc.getAttributes();
  619. for (int i = 0; i < attributes.length; i++) {
  620. if (attributes[i].getName().equals(Aspect.AttributeName)) {
  621. return false;
  622. }
  623. }
  624. return true;
  625. } catch (IOException e) {
  626. // assume it is one as a best effort
  627. return true;
  628. }
  629. }
  630. /**
  631. * Apply a single declare parents - return true if we change the type
  632. */
  633. private boolean applyDeclareParents(DeclareParents p, ResolvedType onType) {
  634. boolean didSomething = false;
  635. List newParents = p.findMatchingNewParents(onType,true);
  636. if (!newParents.isEmpty()) {
  637. didSomething=true;
  638. BcelObjectType classType = BcelWorld.getBcelObjectType(onType);
  639. //System.err.println("need to do declare parents for: " + onType);
  640. for (Iterator j = newParents.iterator(); j.hasNext(); ) {
  641. ResolvedType newParent = (ResolvedType)j.next();
  642. // We set it here so that the imminent matching for ITDs can succeed - we
  643. // still haven't done the necessary changes to the class file itself
  644. // (like transform super calls) - that is done in BcelTypeMunger.mungeNewParent()
  645. classType.addParent(newParent);
  646. ResolvedTypeMunger newParentMunger = new NewParentTypeMunger(newParent);
  647. newParentMunger.setSourceLocation(p.getSourceLocation());
  648. onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, getCrosscuttingMembersSet().findAspectDeclaringParents(p)));
  649. }
  650. }
  651. return didSomething;
  652. }
  653. /**
  654. * Apply a declare @type - return true if we change the type
  655. */
  656. private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType,boolean reportProblems) {
  657. boolean didSomething = false;
  658. if (decA.matches(onType)) {
  659. if (onType.hasAnnotation(decA.getAnnotationX().getSignature())) {
  660. // already has it
  661. return false;
  662. }
  663. AnnotationX annoX = decA.getAnnotationX();
  664. // check the annotation is suitable for the target
  665. boolean isOK = checkTargetOK(decA,onType,annoX);
  666. if (isOK) {
  667. didSomething = true;
  668. ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX);
  669. newAnnotationTM.setSourceLocation(decA.getSourceLocation());
  670. onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM,decA.getAspect().resolve(this)));
  671. decA.copyAnnotationTo(onType);
  672. }
  673. }
  674. return didSomething;
  675. }
  676. /**
  677. * Checks for an @target() on the annotation and if found ensures it allows the annotation
  678. * to be attached to the target type that matched.
  679. */
  680. private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, AnnotationX annoX) {
  681. if (annoX.specifiesTarget()) {
  682. if ( (onType.isAnnotation() && !annoX.allowedOnAnnotationType()) ||
  683. (!annoX.allowedOnRegularType())) {
  684. return false;
  685. }
  686. }
  687. return true;
  688. }
  689. // Hmmm - very similar to the code in BcelWeaver.weaveParentTypeMungers - this code
  690. // doesn't need to produce errors/warnings though as it won't really be weaving.
  691. protected void weaveInterTypeDeclarations(ResolvedType onType) {
  692. List declareParentsList = getCrosscuttingMembersSet().getDeclareParents();
  693. if (onType.isRawType()) onType = onType.getGenericType();
  694. onType.clearInterTypeMungers();
  695. List decpToRepeat = new ArrayList();
  696. boolean aParentChangeOccurred = false;
  697. boolean anAnnotationChangeOccurred = false;
  698. // First pass - apply all decp mungers
  699. for (Iterator i = declareParentsList.iterator(); i.hasNext(); ) {
  700. DeclareParents decp = (DeclareParents)i.next();
  701. boolean typeChanged = applyDeclareParents(decp,onType);
  702. if (typeChanged) {
  703. aParentChangeOccurred = true;
  704. } else { // Perhaps it would have matched if a 'dec @type' had modified the type
  705. if (!decp.getChild().isStarAnnotation()) decpToRepeat.add(decp);
  706. }
  707. }
  708. // Still first pass - apply all dec @type mungers
  709. for (Iterator i = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator();i.hasNext();) {
  710. DeclareAnnotation decA = (DeclareAnnotation)i.next();
  711. boolean typeChanged = applyDeclareAtType(decA,onType,true);
  712. if (typeChanged) {
  713. anAnnotationChangeOccurred = true;
  714. }
  715. }
  716. while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) {
  717. anAnnotationChangeOccurred = aParentChangeOccurred = false;
  718. List decpToRepeatNextTime = new ArrayList();
  719. for (Iterator iter = decpToRepeat.iterator(); iter.hasNext();) {
  720. DeclareParents decp = (DeclareParents) iter.next();
  721. boolean typeChanged = applyDeclareParents(decp,onType);
  722. if (typeChanged) {
  723. aParentChangeOccurred = true;
  724. } else {
  725. decpToRepeatNextTime.add(decp);
  726. }
  727. }
  728. for (Iterator iter = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator(); iter.hasNext();) {
  729. DeclareAnnotation decA = (DeclareAnnotation) iter.next();
  730. boolean typeChanged = applyDeclareAtType(decA,onType,false);
  731. if (typeChanged) {
  732. anAnnotationChangeOccurred = true;
  733. }
  734. }
  735. decpToRepeat = decpToRepeatNextTime;
  736. }
  737. }
  738. }