Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

BcelTypeMunger.java 18KB

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