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.

BcelTypeMunger.java 50KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  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.lang.reflect.Modifier;
  14. import java.util.Iterator;
  15. import java.util.List;
  16. import java.util.Set;
  17. import org.aspectj.apache.bcel.Constants;
  18. import org.aspectj.apache.bcel.classfile.annotation.Annotation;
  19. import org.aspectj.apache.bcel.generic.ConstantPoolGen;
  20. import org.aspectj.apache.bcel.generic.FieldGen;
  21. import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
  22. import org.aspectj.apache.bcel.generic.InstructionConstants;
  23. import org.aspectj.apache.bcel.generic.InstructionFactory;
  24. import org.aspectj.apache.bcel.generic.InstructionHandle;
  25. import org.aspectj.apache.bcel.generic.InstructionList;
  26. import org.aspectj.apache.bcel.generic.Type;
  27. import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
  28. import org.aspectj.bridge.IMessage;
  29. import org.aspectj.bridge.ISourceLocation;
  30. import org.aspectj.bridge.Message;
  31. import org.aspectj.bridge.MessageUtil;
  32. import org.aspectj.bridge.WeaveMessage;
  33. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  34. import org.aspectj.bridge.context.ContextToken;
  35. import org.aspectj.weaver.AjcMemberMaker;
  36. import org.aspectj.weaver.AnnotationOnTypeMunger;
  37. import org.aspectj.weaver.AnnotationX;
  38. import org.aspectj.weaver.AsmRelationshipProvider;
  39. import org.aspectj.weaver.BCException;
  40. import org.aspectj.weaver.ConcreteTypeMunger;
  41. import org.aspectj.weaver.Member;
  42. import org.aspectj.weaver.NameMangler;
  43. import org.aspectj.weaver.NewConstructorTypeMunger;
  44. import org.aspectj.weaver.NewFieldTypeMunger;
  45. import org.aspectj.weaver.NewMethodTypeMunger;
  46. import org.aspectj.weaver.NewParentTypeMunger;
  47. import org.aspectj.weaver.PerObjectInterfaceTypeMunger;
  48. import org.aspectj.weaver.PrivilegedAccessMunger;
  49. import org.aspectj.weaver.ResolvedMember;
  50. import org.aspectj.weaver.ResolvedType;
  51. import org.aspectj.weaver.ResolvedTypeMunger;
  52. import org.aspectj.weaver.Shadow;
  53. import org.aspectj.weaver.UnresolvedType;
  54. import org.aspectj.weaver.WeaverMessages;
  55. import org.aspectj.weaver.WeaverStateInfo;
  56. import org.aspectj.weaver.patterns.DeclareAnnotation;
  57. import org.aspectj.weaver.patterns.Pointcut;
  58. //XXX addLazyMethodGen is probably bad everywhere
  59. public class BcelTypeMunger extends ConcreteTypeMunger {
  60. public BcelTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
  61. super(munger, aspectType);
  62. }
  63. public String toString() {
  64. return "(BcelTypeMunger " + getMunger() + ")";
  65. }
  66. public boolean munge(BcelClassWeaver weaver) {
  67. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MUNGING_WITH, this);
  68. boolean changed = false;
  69. boolean worthReporting = true;
  70. if (munger.getKind() == ResolvedTypeMunger.Field) {
  71. changed = mungeNewField(weaver, (NewFieldTypeMunger)munger);
  72. } else if (munger.getKind() == ResolvedTypeMunger.Method) {
  73. changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger);
  74. } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
  75. changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger);
  76. worthReporting = false;
  77. } else if (munger.getKind() == ResolvedTypeMunger.PerTypeWithinInterface) {
  78. // PTWIMPL Transform the target type (add the aspect instance field)
  79. changed = mungePerTypeWithinTransformer(weaver);
  80. worthReporting = false;
  81. } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
  82. changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger);
  83. worthReporting = false;
  84. } else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
  85. changed = mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger);
  86. } else if (munger.getKind() == ResolvedTypeMunger.Parent) {
  87. changed = mungeNewParent(weaver, (NewParentTypeMunger)munger);
  88. } else if (munger.getKind() == ResolvedTypeMunger.AnnotationOnType) {
  89. changed = mungeNewAnnotationOnType(weaver,(AnnotationOnTypeMunger)munger);
  90. } else {
  91. throw new RuntimeException("unimplemented");
  92. }
  93. if (changed && munger.changesPublicSignature()) {
  94. WeaverStateInfo info =
  95. weaver.getLazyClassGen().getOrCreateWeaverStateInfo(weaver.getReweavableMode());
  96. info.addConcreteMunger(this);
  97. }
  98. if (changed && worthReporting) {
  99. if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
  100. AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType());
  101. } else {
  102. AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType());
  103. }
  104. }
  105. // TAG: WeavingMessage
  106. if (changed && worthReporting && munger!=null && !weaver.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
  107. String tName = weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getName();
  108. if (tName.indexOf("no debug info available")!=-1) tName = "no debug info available";
  109. else tName = getShortname(weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getPath());
  110. String fName = getShortname(getAspectType().getSourceLocation().getSourceFile().getPath());
  111. if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
  112. // This message could come out of AjLookupEnvironment.addParent if doing parents
  113. // munging at compile time only...
  114. NewParentTypeMunger parentTM = (NewParentTypeMunger)munger;
  115. if (parentTM.getNewParent().isInterface()) {
  116. weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,
  117. new String[]{weaver.getLazyClassGen().getType().getName(),
  118. tName,parentTM.getNewParent().getName(),fName},
  119. weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
  120. } else {
  121. weaver.getWorld().getMessageHandler().handleMessage(
  122. WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,
  123. new String[]{weaver.getLazyClassGen().getType().getName(),
  124. tName,parentTM.getNewParent().getName(),fName
  125. }));
  126. // TAG: WeavingMessage DECLARE PARENTS: EXTENDS
  127. // reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
  128. }
  129. } else {
  130. weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD,
  131. new String[]{weaver.getLazyClassGen().getType().getName(),
  132. tName,munger.getKind().toString().toLowerCase(),
  133. getAspectType().getName(),
  134. fName+":'"+munger.getSignature()+"'"},
  135. weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
  136. }
  137. }
  138. CompilationAndWeavingContext.leavingPhase(tok);
  139. return changed;
  140. }
  141. private String getShortname(String path) {
  142. int takefrom = path.lastIndexOf('/');
  143. if (takefrom == -1) {
  144. takefrom = path.lastIndexOf('\\');
  145. }
  146. return path.substring(takefrom+1);
  147. }
  148. private boolean mungeNewAnnotationOnType(BcelClassWeaver weaver,AnnotationOnTypeMunger munger) {
  149. // FIXME asc this has already been done up front, need to do it here too?
  150. weaver.getLazyClassGen().addAnnotation(munger.getNewAnnotation().getBcelAnnotation());
  151. return true;
  152. }
  153. /**
  154. * For a long time, AspectJ did not allow binary weaving of declare parents. This restriction is now lifted
  155. * but could do with more testing!
  156. */
  157. private boolean mungeNewParent(BcelClassWeaver weaver, NewParentTypeMunger munger) {
  158. LazyClassGen newParentTarget = weaver.getLazyClassGen();
  159. ResolvedType newParent = munger.getNewParent();
  160. boolean cont = true; // Set to false when we error, so we don't actually *do* the munge
  161. cont = enforceDecpRule1_abstractMethodsImplemented(weaver, munger.getSourceLocation(),newParentTarget, newParent);
  162. cont = enforceDecpRule2_cantExtendFinalClass(weaver,munger.getSourceLocation(),newParentTarget,newParent) && cont;
  163. List methods = newParent.getMethodsWithoutIterator(false,true);
  164. for (Iterator iter = methods.iterator(); iter.hasNext();) {
  165. ResolvedMember superMethod = (ResolvedMember) iter.next();
  166. if (!superMethod.getName().equals("<init>")) {
  167. LazyMethodGen subMethod = findMatchingMethod(newParentTarget, superMethod);
  168. if (subMethod!=null) {
  169. cont = enforceDecpRule3_visibilityChanges(weaver, newParent, superMethod, subMethod) && cont;
  170. cont = enforceDecpRule4_compatibleReturnTypes(weaver, superMethod, subMethod) && cont;
  171. cont = enforceDecpRule5_cantChangeFromStaticToNonstatic(weaver,munger.getSourceLocation(),superMethod,subMethod) && cont;
  172. }
  173. }
  174. }
  175. if (!cont) return false; // A rule was violated and an error message already reported
  176. if (newParent.isClass()) { // Changing the supertype
  177. if (!attemptToModifySuperCalls(weaver,newParentTarget,newParent)) return false;
  178. newParentTarget.setSuperClass(newParent);
  179. } else { // Adding a new interface
  180. newParentTarget.addInterface(newParent,getSourceLocation());
  181. }
  182. return true;
  183. }
  184. /**
  185. * Rule 1: For the declare parents to be allowed, the target type must override and implement
  186. * inherited abstract methods (if the type is not declared abstract)
  187. */
  188. private boolean enforceDecpRule1_abstractMethodsImplemented(BcelClassWeaver weaver, ISourceLocation mungerLoc,LazyClassGen newParentTarget, ResolvedType newParent) {
  189. boolean ruleCheckingSucceeded = true;
  190. if (!(newParentTarget.isAbstract() || newParentTarget.isInterface())) { // Ignore abstract classes or interfaces
  191. List methods = newParent.getMethodsWithoutIterator(false,true);
  192. for (Iterator i = methods.iterator(); i.hasNext();) {
  193. ResolvedMember o = (ResolvedMember)i.next();
  194. if (o.isAbstract() && !o.getName().startsWith("ajc$interField")) { // Ignore abstract methods of ajc$interField prefixed methods
  195. ResolvedMember discoveredImpl = null;
  196. List newParentTargetMethods = newParentTarget.getType().getMethodsWithoutIterator(false,true);
  197. for (Iterator ii = newParentTargetMethods.iterator(); ii.hasNext() && discoveredImpl==null;) {
  198. ResolvedMember gen2 = (ResolvedMember) ii.next();
  199. if (gen2.getName().equals(o.getName()) &&
  200. gen2.getParameterSignature().equals(o.getParameterSignature()) && !gen2.isAbstract()) {
  201. discoveredImpl = gen2; // Found a valid implementation !
  202. }
  203. }
  204. if (discoveredImpl == null) {
  205. // didnt find a valid implementation, lets check the ITDs on this type to see if they satisfy it
  206. boolean satisfiedByITD = false;
  207. for (Iterator ii = newParentTarget.getType().getInterTypeMungersIncludingSupers().iterator(); ii.hasNext(); ) {
  208. ConcreteTypeMunger m = (ConcreteTypeMunger)ii.next();
  209. if (m.getMunger() instanceof NewMethodTypeMunger) {
  210. ResolvedMember sig = m.getSignature();
  211. if (!Modifier.isAbstract(sig.getModifiers())) {
  212. if (ResolvedType
  213. .matches(
  214. AjcMemberMaker.interMethod(
  215. sig,m.getAspectType(),sig.getDeclaringType().resolve(weaver.getWorld()).isInterface()),o)) {
  216. satisfiedByITD = true;
  217. }
  218. }
  219. }
  220. }
  221. if (!satisfiedByITD) {
  222. error(weaver,
  223. "The type " + newParentTarget.getName() + " must implement the inherited abstract method "+o.getDeclaringType()+"."+o.getName()+o.getParameterSignature(),
  224. newParentTarget.getType().getSourceLocation(),new ISourceLocation[]{o.getSourceLocation(),mungerLoc});
  225. ruleCheckingSucceeded=false;
  226. }
  227. }
  228. }
  229. }
  230. }
  231. return ruleCheckingSucceeded;
  232. }
  233. /**
  234. * Rule 2. Can't extend final types
  235. */
  236. private boolean enforceDecpRule2_cantExtendFinalClass(BcelClassWeaver weaver, ISourceLocation mungerLoc,
  237. LazyClassGen newParentTarget, ResolvedType newParent) {
  238. if (newParent.isFinal()) {
  239. error(weaver,"Cannot make type "+newParentTarget.getName()+" extend final class "+newParent.getName(),
  240. newParentTarget.getType().getSourceLocation(),
  241. new ISourceLocation[]{mungerLoc});
  242. return false;
  243. }
  244. return true;
  245. }
  246. /**
  247. * Rule 3. Can't narrow visibility of methods when overriding
  248. */
  249. private boolean enforceDecpRule3_visibilityChanges(BcelClassWeaver weaver, ResolvedType newParent, ResolvedMember superMethod, LazyMethodGen subMethod) {
  250. boolean cont = true;
  251. if (superMethod.isPublic()) {
  252. if (subMethod.isProtected() || subMethod.isDefault() || subMethod.isPrivate()) {
  253. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  254. "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
  255. superMethod.getSourceLocation()));
  256. cont=false;
  257. }
  258. } else if (superMethod.isProtected()) {
  259. if (subMethod.isDefault() || subMethod.isPrivate()) {
  260. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  261. "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
  262. superMethod.getSourceLocation()));
  263. cont=false;
  264. }
  265. } else if (superMethod.isDefault()) {
  266. if (subMethod.isPrivate()) {
  267. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  268. "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
  269. superMethod.getSourceLocation()));
  270. cont=false;
  271. }
  272. }
  273. return cont;
  274. }
  275. /**
  276. * Rule 4. Can't have incompatible return types
  277. */
  278. private boolean enforceDecpRule4_compatibleReturnTypes(BcelClassWeaver weaver, ResolvedMember superMethod, LazyMethodGen subMethod) {
  279. boolean cont = true;
  280. String superReturnTypeSig = superMethod.getReturnType().getSignature();
  281. String subReturnTypeSig = subMethod.getReturnType().getSignature();
  282. if (!superReturnTypeSig.equals(subReturnTypeSig)) {
  283. // Allow for covariance - wish I could test this (need Java5...)
  284. ResolvedType subType = weaver.getWorld().resolve(subMethod.getReturnType());
  285. ResolvedType superType = weaver.getWorld().resolve(superMethod.getReturnType());
  286. if (!superType.isAssignableFrom(subType)) {
  287. ISourceLocation sloc = subMethod.getSourceLocation();
  288. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  289. "The return type is incompatible with "+superMethod.getDeclaringType()+"."+superMethod.getName()+superMethod.getParameterSignature(),
  290. subMethod.getSourceLocation()));
  291. cont=false;
  292. }
  293. }
  294. return cont;
  295. }
  296. /**
  297. * Rule5. Method overrides can't change the staticality (word?) - you can't override and make an instance
  298. * method static or override and make a static method an instance method.
  299. */
  300. private boolean enforceDecpRule5_cantChangeFromStaticToNonstatic(BcelClassWeaver weaver,ISourceLocation mungerLoc,ResolvedMember superMethod, LazyMethodGen subMethod ) {
  301. if (superMethod.isStatic() && !subMethod.isStatic()) {
  302. error(weaver,"This instance method "+subMethod.getName()+subMethod.getParameterSignature()+
  303. " cannot override the static method from "+superMethod.getDeclaringType().getName(),
  304. subMethod.getSourceLocation(),new ISourceLocation[]{mungerLoc});
  305. return false;
  306. } else if (!superMethod.isStatic() && subMethod.isStatic()) {
  307. error(weaver,"The static method "+subMethod.getName()+subMethod.getParameterSignature()+
  308. " cannot hide the instance method from "+superMethod.getDeclaringType().getName(),
  309. subMethod.getSourceLocation(),new ISourceLocation[]{mungerLoc});
  310. return false;
  311. }
  312. return true;
  313. }
  314. public void error(BcelClassWeaver weaver,String text,ISourceLocation primaryLoc,ISourceLocation[] extraLocs) {
  315. IMessage msg = new Message(text, primaryLoc, true, extraLocs);
  316. weaver.getWorld().getMessageHandler().handleMessage(msg);
  317. }
  318. private LazyMethodGen findMatchingMethod(LazyClassGen newParentTarget, ResolvedMember m) {
  319. LazyMethodGen found = null;
  320. // Search the type for methods overriding super methods (methods that come from the new parent)
  321. // Don't use the return value in the comparison as overriding doesnt
  322. for (Iterator i = newParentTarget.getMethodGens().iterator(); i.hasNext() && found==null;) {
  323. LazyMethodGen gen = (LazyMethodGen) i.next();
  324. if (gen.getName().equals(m.getName()) &&
  325. gen.getParameterSignature().equals(m.getParameterSignature())) {
  326. found = gen;
  327. }
  328. }
  329. return found;
  330. }
  331. /**
  332. * The main part of implementing declare parents extends. Modify super ctor calls to target the new type.
  333. */
  334. public boolean attemptToModifySuperCalls(BcelClassWeaver weaver,LazyClassGen newParentTarget, ResolvedType newParent) {
  335. String currentParent = newParentTarget.getSuperClassname();
  336. List mgs = newParentTarget.getMethodGens();
  337. // Look for ctors to modify
  338. for (Iterator iter = mgs.iterator(); iter.hasNext();) {
  339. LazyMethodGen aMethod = (LazyMethodGen) iter.next();
  340. if (aMethod.getName().equals("<init>")) {
  341. InstructionList insList = aMethod.getBody();
  342. InstructionHandle handle = insList.getStart();
  343. while (handle!= null) {
  344. if (handle.getInstruction() instanceof INVOKESPECIAL) {
  345. ConstantPoolGen cpg = newParentTarget.getConstantPoolGen();
  346. INVOKESPECIAL invokeSpecial = (INVOKESPECIAL)handle.getInstruction();
  347. if (invokeSpecial.getClassName(cpg).equals(currentParent) && invokeSpecial.getMethodName(cpg).equals("<init>")) {
  348. // System.err.println("Transforming super call '<init>"+sp.getSignature(cpg)+"'");
  349. // 1. Check there is a ctor in the new parent with the same signature
  350. ResolvedMember newCtor = getConstructorWithSignature(newParent,invokeSpecial.getSignature(cpg));
  351. if (newCtor == null) {
  352. // 2. Check ITDCs to see if the necessary ctor is provided that way
  353. boolean satisfiedByITDC = false;
  354. for (Iterator ii = newParentTarget.getType().getInterTypeMungersIncludingSupers().iterator(); ii.hasNext() && !satisfiedByITDC; ) {
  355. ConcreteTypeMunger m = (ConcreteTypeMunger)ii.next();
  356. if (m.getMunger() instanceof NewConstructorTypeMunger) {
  357. if (m.getSignature().getSignature().equals(invokeSpecial.getSignature(cpg))) {
  358. satisfiedByITDC = true;
  359. }
  360. }
  361. }
  362. if (!satisfiedByITDC) {
  363. String csig = createReadableCtorSig(newParent, cpg, invokeSpecial);
  364. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  365. "Unable to modify hierarchy for "+newParentTarget.getClassName()+" - the constructor "+
  366. csig+" is missing",this.getSourceLocation()));
  367. return false;
  368. }
  369. }
  370. int idx = cpg.addMethodref(newParent.getClassName(), invokeSpecial.getMethodName(cpg), invokeSpecial.getSignature(cpg));
  371. invokeSpecial.setIndex(idx);
  372. }
  373. }
  374. handle = handle.getNext();
  375. }
  376. }
  377. }
  378. return true;
  379. }
  380. /**
  381. * Creates a nice signature for the ctor, something like "(int,Integer,String)"
  382. */
  383. private String createReadableCtorSig(ResolvedType newParent, ConstantPoolGen cpg, INVOKESPECIAL invokeSpecial) {
  384. StringBuffer sb = new StringBuffer();
  385. Type[] ctorArgs = invokeSpecial.getArgumentTypes(cpg);
  386. sb.append(newParent.getClassName());
  387. sb.append("(");
  388. for (int i = 0; i < ctorArgs.length; i++) {
  389. String argtype = ctorArgs[i].toString();
  390. if (argtype.lastIndexOf(".")!=-1)
  391. sb.append(argtype.substring(argtype.lastIndexOf(".")+1));
  392. else
  393. sb.append(argtype);
  394. if (i+1<ctorArgs.length) sb.append(",");
  395. }
  396. sb.append(")");
  397. return sb.toString();
  398. }
  399. private ResolvedMember getConstructorWithSignature(ResolvedType tx,String signature) {
  400. ResolvedMember[] mems = tx.getDeclaredJavaMethods();
  401. for (int i = 0; i < mems.length; i++) {
  402. ResolvedMember rm = mems[i];
  403. if (rm.getName().equals("<init>")) {
  404. if (rm.getSignature().equals(signature)) return rm;
  405. }
  406. }
  407. return null;
  408. }
  409. private boolean mungePrivilegedAccess(
  410. BcelClassWeaver weaver,
  411. PrivilegedAccessMunger munger)
  412. {
  413. LazyClassGen gen = weaver.getLazyClassGen();
  414. ResolvedMember member = munger.getMember();
  415. ResolvedType onType = weaver.getWorld().resolve(member.getDeclaringType(),munger.getSourceLocation());
  416. if (onType.isRawType()) onType = onType.getGenericType();
  417. //System.out.println("munging: " + gen + " with " + member);
  418. if (onType.equals(gen.getType())) {
  419. if (member.getKind() == Member.FIELD) {
  420. //System.out.println("matched: " + gen);
  421. addFieldGetter(gen, member,
  422. AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member));
  423. addFieldSetter(gen, member,
  424. AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member));
  425. return true;
  426. } else if (member.getKind() == Member.METHOD) {
  427. addMethodDispatch(gen, member,
  428. AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
  429. return true;
  430. } else if (member.getKind() == Member.CONSTRUCTOR) {
  431. for (Iterator i = gen.getMethodGens().iterator(); i.hasNext(); ) {
  432. LazyMethodGen m = (LazyMethodGen)i.next();
  433. if (m.getMemberView() != null
  434. && m.getMemberView().getKind() == Member.CONSTRUCTOR) {
  435. // m.getMemberView().equals(member)) {
  436. m.forcePublic();
  437. //return true;
  438. }
  439. }
  440. return true;
  441. //throw new BCException("no match for " + member + " in " + gen);
  442. } else if (member.getKind() == Member.STATIC_INITIALIZATION) {
  443. gen.forcePublic();
  444. return true;
  445. } else {
  446. throw new RuntimeException("unimplemented");
  447. }
  448. }
  449. return false;
  450. }
  451. private void addFieldGetter(
  452. LazyClassGen gen,
  453. ResolvedMember field,
  454. ResolvedMember accessMethod)
  455. {
  456. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  457. InstructionList il = new InstructionList();
  458. InstructionFactory fact = gen.getFactory();
  459. if (field.isStatic()) {
  460. il.append(fact.createFieldAccess(
  461. gen.getClassName(),
  462. field.getName(),
  463. BcelWorld.makeBcelType(field.getType()), Constants.GETSTATIC));
  464. } else {
  465. il.append(InstructionConstants.ALOAD_0);
  466. il.append(fact.createFieldAccess(
  467. gen.getClassName(),
  468. field.getName(),
  469. BcelWorld.makeBcelType(field.getType()), Constants.GETFIELD));
  470. }
  471. il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(field.getType())));
  472. mg.getBody().insert(il);
  473. gen.addMethodGen(mg,getSignature().getSourceLocation());
  474. }
  475. private void addFieldSetter(
  476. LazyClassGen gen,
  477. ResolvedMember field,
  478. ResolvedMember accessMethod)
  479. {
  480. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  481. InstructionList il = new InstructionList();
  482. InstructionFactory fact = gen.getFactory();
  483. Type fieldType = BcelWorld.makeBcelType(field.getType());
  484. if (field.isStatic()) {
  485. il.append(InstructionFactory.createLoad(fieldType, 0));
  486. il.append(fact.createFieldAccess(
  487. gen.getClassName(),
  488. field.getName(),
  489. fieldType, Constants.PUTSTATIC));
  490. } else {
  491. il.append(InstructionConstants.ALOAD_0);
  492. il.append(InstructionFactory.createLoad(fieldType, 1));
  493. il.append(fact.createFieldAccess(
  494. gen.getClassName(),
  495. field.getName(),
  496. fieldType, Constants.PUTFIELD));
  497. }
  498. il.append(InstructionFactory.createReturn(Type.VOID));
  499. mg.getBody().insert(il);
  500. gen.addMethodGen(mg,getSignature().getSourceLocation());
  501. }
  502. private void addMethodDispatch(
  503. LazyClassGen gen,
  504. ResolvedMember method,
  505. ResolvedMember accessMethod)
  506. {
  507. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  508. InstructionList il = new InstructionList();
  509. InstructionFactory fact = gen.getFactory();
  510. //Type fieldType = BcelWorld.makeBcelType(field.getType());
  511. Type[] paramTypes = BcelWorld.makeBcelTypes(method.getParameterTypes());
  512. int pos = 0;
  513. if (!method.isStatic()) {
  514. il.append(InstructionConstants.ALOAD_0);
  515. pos++;
  516. }
  517. for (int i = 0, len = paramTypes.length; i < len; i++) {
  518. Type paramType = paramTypes[i];
  519. il.append(InstructionFactory.createLoad(paramType, pos));
  520. pos+=paramType.getSize();
  521. }
  522. il.append(Utility.createInvoke(fact, (BcelWorld)aspectType.getWorld(),
  523. method));
  524. il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(method.getReturnType())));
  525. mg.getBody().insert(il);
  526. gen.addMethodGen(mg);
  527. }
  528. protected LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) {
  529. LazyMethodGen ret = new LazyMethodGen(
  530. member.getModifiers(),
  531. BcelWorld.makeBcelType(member.getReturnType()),
  532. member.getName(),
  533. BcelWorld.makeBcelTypes(member.getParameterTypes()),
  534. UnresolvedType.getNames(member.getExceptions()),
  535. gen);
  536. // 43972 : Static crosscutting makes interfaces unusable for javac
  537. // ret.makeSynthetic();
  538. return ret;
  539. }
  540. protected FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) {
  541. return new FieldGen(
  542. member.getModifiers(),
  543. BcelWorld.makeBcelType(member.getReturnType()),
  544. member.getName(),
  545. gen.getConstantPoolGen());
  546. }
  547. private boolean mungePerObjectInterface(
  548. BcelClassWeaver weaver,
  549. PerObjectInterfaceTypeMunger munger)
  550. {
  551. LazyClassGen gen = weaver.getLazyClassGen();
  552. if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
  553. FieldGen fg = makeFieldGen(gen,
  554. AjcMemberMaker.perObjectField(gen.getType(), aspectType));
  555. gen.addField(fg.getField(),getSourceLocation());
  556. Type fieldType = BcelWorld.makeBcelType(aspectType);
  557. LazyMethodGen mg = new LazyMethodGen(
  558. Modifier.PUBLIC,
  559. fieldType,
  560. NameMangler.perObjectInterfaceGet(aspectType),
  561. new Type[0], new String[0],
  562. gen);
  563. InstructionList il = new InstructionList();
  564. InstructionFactory fact = gen.getFactory();
  565. il.append(InstructionConstants.ALOAD_0);
  566. il.append(fact.createFieldAccess(
  567. gen.getClassName(),
  568. fg.getName(),
  569. fieldType, Constants.GETFIELD));
  570. il.append(InstructionFactory.createReturn(fieldType));
  571. mg.getBody().insert(il);
  572. gen.addMethodGen(mg);
  573. LazyMethodGen mg1 = new LazyMethodGen(
  574. Modifier.PUBLIC,
  575. Type.VOID,
  576. NameMangler.perObjectInterfaceSet(aspectType),
  577. new Type[]{fieldType,}, new String[0],
  578. gen);
  579. InstructionList il1 = new InstructionList();
  580. il1.append(InstructionConstants.ALOAD_0);
  581. il1.append(InstructionFactory.createLoad(fieldType, 1));
  582. il1.append(fact.createFieldAccess(
  583. gen.getClassName(),
  584. fg.getName(),
  585. fieldType, Constants.PUTFIELD));
  586. il1.append(InstructionFactory.createReturn(Type.VOID));
  587. mg1.getBody().insert(il1);
  588. gen.addMethodGen(mg1);
  589. gen.addInterface(munger.getInterfaceType(),getSourceLocation());
  590. return true;
  591. } else {
  592. return false;
  593. }
  594. }
  595. // PTWIMPL Add field to hold aspect instance and an accessor
  596. private boolean mungePerTypeWithinTransformer(BcelClassWeaver weaver) {
  597. LazyClassGen gen = weaver.getLazyClassGen();
  598. // if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
  599. // Add (to the target type) the field that will hold the aspect instance
  600. // e.g ajc$com_blah_SecurityAspect$ptwAspectInstance
  601. FieldGen fg = makeFieldGen(gen, AjcMemberMaker.perTypeWithinField(gen.getType(), aspectType));
  602. gen.addField(fg.getField(),getSourceLocation());
  603. // Add an accessor for this new field, the ajc$<aspectname>$localAspectOf() method
  604. // e.g. "public com_blah_SecurityAspect ajc$com_blah_SecurityAspect$localAspectOf()"
  605. Type fieldType = BcelWorld.makeBcelType(aspectType);
  606. LazyMethodGen mg = new LazyMethodGen(
  607. Modifier.PUBLIC | Modifier.STATIC,fieldType,
  608. NameMangler.perTypeWithinLocalAspectOf(aspectType),
  609. new Type[0], new String[0],gen);
  610. InstructionList il = new InstructionList();
  611. //PTWIMPL ?? Should check if it is null and throw NoAspectBoundException
  612. InstructionFactory fact = gen.getFactory();
  613. il.append(fact.createFieldAccess(
  614. gen.getClassName(),
  615. fg.getName(),
  616. fieldType, Constants.GETSTATIC));
  617. il.append(InstructionFactory.createReturn(fieldType));
  618. mg.getBody().insert(il);
  619. gen.addMethodGen(mg);
  620. return true;
  621. // } else {
  622. // return false;
  623. // }
  624. }
  625. // ??? Why do we have this method? I thought by now we would know if it matched or not
  626. private boolean couldMatch(
  627. BcelObjectType bcelObjectType,
  628. Pointcut pointcut) {
  629. return !bcelObjectType.isInterface();
  630. }
  631. private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) {
  632. ResolvedMember unMangledInterMethod = munger.getSignature();
  633. // do matching on the unMangled one, but actually add them to the mangled method
  634. ResolvedMember interMethodBody = munger.getInterMethodBody(aspectType);
  635. ResolvedMember interMethodDispatcher = munger.getInterMethodDispatcher(aspectType);
  636. LazyClassGen gen = weaver.getLazyClassGen();
  637. boolean mungingInterface = gen.isInterface();
  638. ResolvedType onType = weaver.getWorld().resolve(unMangledInterMethod.getDeclaringType(),munger.getSourceLocation());
  639. if (onType.isRawType()) onType = onType.getGenericType();
  640. boolean onInterface = onType.isInterface();
  641. if (onType.isAnnotation()) {
  642. signalError(WeaverMessages.ITDM_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
  643. return false;
  644. }
  645. if (onType.isEnum()) {
  646. signalError(WeaverMessages.ITDM_ON_ENUM_NOT_ALLOWED,weaver,onType);
  647. return false;
  648. }
  649. if (onInterface && gen.getLazyMethodGen(unMangledInterMethod.getName(), unMangledInterMethod.getSignature(),true) != null) {
  650. // this is ok, we could be providing the default implementation of a method
  651. // that the target has already declared
  652. return false;
  653. }
  654. if (onType.equals(gen.getType())) {
  655. ResolvedMember mangledInterMethod =
  656. AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface);
  657. LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod);
  658. if (mungingInterface) {
  659. // we want the modifiers of the ITD to be used for all *implementors* of the
  660. // interface, but the method itself we add to the interface must be public abstract
  661. mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
  662. }
  663. // pr98901
  664. // For copying the annotations across, we have to discover the real member in the aspect
  665. // which is holding them.
  666. if (weaver.getWorld().isInJava5Mode()){
  667. AnnotationX annotationsOnRealMember[] = null;
  668. ResolvedType toLookOn = aspectType;
  669. if (aspectType.isRawType()) toLookOn = aspectType.getGenericType();
  670. ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn,interMethodDispatcher);
  671. if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
  672. interMethodDispatcher+"' on aspect "+aspectType);
  673. annotationsOnRealMember = realMember.getAnnotations();
  674. if (annotationsOnRealMember!=null) {
  675. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  676. AnnotationX annotationX = annotationsOnRealMember[i];
  677. Annotation a = annotationX.getBcelAnnotation();
  678. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  679. mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
  680. }
  681. }
  682. // the below loop fixes the very special (and very stupid)
  683. // case where an aspect declares an annotation
  684. // on an ITD it declared on itself.
  685. List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods();
  686. for (Iterator i = allDecams.iterator(); i.hasNext();){
  687. DeclareAnnotation decaMC = (DeclareAnnotation) i.next();
  688. if (decaMC.matches(unMangledInterMethod,weaver.getWorld())
  689. && mg.getEnclosingClass().getType() == aspectType) {
  690. mg.addAnnotation(decaMC.getAnnotationX());
  691. }
  692. }
  693. }
  694. if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) {
  695. InstructionList body = mg.getBody();
  696. InstructionFactory fact = gen.getFactory();
  697. int pos = 0;
  698. if (!unMangledInterMethod.isStatic()) {
  699. body.append(InstructionFactory.createThis());
  700. pos++;
  701. }
  702. Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
  703. for (int i = 0, len = paramTypes.length; i < len; i++) {
  704. Type paramType = paramTypes[i];
  705. body.append(InstructionFactory.createLoad(paramType, pos));
  706. pos+=paramType.getSize();
  707. }
  708. body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody));
  709. body.append(
  710. InstructionFactory.createReturn(
  711. BcelWorld.makeBcelType(mangledInterMethod.getReturnType())));
  712. } else {
  713. //??? this is okay
  714. //if (!(mg.getBody() == null)) throw new RuntimeException("bas");
  715. }
  716. // XXX make sure to check that we set exceptions properly on this guy.
  717. weaver.addLazyMethodGen(mg);
  718. weaver.getLazyClassGen().warnOnAddedMethod(mg.getMethod(),getSignature().getSourceLocation());
  719. addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
  720. return true;
  721. } else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) {
  722. // This means the 'gen' should be the top most implementor
  723. // - if it is *not* then something went wrong after we worked
  724. // out that it was the top most implementor (see pr49657)
  725. if (!gen.getType().isTopmostImplementor(onType)) {
  726. ResolvedType rtx = gen.getType().getTopmostImplementor(onType);
  727. if (!rtx.isExposedToWeaver()) {
  728. ISourceLocation sLoc = munger.getSourceLocation();
  729. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  730. WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR,rtx,getAspectType().getName()),
  731. (sLoc==null?getAspectType().getSourceLocation():sLoc)));
  732. } else {
  733. // XXX what does this state mean?
  734. // We have incorrectly identified what is the top most implementor and its not because
  735. // a type wasn't exposed to the weaver
  736. }
  737. return false;
  738. } else {
  739. ResolvedMember mangledInterMethod =
  740. AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false);
  741. LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod);
  742. if (mungingInterface) {
  743. // we want the modifiers of the ITD to be used for all *implementors* of the
  744. // interface, but the method itself we add to the interface must be public abstract
  745. mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
  746. }
  747. Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
  748. Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType());
  749. InstructionList body = mg.getBody();
  750. InstructionFactory fact = gen.getFactory();
  751. int pos = 0;
  752. if (!mangledInterMethod.isStatic()) {
  753. body.append(InstructionFactory.createThis());
  754. pos++;
  755. }
  756. for (int i = 0, len = paramTypes.length; i < len; i++) {
  757. Type paramType = paramTypes[i];
  758. body.append(InstructionFactory.createLoad(paramType, pos));
  759. pos+=paramType.getSize();
  760. }
  761. body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody));
  762. body.append(InstructionFactory.createReturn(returnType));
  763. mg.definingType = onType;
  764. weaver.addOrReplaceLazyMethodGen(mg);
  765. addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
  766. return true;
  767. }
  768. } else {
  769. return false;
  770. }
  771. }
  772. private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor) {
  773. ResolvedMember aspectMethods[] = aspectType.getDeclaredMethods();
  774. UnresolvedType [] lookingForParams = lookingFor.getParameterTypes();
  775. ResolvedMember realMember = null;
  776. for (int i = 0; realMember==null && i < aspectMethods.length; i++) {
  777. ResolvedMember member = aspectMethods[i];
  778. if (member.getName().equals(lookingFor.getName())){
  779. UnresolvedType [] memberParams = member.getParameterTypes();
  780. if (memberParams.length == lookingForParams.length){
  781. boolean matchOK = true;
  782. for (int j = 0; j < memberParams.length && matchOK; j++){
  783. UnresolvedType memberParam = memberParams[j];
  784. UnresolvedType lookingForParam = lookingForParams[j].resolve(aspectType.getWorld());
  785. if (lookingForParam.isTypeVariableReference()) lookingForParam = lookingForParam.getUpperBound();
  786. if (!memberParam.equals(lookingForParam)){
  787. matchOK=false;
  788. }
  789. }
  790. if (matchOK) realMember = member;
  791. }
  792. }
  793. }
  794. return realMember;
  795. }
  796. private void addNeededSuperCallMethods(
  797. BcelClassWeaver weaver,
  798. ResolvedType onType,
  799. Set neededSuperCalls)
  800. {
  801. LazyClassGen gen = weaver.getLazyClassGen();
  802. for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext();) {
  803. ResolvedMember superMethod = (ResolvedMember) iter.next();
  804. if (weaver.addDispatchTarget(superMethod)) {
  805. //System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
  806. boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
  807. String dispatchName;
  808. if (isSuper)
  809. dispatchName =
  810. NameMangler.superDispatchMethod(onType, superMethod.getName());
  811. else
  812. dispatchName =
  813. NameMangler.protectedDispatchMethod(
  814. onType,
  815. superMethod.getName());
  816. LazyMethodGen dispatcher =
  817. makeDispatcher(
  818. gen,
  819. dispatchName,
  820. superMethod,
  821. weaver.getWorld(),
  822. isSuper);
  823. weaver.addLazyMethodGen(dispatcher);
  824. }
  825. }
  826. }
  827. private void signalError(String msgid,BcelClassWeaver weaver,UnresolvedType onType) {
  828. IMessage msg = MessageUtil.error(
  829. WeaverMessages.format(msgid,onType.getName()),getSourceLocation());
  830. weaver.getWorld().getMessageHandler().handleMessage(msg);
  831. }
  832. private boolean mungeNewConstructor(
  833. BcelClassWeaver weaver,
  834. NewConstructorTypeMunger newConstructorTypeMunger)
  835. {
  836. final LazyClassGen currentClass = weaver.getLazyClassGen();
  837. final InstructionFactory fact = currentClass.getFactory();
  838. ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor();
  839. ResolvedType onType = newConstructorMember.getDeclaringType().resolve(weaver.getWorld());
  840. if (onType.isRawType()) onType = onType.getGenericType();
  841. if (onType.isAnnotation()) {
  842. signalError(WeaverMessages.ITDC_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
  843. return false;
  844. }
  845. if (onType.isEnum()) {
  846. signalError(WeaverMessages.ITDC_ON_ENUM_NOT_ALLOWED,weaver,onType);
  847. return false;
  848. }
  849. if (! onType.equals(currentClass.getType())) return false;
  850. ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor();
  851. //int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount();
  852. LazyMethodGen mg =
  853. makeMethodGen(currentClass, newConstructorMember);
  854. mg.setEffectiveSignature(newConstructorTypeMunger.getSignature(),Shadow.ConstructorExecution,true);
  855. // pr98901
  856. // For copying the annotations across, we have to discover the real member in the aspect
  857. // which is holding them.
  858. if (weaver.getWorld().isInJava5Mode()){
  859. ResolvedMember interMethodDispatcher =AjcMemberMaker.postIntroducedConstructor(aspectType,onType,newConstructorTypeMunger.getSignature().getParameterTypes());
  860. AnnotationX annotationsOnRealMember[] = null;
  861. ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodDispatcher);
  862. if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
  863. interMethodDispatcher+"' on aspect "+aspectType);
  864. annotationsOnRealMember = realMember.getAnnotations();
  865. if (annotationsOnRealMember!=null) {
  866. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  867. AnnotationX annotationX = annotationsOnRealMember[i];
  868. Annotation a = annotationX.getBcelAnnotation();
  869. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  870. mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
  871. }
  872. }
  873. // the below loop fixes the very special (and very stupid)
  874. // case where an aspect declares an annotation
  875. // on an ITD it declared on itself.
  876. List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods();
  877. for (Iterator i = allDecams.iterator(); i.hasNext();){
  878. DeclareAnnotation decaMC = (DeclareAnnotation) i.next();
  879. if (decaMC.matches(explicitConstructor,weaver.getWorld())
  880. && mg.getEnclosingClass().getType() == aspectType) {
  881. mg.addAnnotation(decaMC.getAnnotationX());
  882. }
  883. }
  884. }
  885. currentClass.addMethodGen(mg);
  886. //weaver.addLazyMethodGen(freshConstructor);
  887. InstructionList body = mg.getBody();
  888. // add to body: push arts for call to pre, from actual args starting at 1 (skipping this), going to
  889. // declared argcount + 1
  890. UnresolvedType[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes();
  891. Type[] paramTypes = mg.getArgumentTypes();
  892. int frameIndex = 1;
  893. for (int i = 0, len = declaredParams.length; i < len; i++) {
  894. body.append(InstructionFactory.createLoad(paramTypes[i], frameIndex));
  895. frameIndex += paramTypes[i].getSize();
  896. }
  897. // do call to pre
  898. Member preMethod =
  899. AjcMemberMaker.preIntroducedConstructor(aspectType, onType, declaredParams);
  900. body.append(Utility.createInvoke(fact, null, preMethod));
  901. // create a local, and store return pre stuff into it.
  902. int arraySlot = mg.allocateLocal(1);
  903. body.append(InstructionFactory.createStore(Type.OBJECT, arraySlot));
  904. // put this on the stack
  905. body.append(InstructionConstants.ALOAD_0);
  906. // unpack pre args onto stack
  907. UnresolvedType[] superParamTypes = explicitConstructor.getParameterTypes();
  908. for (int i = 0, len = superParamTypes.length; i < len; i++) {
  909. body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
  910. body.append(Utility.createConstant(fact, i));
  911. body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
  912. body.append(
  913. Utility.createConversion(
  914. fact,
  915. Type.OBJECT,
  916. BcelWorld.makeBcelType(superParamTypes[i])));
  917. }
  918. // call super/this
  919. body.append(Utility.createInvoke(fact, null, explicitConstructor));
  920. // put this back on the stack
  921. body.append(InstructionConstants.ALOAD_0);
  922. // unpack params onto stack
  923. Member postMethod =
  924. AjcMemberMaker.postIntroducedConstructor(aspectType, onType, declaredParams);
  925. UnresolvedType[] postParamTypes = postMethod.getParameterTypes();
  926. for (int i = 1, len = postParamTypes.length; i < len; i++) {
  927. body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
  928. body.append(Utility.createConstant(fact, superParamTypes.length + i-1));
  929. body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
  930. body.append(
  931. Utility.createConversion(
  932. fact,
  933. Type.OBJECT,
  934. BcelWorld.makeBcelType(postParamTypes[i])));
  935. }
  936. // call post
  937. body.append(Utility.createInvoke(fact, null, postMethod));
  938. // don't forget to return!!
  939. body.append(InstructionConstants.RETURN);
  940. return true;
  941. }
  942. private static LazyMethodGen makeDispatcher(
  943. LazyClassGen onGen,
  944. String dispatchName,
  945. ResolvedMember superMethod,
  946. BcelWorld world,
  947. boolean isSuper)
  948. {
  949. Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
  950. Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
  951. int modifiers = Modifier.PUBLIC;
  952. if (onGen.isInterface()) modifiers |= Modifier.ABSTRACT;
  953. LazyMethodGen mg =
  954. new LazyMethodGen(
  955. modifiers,
  956. returnType,
  957. dispatchName,
  958. paramTypes,
  959. UnresolvedType.getNames(superMethod.getExceptions()),
  960. onGen);
  961. InstructionList body = mg.getBody();
  962. if (onGen.isInterface()) return mg;
  963. // assert (!superMethod.isStatic())
  964. InstructionFactory fact = onGen.getFactory();
  965. int pos = 0;
  966. body.append(InstructionFactory.createThis());
  967. pos++;
  968. for (int i = 0, len = paramTypes.length; i < len; i++) {
  969. Type paramType = paramTypes[i];
  970. body.append(InstructionFactory.createLoad(paramType, pos));
  971. pos+=paramType.getSize();
  972. }
  973. if (isSuper) {
  974. body.append(Utility.createSuperInvoke(fact, world, superMethod));
  975. } else {
  976. body.append(Utility.createInvoke(fact, world, superMethod));
  977. }
  978. body.append(InstructionFactory.createReturn(returnType));
  979. return mg;
  980. }
  981. private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) {
  982. /*ResolvedMember initMethod = */munger.getInitMethod(aspectType);
  983. LazyClassGen gen = weaver.getLazyClassGen();
  984. ResolvedMember field = munger.getSignature();
  985. ResolvedType onType = weaver.getWorld().resolve(field.getDeclaringType(),munger.getSourceLocation());
  986. if (onType.isRawType()) onType = onType.getGenericType();
  987. boolean onInterface = onType.isInterface();
  988. if (onType.isAnnotation()) {
  989. signalError(WeaverMessages.ITDF_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
  990. return false;
  991. }
  992. if (onType.isEnum()) {
  993. signalError(WeaverMessages.ITDF_ON_ENUM_NOT_ALLOWED,weaver,onType);
  994. return false;
  995. }
  996. ResolvedMember interMethodBody = munger.getInitMethod(aspectType);
  997. AnnotationX annotationsOnRealMember[] = null;
  998. // pr98901
  999. // For copying the annotations across, we have to discover the real member in the aspect
  1000. // which is holding them.
  1001. if (weaver.getWorld().isInJava5Mode()){
  1002. // the below line just gets the method with the same name in aspectType.getDeclaredMethods();
  1003. ResolvedType toLookOn = aspectType;
  1004. if (aspectType.isRawType()) toLookOn = aspectType.getGenericType();
  1005. ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn,interMethodBody);
  1006. if (realMember==null) throw new BCException("Couldn't find ITD init member '"+
  1007. interMethodBody+"' on aspect "+aspectType);
  1008. annotationsOnRealMember = realMember.getAnnotations();
  1009. }
  1010. if (onType.equals(gen.getType())) {
  1011. if (onInterface) {
  1012. LazyMethodGen mg = makeMethodGen(gen,
  1013. AjcMemberMaker.interFieldInterfaceGetter(field, onType, aspectType));
  1014. gen.addMethodGen(mg);
  1015. LazyMethodGen mg1 = makeMethodGen(gen,
  1016. AjcMemberMaker.interFieldInterfaceSetter(field, onType, aspectType));
  1017. gen.addMethodGen(mg1);
  1018. } else {
  1019. weaver.addInitializer(this);
  1020. FieldGen fg = makeFieldGen(gen,
  1021. AjcMemberMaker.interFieldClassField(field, aspectType));
  1022. if (annotationsOnRealMember!=null) {
  1023. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  1024. AnnotationX annotationX = annotationsOnRealMember[i];
  1025. Annotation a = annotationX.getBcelAnnotation();
  1026. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  1027. fg.addAnnotation(ag);
  1028. }
  1029. }
  1030. gen.addField(fg.getField(),getSourceLocation());
  1031. }
  1032. return true;
  1033. } else if (onInterface && gen.getType().isTopmostImplementor(onType)) {
  1034. // wew know that we can't be static since we don't allow statics on interfaces
  1035. if (field.isStatic()) throw new RuntimeException("unimplemented");
  1036. weaver.addInitializer(this);
  1037. //System.err.println("impl body on " + gen.getType() + " for " + munger);
  1038. Type fieldType = BcelWorld.makeBcelType(field.getType());
  1039. FieldGen fg = makeFieldGen(gen,
  1040. AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));
  1041. gen.addField(fg.getField(),getSourceLocation());
  1042. //this uses a shadow munger to add init method to constructors
  1043. //weaver.getShadowMungers().add(makeInitCallShadowMunger(initMethod));
  1044. LazyMethodGen mg = makeMethodGen(gen,
  1045. AjcMemberMaker.interFieldInterfaceGetter(field, gen.getType(), aspectType));
  1046. InstructionList il = new InstructionList();
  1047. InstructionFactory fact = gen.getFactory();
  1048. if (field.isStatic()) {
  1049. il.append(fact.createFieldAccess(
  1050. gen.getClassName(),
  1051. fg.getName(),
  1052. fieldType, Constants.GETSTATIC));
  1053. } else {
  1054. il.append(InstructionConstants.ALOAD_0);
  1055. il.append(fact.createFieldAccess(
  1056. gen.getClassName(),
  1057. fg.getName(),
  1058. fieldType, Constants.GETFIELD));
  1059. }
  1060. il.append(InstructionFactory.createReturn(fieldType));
  1061. mg.getBody().insert(il);
  1062. gen.addMethodGen(mg);
  1063. LazyMethodGen mg1 = makeMethodGen(gen,
  1064. AjcMemberMaker.interFieldInterfaceSetter(field, gen.getType(), aspectType));
  1065. InstructionList il1 = new InstructionList();
  1066. if (field.isStatic()) {
  1067. il1.append(InstructionFactory.createLoad(fieldType, 0));
  1068. il1.append(fact.createFieldAccess(
  1069. gen.getClassName(),
  1070. fg.getName(),
  1071. fieldType, Constants.PUTSTATIC));
  1072. } else {
  1073. il1.append(InstructionConstants.ALOAD_0);
  1074. il1.append(InstructionFactory.createLoad(fieldType, 1));
  1075. il1.append(fact.createFieldAccess(
  1076. gen.getClassName(),
  1077. fg.getName(),
  1078. fieldType, Constants.PUTFIELD));
  1079. }
  1080. il1.append(InstructionFactory.createReturn(Type.VOID));
  1081. mg1.getBody().insert(il1);
  1082. gen.addMethodGen(mg1);
  1083. return true;
  1084. } else {
  1085. return false;
  1086. }
  1087. }
  1088. }