Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

BcelTypeMunger.java 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  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.bcel;
  13. import java.lang.reflect.Modifier;
  14. import java.util.*;
  15. import org.apache.bcel.Constants;
  16. import org.apache.bcel.generic.*;
  17. import org.aspectj.weaver.*;
  18. import org.aspectj.weaver.patterns.*;
  19. //XXX addLazyMethodGen is probably bad everywhere
  20. public class BcelTypeMunger extends ConcreteTypeMunger {
  21. public BcelTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType) {
  22. super(munger, aspectType);
  23. }
  24. public String toString() {
  25. return "(BcelTypeMunger " + getMunger() + ")";
  26. }
  27. public boolean munge(BcelClassWeaver weaver) {
  28. if (munger.getKind() == ResolvedTypeMunger.Field) {
  29. return mungeNewField(weaver, (NewFieldTypeMunger)munger);
  30. } else if (munger.getKind() == ResolvedTypeMunger.Method) {
  31. return mungeNewMethod(weaver, (NewMethodTypeMunger)munger);
  32. } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
  33. return mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger);
  34. } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
  35. return mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger);
  36. } else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
  37. return mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger);
  38. } else {
  39. throw new RuntimeException("unimplemented");
  40. }
  41. }
  42. private boolean mungePrivilegedAccess(
  43. BcelClassWeaver weaver,
  44. PrivilegedAccessMunger munger)
  45. {
  46. LazyClassGen gen = weaver.getLazyClassGen();
  47. ResolvedMember member = munger.getMember();
  48. ResolvedTypeX onType = weaver.getWorld().resolve(member.getDeclaringType());
  49. //System.out.println("munging: " + gen + " with " + member);
  50. if (onType.equals(gen.getType())) {
  51. if (member.getKind() == Member.FIELD) {
  52. //System.out.println("matched: " + gen);
  53. addFieldGetter(gen, member,
  54. AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member));
  55. addFieldSetter(gen, member,
  56. AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member));
  57. return true;
  58. } else if (member.getKind() == Member.METHOD) {
  59. addMethodDispatch(gen, member,
  60. AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
  61. return true;
  62. } else if (member.getKind() == Member.STATIC_INITIALIZATION) {
  63. gen.forcePublic();
  64. return true;
  65. } else {
  66. throw new RuntimeException("unimplemented");
  67. }
  68. }
  69. return false;
  70. }
  71. private void addFieldGetter(
  72. LazyClassGen gen,
  73. ResolvedMember field,
  74. ResolvedMember accessMethod)
  75. {
  76. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  77. InstructionList il = new InstructionList();
  78. InstructionFactory fact = gen.getFactory();
  79. if (field.isStatic()) {
  80. il.append(fact.createFieldAccess(
  81. gen.getClassName(),
  82. field.getName(),
  83. BcelWorld.makeBcelType(field.getType()), Constants.GETSTATIC));
  84. } else {
  85. il.append(fact.ALOAD_0);
  86. il.append(fact.createFieldAccess(
  87. gen.getClassName(),
  88. field.getName(),
  89. BcelWorld.makeBcelType(field.getType()), Constants.GETFIELD));
  90. }
  91. il.append(fact.createReturn(BcelWorld.makeBcelType(field.getType())));
  92. mg.getBody().insert(il);
  93. gen.addMethodGen(mg);
  94. }
  95. private void addFieldSetter(
  96. LazyClassGen gen,
  97. ResolvedMember field,
  98. ResolvedMember accessMethod)
  99. {
  100. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  101. InstructionList il = new InstructionList();
  102. InstructionFactory fact = gen.getFactory();
  103. Type fieldType = BcelWorld.makeBcelType(field.getType());
  104. if (field.isStatic()) {
  105. il.append(fact.createLoad(fieldType, 0));
  106. il.append(fact.createFieldAccess(
  107. gen.getClassName(),
  108. field.getName(),
  109. fieldType, Constants.PUTSTATIC));
  110. } else {
  111. il.append(fact.ALOAD_0);
  112. il.append(fact.createLoad(fieldType, 1));
  113. il.append(fact.createFieldAccess(
  114. gen.getClassName(),
  115. field.getName(),
  116. fieldType, Constants.PUTFIELD));
  117. }
  118. il.append(fact.createReturn(Type.VOID));
  119. mg.getBody().insert(il);
  120. gen.addMethodGen(mg);
  121. }
  122. private void addMethodDispatch(
  123. LazyClassGen gen,
  124. ResolvedMember method,
  125. ResolvedMember accessMethod)
  126. {
  127. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  128. InstructionList il = new InstructionList();
  129. InstructionFactory fact = gen.getFactory();
  130. //Type fieldType = BcelWorld.makeBcelType(field.getType());
  131. Type[] paramTypes = BcelWorld.makeBcelTypes(method.getParameterTypes());
  132. int pos = 0;
  133. if (!method.isStatic()) {
  134. il.append(fact.ALOAD_0);
  135. pos++;
  136. }
  137. for (int i = 0, len = paramTypes.length; i < len; i++) {
  138. Type paramType = paramTypes[i];
  139. il.append(fact.createLoad(paramType, pos));
  140. pos+=paramType.getSize();
  141. }
  142. il.append(Utility.createInvoke(fact, (BcelWorld)aspectType.getWorld(),
  143. method));
  144. il.append(fact.createReturn(BcelWorld.makeBcelType(method.getReturnType())));
  145. mg.getBody().insert(il);
  146. gen.addMethodGen(mg);
  147. }
  148. private LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) {
  149. return new LazyMethodGen(
  150. member.getModifiers(),
  151. BcelWorld.makeBcelType(member.getReturnType()),
  152. member.getName(),
  153. BcelWorld.makeBcelTypes(member.getParameterTypes()),
  154. TypeX.getNames(member.getExceptions()),
  155. gen);
  156. }
  157. private FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) {
  158. return new FieldGen(
  159. member.getModifiers(),
  160. BcelWorld.makeBcelType(member.getReturnType()),
  161. member.getName(),
  162. gen.getConstantPoolGen());
  163. }
  164. private boolean mungePerObjectInterface(
  165. BcelClassWeaver weaver,
  166. PerObjectInterfaceTypeMunger munger)
  167. {
  168. LazyClassGen gen = weaver.getLazyClassGen();
  169. if (couldMatch(gen.getType(), munger.getTestPointcut())) {
  170. FieldGen fg = makeFieldGen(gen,
  171. AjcMemberMaker.perObjectField(gen.getType(), aspectType));
  172. gen.addField(fg.getField());
  173. Type fieldType = BcelWorld.makeBcelType(aspectType);
  174. LazyMethodGen mg = new LazyMethodGen(
  175. Modifier.PUBLIC,
  176. fieldType,
  177. NameMangler.perObjectInterfaceGet(aspectType),
  178. new Type[0], new String[0],
  179. gen);
  180. InstructionList il = new InstructionList();
  181. InstructionFactory fact = gen.getFactory();
  182. il.append(fact.ALOAD_0);
  183. il.append(fact.createFieldAccess(
  184. gen.getClassName(),
  185. fg.getName(),
  186. fieldType, Constants.GETFIELD));
  187. il.append(fact.createReturn(fieldType));
  188. mg.getBody().insert(il);
  189. gen.addMethodGen(mg);
  190. LazyMethodGen mg1 = new LazyMethodGen(
  191. Modifier.PUBLIC,
  192. Type.VOID,
  193. NameMangler.perObjectInterfaceSet(aspectType),
  194. new Type[]{fieldType,}, new String[0],
  195. gen);
  196. InstructionList il1 = new InstructionList();
  197. il1.append(fact.ALOAD_0);
  198. il1.append(fact.createLoad(fieldType, 1));
  199. il1.append(fact.createFieldAccess(
  200. gen.getClassName(),
  201. fg.getName(),
  202. fieldType, Constants.PUTFIELD));
  203. il1.append(fact.createReturn(Type.VOID));
  204. mg1.getBody().insert(il1);
  205. gen.addMethodGen(mg1);
  206. gen.addInterface(munger.getInterfaceType());
  207. return true;
  208. } else {
  209. return false;
  210. }
  211. }
  212. private boolean couldMatch(
  213. BcelObjectType bcelObjectType,
  214. Pointcut pointcut) {
  215. return !bcelObjectType.isInterface();
  216. }
  217. private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) {
  218. ResolvedMember signature = munger.getSignature();
  219. ResolvedMember dispatchMethod = munger.getDispatchMethod(aspectType);
  220. LazyClassGen gen = weaver.getLazyClassGen();
  221. ResolvedTypeX onType = weaver.getWorld().resolve(signature.getDeclaringType());
  222. boolean onInterface = onType.isInterface();
  223. if (onType.equals(gen.getType())) {
  224. ResolvedMember introMethod =
  225. AjcMemberMaker.interMethod(signature, aspectType, onInterface);
  226. LazyMethodGen mg = makeMethodGen(gen, introMethod);
  227. if (!onInterface && !Modifier.isAbstract(introMethod.getModifiers())) {
  228. InstructionList body = mg.getBody();
  229. InstructionFactory fact = gen.getFactory();
  230. int pos = 0;
  231. if (!signature.isStatic()) {
  232. body.append(fact.createThis());
  233. pos++;
  234. }
  235. Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
  236. for (int i = 0, len = paramTypes.length; i < len; i++) {
  237. Type paramType = paramTypes[i];
  238. body.append(fact.createLoad(paramType, pos));
  239. pos+=paramType.getSize();
  240. }
  241. body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
  242. body.append(fact.createReturn(BcelWorld.makeBcelType(introMethod.getReturnType())));
  243. } else {
  244. //??? this is okay
  245. //if (!(mg.getBody() == null)) throw new RuntimeException("bas");
  246. }
  247. // XXX make sure to check that we set exceptions properly on this guy.
  248. weaver.addLazyMethodGen(mg);
  249. Set neededSuperCalls = munger.getSuperMethodsCalled();
  250. for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext(); ) {
  251. ResolvedMember superMethod = (ResolvedMember) iter.next();
  252. if (weaver.addDispatchTarget(superMethod)) {
  253. //System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
  254. boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
  255. String dispatchName;
  256. if (isSuper) dispatchName = NameMangler.superDispatchMethod(onType, superMethod.getName());
  257. else dispatchName = NameMangler.protectedDispatchMethod(onType, superMethod.getName());
  258. LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld(), isSuper);
  259. weaver.addLazyMethodGen(dispatcher);
  260. }
  261. }
  262. return true;
  263. } else if (onInterface && gen.getType().isTopmostImplementor(onType) &&
  264. !Modifier.isAbstract(signature.getModifiers()))
  265. {
  266. ResolvedMember introMethod =
  267. AjcMemberMaker.interMethod(signature, aspectType, false);
  268. LazyMethodGen mg = makeMethodGen(gen, introMethod);
  269. //
  270. Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
  271. Type returnType = BcelWorld.makeBcelType(introMethod.getReturnType());
  272. InstructionList body = mg.getBody();
  273. InstructionFactory fact = gen.getFactory();
  274. int pos = 0;
  275. if (!introMethod.isStatic()) {
  276. body.append(fact.createThis());
  277. pos++;
  278. }
  279. for (int i = 0, len = paramTypes.length; i < len; i++) {
  280. Type paramType = paramTypes[i];
  281. body.append(fact.createLoad(paramType, pos));
  282. pos+=paramType.getSize();
  283. }
  284. body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
  285. body.append(fact.createReturn(returnType));
  286. mg.definingType = onType;
  287. weaver.addOrReplaceLazyMethodGen(mg);
  288. return true;
  289. } else {
  290. return false;
  291. }
  292. }
  293. private boolean mungeNewConstructor(
  294. BcelClassWeaver weaver,
  295. NewConstructorTypeMunger newConstructorTypeMunger)
  296. {
  297. final LazyClassGen currentClass = weaver.getLazyClassGen();
  298. final InstructionFactory fact = currentClass.getFactory();
  299. ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor();
  300. TypeX onType = newConstructorMember.getDeclaringType();
  301. if (! onType.equals(currentClass.getType())) return false;
  302. ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor();
  303. //int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount();
  304. LazyMethodGen freshConstructor =
  305. makeMethodGen(currentClass, newConstructorMember);
  306. currentClass.addMethodGen(freshConstructor);
  307. //weaver.addLazyMethodGen(freshConstructor);
  308. InstructionList body = freshConstructor.getBody();
  309. // add to body: push arts for call to pre, from actual args starting at 1 (skipping this), going to
  310. // declared argcount + 1
  311. TypeX[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes();
  312. Type[] paramTypes = freshConstructor.getArgumentTypes();
  313. int frameIndex = 1;
  314. for (int i = 0, len = declaredParams.length; i < len; i++) {
  315. body.append(fact.createLoad(paramTypes[i], frameIndex));
  316. frameIndex += paramTypes[i].getSize();
  317. }
  318. // do call to pre
  319. Member preMethod = AjcMemberMaker.preIntroducedConstructor(aspectType, onType, declaredParams);
  320. body.append(Utility.createInvoke(fact, null, preMethod));
  321. // create a local, and store return pre stuff into it.
  322. int arraySlot = freshConstructor.allocateLocal(1);
  323. body.append(fact.createStore(Type.OBJECT, arraySlot));
  324. // put this on the stack
  325. body.append(fact.ALOAD_0);
  326. // unpack pre args onto stack
  327. TypeX[] superParamTypes = explicitConstructor.getParameterTypes();
  328. for (int i = 0, len = superParamTypes.length; i < len; i++) {
  329. body.append(fact.createLoad(Type.OBJECT, arraySlot));
  330. body.append(Utility.createConstant(fact, i));
  331. body.append(fact.createArrayLoad(Type.OBJECT));
  332. body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(superParamTypes[i])));
  333. }
  334. // call super/this
  335. body.append(Utility.createInvoke(fact, null, explicitConstructor));
  336. // put this back on the stack
  337. body.append(fact.ALOAD_0);
  338. // unpack params onto stack
  339. Member postMethod = AjcMemberMaker.postIntroducedConstructor(aspectType, onType, declaredParams);
  340. TypeX[] postParamTypes = postMethod.getParameterTypes();
  341. for (int i = 1, len = postParamTypes.length; i < len; i++) {
  342. body.append(fact.createLoad(Type.OBJECT, arraySlot));
  343. body.append(Utility.createConstant(fact, superParamTypes.length + i-1));
  344. body.append(fact.createArrayLoad(Type.OBJECT));
  345. body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(postParamTypes[i])));
  346. }
  347. // call post
  348. body.append(Utility.createInvoke(fact, null, postMethod));
  349. // don't forget to return!!
  350. body.append(fact.RETURN);
  351. return true;
  352. }
  353. private static LazyMethodGen makeDispatcher(
  354. LazyClassGen onGen,
  355. String dispatchName,
  356. ResolvedMember superMethod,
  357. BcelWorld world,
  358. boolean isSuper)
  359. {
  360. Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
  361. Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
  362. LazyMethodGen mg =
  363. new LazyMethodGen(
  364. Modifier.PUBLIC,
  365. returnType,
  366. dispatchName,
  367. paramTypes,
  368. TypeX.getNames(superMethod.getExceptions()),
  369. onGen);
  370. InstructionList body = mg.getBody();
  371. // assert (!superMethod.isStatic())
  372. InstructionFactory fact = onGen.getFactory();
  373. int pos = 0;
  374. body.append(fact.createThis());
  375. pos++;
  376. for (int i = 0, len = paramTypes.length; i < len; i++) {
  377. Type paramType = paramTypes[i];
  378. body.append(fact.createLoad(paramType, pos));
  379. pos+=paramType.getSize();
  380. }
  381. if (isSuper) {
  382. body.append(Utility.createSuperInvoke(fact, world, superMethod));
  383. } else {
  384. body.append(Utility.createInvoke(fact, world, superMethod));
  385. }
  386. body.append(fact.createReturn(returnType));
  387. return mg;
  388. }
  389. private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) {
  390. ResolvedMember initMethod = munger.getInitMethod(aspectType);
  391. LazyClassGen gen = weaver.getLazyClassGen();
  392. ResolvedMember field = munger.getSignature();
  393. ResolvedTypeX onType = weaver.getWorld().resolve(field.getDeclaringType());
  394. boolean onInterface = onType.isInterface();
  395. if (onType.equals(gen.getType())) {
  396. if (onInterface) {
  397. LazyMethodGen mg = makeMethodGen(gen,
  398. AjcMemberMaker.interFieldInterfaceGetter(field, onType, aspectType));
  399. gen.addMethodGen(mg);
  400. LazyMethodGen mg1 = makeMethodGen(gen,
  401. AjcMemberMaker.interFieldInterfaceSetter(field, onType, aspectType));
  402. gen.addMethodGen(mg1);
  403. } else {
  404. weaver.addInitializer(this);
  405. FieldGen fg = makeFieldGen(gen,
  406. AjcMemberMaker.interFieldClassField(field, aspectType));
  407. gen.addField(fg.getField());
  408. }
  409. return true;
  410. } else if (onInterface && gen.getType().isTopmostImplementor(onType)) {
  411. // wew know that we can't be static since we don't allow statics on interfaces
  412. if (field.isStatic()) throw new RuntimeException("unimplemented");
  413. weaver.addInitializer(this);
  414. //System.err.println("impl body on " + gen.getType() + " for " + munger);
  415. Type fieldType = BcelWorld.makeBcelType(field.getType());
  416. FieldGen fg = makeFieldGen(gen,
  417. AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));
  418. gen.addField(fg.getField());
  419. //this uses a shadow munger to add init method to constructors
  420. //weaver.getShadowMungers().add(makeInitCallShadowMunger(initMethod));
  421. LazyMethodGen mg = makeMethodGen(gen,
  422. AjcMemberMaker.interFieldInterfaceGetter(field, gen.getType(), aspectType));
  423. InstructionList il = new InstructionList();
  424. InstructionFactory fact = gen.getFactory();
  425. if (field.isStatic()) {
  426. il.append(fact.createFieldAccess(
  427. gen.getClassName(),
  428. fg.getName(),
  429. fieldType, Constants.GETSTATIC));
  430. } else {
  431. il.append(fact.ALOAD_0);
  432. il.append(fact.createFieldAccess(
  433. gen.getClassName(),
  434. fg.getName(),
  435. fieldType, Constants.GETFIELD));
  436. }
  437. il.append(fact.createReturn(fieldType));
  438. mg.getBody().insert(il);
  439. gen.addMethodGen(mg);
  440. LazyMethodGen mg1 = makeMethodGen(gen,
  441. AjcMemberMaker.interFieldInterfaceSetter(field, gen.getType(), aspectType));
  442. InstructionList il1 = new InstructionList();
  443. if (field.isStatic()) {
  444. il1.append(fact.createLoad(fieldType, 0));
  445. il1.append(fact.createFieldAccess(
  446. gen.getClassName(),
  447. fg.getName(),
  448. fieldType, Constants.PUTSTATIC));
  449. } else {
  450. il1.append(fact.ALOAD_0);
  451. il1.append(fact.createLoad(fieldType, 1));
  452. il1.append(fact.createFieldAccess(
  453. gen.getClassName(),
  454. fg.getName(),
  455. fieldType, Constants.PUTFIELD));
  456. }
  457. il1.append(fact.createReturn(Type.VOID));
  458. mg1.getBody().insert(il1);
  459. gen.addMethodGen(mg1);
  460. return true;
  461. } else {
  462. return false;
  463. }
  464. }
  465. }