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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Alexandre Vasseur @AspectJ ITDs
  12. * ******************************************************************/
  13. package org.aspectj.weaver.bcel;
  14. import java.lang.reflect.Modifier;
  15. import java.util.Iterator;
  16. import java.util.List;
  17. import java.util.Set;
  18. import org.aspectj.apache.bcel.Constants;
  19. import org.aspectj.apache.bcel.classfile.annotation.Annotation;
  20. import org.aspectj.apache.bcel.generic.BranchInstruction;
  21. import org.aspectj.apache.bcel.generic.ConstantPoolGen;
  22. import org.aspectj.apache.bcel.generic.FieldGen;
  23. import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
  24. import org.aspectj.apache.bcel.generic.InstructionConstants;
  25. import org.aspectj.apache.bcel.generic.InstructionFactory;
  26. import org.aspectj.apache.bcel.generic.InstructionHandle;
  27. import org.aspectj.apache.bcel.generic.InstructionList;
  28. import org.aspectj.apache.bcel.generic.Type;
  29. import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
  30. import org.aspectj.asm.AsmManager;
  31. import org.aspectj.bridge.IMessage;
  32. import org.aspectj.bridge.ISourceLocation;
  33. import org.aspectj.bridge.Message;
  34. import org.aspectj.bridge.MessageUtil;
  35. import org.aspectj.bridge.WeaveMessage;
  36. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  37. import org.aspectj.bridge.context.ContextToken;
  38. import org.aspectj.weaver.AjcMemberMaker;
  39. import org.aspectj.weaver.AnnotationOnTypeMunger;
  40. import org.aspectj.weaver.AnnotationX;
  41. import org.aspectj.weaver.AsmRelationshipProvider;
  42. import org.aspectj.weaver.BCException;
  43. import org.aspectj.weaver.ConcreteTypeMunger;
  44. import org.aspectj.weaver.Member;
  45. import org.aspectj.weaver.MethodDelegateTypeMunger;
  46. import org.aspectj.weaver.NameMangler;
  47. import org.aspectj.weaver.NewConstructorTypeMunger;
  48. import org.aspectj.weaver.NewFieldTypeMunger;
  49. import org.aspectj.weaver.NewMethodTypeMunger;
  50. import org.aspectj.weaver.NewParentTypeMunger;
  51. import org.aspectj.weaver.PerObjectInterfaceTypeMunger;
  52. import org.aspectj.weaver.PrivilegedAccessMunger;
  53. import org.aspectj.weaver.ResolvedMember;
  54. import org.aspectj.weaver.ResolvedType;
  55. import org.aspectj.weaver.ResolvedTypeMunger;
  56. import org.aspectj.weaver.Shadow;
  57. import org.aspectj.weaver.TypeVariableReference;
  58. import org.aspectj.weaver.UnresolvedType;
  59. import org.aspectj.weaver.WeaverMessages;
  60. import org.aspectj.weaver.WeaverStateInfo;
  61. import org.aspectj.weaver.World;
  62. import org.aspectj.weaver.patterns.DeclareAnnotation;
  63. import org.aspectj.weaver.patterns.Pointcut;
  64. //XXX addLazyMethodGen is probably bad everywhere
  65. public class BcelTypeMunger extends ConcreteTypeMunger {
  66. public BcelTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
  67. super(munger, aspectType);
  68. }
  69. public String toString() {
  70. return "(BcelTypeMunger " + getMunger() + ")";
  71. }
  72. public boolean munge(BcelClassWeaver weaver) {
  73. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MUNGING_WITH, this);
  74. boolean changed = false;
  75. boolean worthReporting = true;
  76. if (munger.getKind() == ResolvedTypeMunger.Field) {
  77. changed = mungeNewField(weaver, (NewFieldTypeMunger)munger);
  78. } else if (munger.getKind() == ResolvedTypeMunger.Method) {
  79. changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger);
  80. } else if (munger.getKind() == ResolvedTypeMunger.MethodDelegate) {
  81. changed = mungeMethodDelegate(weaver, (MethodDelegateTypeMunger)munger);
  82. } else if (munger.getKind() == ResolvedTypeMunger.FieldHost) {
  83. changed = mungeFieldHost(weaver, (MethodDelegateTypeMunger.FieldHostTypeMunger)munger);
  84. } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
  85. changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger);
  86. worthReporting = false;
  87. } else if (munger.getKind() == ResolvedTypeMunger.PerTypeWithinInterface) {
  88. // PTWIMPL Transform the target type (add the aspect instance field)
  89. changed = mungePerTypeWithinTransformer(weaver);
  90. worthReporting = false;
  91. } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
  92. changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger);
  93. worthReporting = false;
  94. } else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
  95. changed = mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger);
  96. } else if (munger.getKind() == ResolvedTypeMunger.Parent) {
  97. changed = mungeNewParent(weaver, (NewParentTypeMunger)munger);
  98. } else if (munger.getKind() == ResolvedTypeMunger.AnnotationOnType) {
  99. changed = mungeNewAnnotationOnType(weaver,(AnnotationOnTypeMunger)munger);
  100. worthReporting=false;
  101. } else {
  102. throw new RuntimeException("unimplemented");
  103. }
  104. if (changed && munger.changesPublicSignature()) {
  105. WeaverStateInfo info =
  106. weaver.getLazyClassGen().getOrCreateWeaverStateInfo(BcelClassWeaver.getReweavableMode());
  107. info.addConcreteMunger(this);
  108. }
  109. if (changed && worthReporting) {
  110. if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
  111. AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType());
  112. } else {
  113. AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType());
  114. }
  115. }
  116. // TAG: WeavingMessage
  117. if (changed && worthReporting && munger!=null && !weaver.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
  118. String tName = weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getName();
  119. if (tName.indexOf("no debug info available")!=-1) tName = "no debug info available";
  120. else tName = getShortname(weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getPath());
  121. String fName = getShortname(getAspectType().getSourceLocation().getSourceFile().getPath());
  122. if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
  123. // This message could come out of AjLookupEnvironment.addParent if doing parents
  124. // munging at compile time only...
  125. NewParentTypeMunger parentTM = (NewParentTypeMunger)munger;
  126. if (parentTM.getNewParent().isInterface()) {
  127. weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,
  128. new String[]{weaver.getLazyClassGen().getType().getName(),
  129. tName,parentTM.getNewParent().getName(),fName},
  130. weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
  131. } else {
  132. weaver.getWorld().getMessageHandler().handleMessage(
  133. WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,
  134. new String[]{weaver.getLazyClassGen().getType().getName(),
  135. tName,parentTM.getNewParent().getName(),fName
  136. }));
  137. // TAG: WeavingMessage DECLARE PARENTS: EXTENDS
  138. // reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
  139. }
  140. } else if (munger.getKind().equals(ResolvedTypeMunger.FieldHost)) {
  141. ;//hidden
  142. } else {
  143. ResolvedMember declaredSig = munger.getDeclaredSignature();
  144. if (declaredSig==null) declaredSig= munger.getSignature();
  145. weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD,
  146. new String[]{weaver.getLazyClassGen().getType().getName(),
  147. tName,munger.getKind().toString().toLowerCase(),
  148. getAspectType().getName(),
  149. fName+":'"+declaredSig+"'"},
  150. weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
  151. }
  152. }
  153. CompilationAndWeavingContext.leavingPhase(tok);
  154. return changed;
  155. }
  156. private String getShortname(String path) {
  157. int takefrom = path.lastIndexOf('/');
  158. if (takefrom == -1) {
  159. takefrom = path.lastIndexOf('\\');
  160. }
  161. return path.substring(takefrom+1);
  162. }
  163. private boolean mungeNewAnnotationOnType(BcelClassWeaver weaver,AnnotationOnTypeMunger munger) {
  164. // FIXME asc this has already been done up front, need to do it here too?
  165. weaver.getLazyClassGen().addAnnotation(munger.getNewAnnotation().getBcelAnnotation());
  166. return true;
  167. }
  168. /**
  169. * For a long time, AspectJ did not allow binary weaving of declare parents. This restriction is now lifted
  170. * but could do with more testing!
  171. */
  172. private boolean mungeNewParent(BcelClassWeaver weaver, NewParentTypeMunger munger) {
  173. LazyClassGen newParentTarget = weaver.getLazyClassGen();
  174. ResolvedType newParent = munger.getNewParent();
  175. boolean cont = true; // Set to false when we error, so we don't actually *do* the munge
  176. cont = enforceDecpRule1_abstractMethodsImplemented(weaver, munger.getSourceLocation(),newParentTarget, newParent);
  177. cont = enforceDecpRule2_cantExtendFinalClass(weaver,munger.getSourceLocation(),newParentTarget,newParent) && cont;
  178. List methods = newParent.getMethodsWithoutIterator(false,true);
  179. for (Iterator iter = methods.iterator(); iter.hasNext();) {
  180. ResolvedMember superMethod = (ResolvedMember) iter.next();
  181. if (!superMethod.getName().equals("<init>")) {
  182. LazyMethodGen subMethod = findMatchingMethod(newParentTarget, superMethod);
  183. if (subMethod!=null && !subMethod.isBridgeMethod()) { // FIXME asc is this safe for all bridge methods?
  184. if (!(subMethod.isSynthetic() && superMethod.isSynthetic())) {
  185. if (!(subMethod.isStatic() && subMethod.getName().startsWith("access$"))) { // ignore generated accessors
  186. cont = enforceDecpRule3_visibilityChanges(weaver, newParent, superMethod, subMethod) && cont;
  187. cont = enforceDecpRule4_compatibleReturnTypes(weaver, superMethod, subMethod) && cont;
  188. cont = enforceDecpRule5_cantChangeFromStaticToNonstatic(weaver,munger.getSourceLocation(),superMethod,subMethod) && cont;
  189. }
  190. }
  191. }
  192. }
  193. }
  194. if (!cont) return false; // A rule was violated and an error message already reported
  195. if (newParent.isClass()) { // Changing the supertype
  196. if (!attemptToModifySuperCalls(weaver,newParentTarget,newParent)) return false;
  197. newParentTarget.setSuperClass(newParent);
  198. } else { // Adding a new interface
  199. newParentTarget.addInterface(newParent,getSourceLocation());
  200. }
  201. return true;
  202. }
  203. /**
  204. * Rule 1: For the declare parents to be allowed, the target type must override and implement
  205. * inherited abstract methods (if the type is not declared abstract)
  206. */
  207. private boolean enforceDecpRule1_abstractMethodsImplemented(BcelClassWeaver weaver, ISourceLocation mungerLoc,LazyClassGen newParentTarget, ResolvedType newParent) {
  208. boolean ruleCheckingSucceeded = true;
  209. if (!(newParentTarget.isAbstract() || newParentTarget.isInterface())) { // Ignore abstract classes or interfaces
  210. List methods = newParent.getMethodsWithoutIterator(false,true);
  211. for (Iterator i = methods.iterator(); i.hasNext();) {
  212. ResolvedMember o = (ResolvedMember)i.next();
  213. if (o.isAbstract() && !o.getName().startsWith("ajc$interField")) { // Ignore abstract methods of ajc$interField prefixed methods
  214. ResolvedMember discoveredImpl = null;
  215. List newParentTargetMethods = newParentTarget.getType().getMethodsWithoutIterator(false,true);
  216. for (Iterator ii = newParentTargetMethods.iterator(); ii.hasNext() && discoveredImpl==null;) {
  217. ResolvedMember gen2 = (ResolvedMember) ii.next();
  218. if (gen2.getName().equals(o.getName()) &&
  219. gen2.getParameterSignature().equals(o.getParameterSignature()) && !gen2.isAbstract()) {
  220. discoveredImpl = gen2; // Found a valid implementation !
  221. }
  222. }
  223. if (discoveredImpl == null) {
  224. // didnt find a valid implementation, lets check the ITDs on this type to see if they satisfy it
  225. boolean satisfiedByITD = false;
  226. for (Iterator ii = newParentTarget.getType().getInterTypeMungersIncludingSupers().iterator(); ii.hasNext(); ) {
  227. ConcreteTypeMunger m = (ConcreteTypeMunger)ii.next();
  228. if (m.getMunger().getKind() == ResolvedTypeMunger.Method) {
  229. ResolvedMember sig = m.getSignature();
  230. if (!Modifier.isAbstract(sig.getModifiers())) {
  231. // If the ITD shares a type variable with some target type, we need to tailor it for that
  232. // type
  233. if (m.isTargetTypeParameterized()) {
  234. ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType();
  235. m = m.parameterizedFor(newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType));
  236. sig = m.getSignature(); // possible sig change when type parameters filled in
  237. }
  238. if (ResolvedType
  239. .matches(
  240. AjcMemberMaker.interMethod(
  241. sig,m.getAspectType(),sig.getDeclaringType().resolve(weaver.getWorld()).isInterface()),o)) {
  242. satisfiedByITD = true;
  243. }
  244. }
  245. } else if (m.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate) {
  246. satisfiedByITD = true;//AV - that should be enough, no need to check more
  247. }
  248. }
  249. if (!satisfiedByITD) {
  250. error(weaver,
  251. "The type " + newParentTarget.getName() + " must implement the inherited abstract method "+o.getDeclaringType()+"."+o.getName()+o.getParameterSignature(),
  252. newParentTarget.getType().getSourceLocation(),new ISourceLocation[]{o.getSourceLocation(),mungerLoc});
  253. ruleCheckingSucceeded=false;
  254. }
  255. }
  256. }
  257. }
  258. }
  259. return ruleCheckingSucceeded;
  260. }
  261. /**
  262. * Rule 2. Can't extend final types
  263. */
  264. private boolean enforceDecpRule2_cantExtendFinalClass(BcelClassWeaver weaver, ISourceLocation mungerLoc,
  265. LazyClassGen newParentTarget, ResolvedType newParent) {
  266. if (newParent.isFinal()) {
  267. error(weaver,"Cannot make type "+newParentTarget.getName()+" extend final class "+newParent.getName(),
  268. newParentTarget.getType().getSourceLocation(),
  269. new ISourceLocation[]{mungerLoc});
  270. return false;
  271. }
  272. return true;
  273. }
  274. /**
  275. * Rule 3. Can't narrow visibility of methods when overriding
  276. */
  277. private boolean enforceDecpRule3_visibilityChanges(BcelClassWeaver weaver, ResolvedType newParent, ResolvedMember superMethod, LazyMethodGen subMethod) {
  278. boolean cont = true;
  279. if (superMethod.isPublic()) {
  280. if (subMethod.isProtected() || subMethod.isDefault() || subMethod.isPrivate()) {
  281. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  282. "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
  283. superMethod.getSourceLocation()));
  284. cont=false;
  285. }
  286. } else if (superMethod.isProtected()) {
  287. if (subMethod.isDefault() || subMethod.isPrivate()) {
  288. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  289. "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
  290. superMethod.getSourceLocation()));
  291. cont=false;
  292. }
  293. } else if (superMethod.isDefault()) {
  294. if (subMethod.isPrivate()) {
  295. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  296. "Cannot reduce the visibility of the inherited method '"+superMethod+"' from "+newParent.getName(),
  297. superMethod.getSourceLocation()));
  298. cont=false;
  299. }
  300. }
  301. return cont;
  302. }
  303. /**
  304. * Rule 4. Can't have incompatible return types
  305. */
  306. private boolean enforceDecpRule4_compatibleReturnTypes(BcelClassWeaver weaver, ResolvedMember superMethod, LazyMethodGen subMethod) {
  307. boolean cont = true;
  308. String superReturnTypeSig = superMethod.getReturnType().getSignature();
  309. String subReturnTypeSig = subMethod.getReturnType().getSignature();
  310. superReturnTypeSig = superReturnTypeSig.replace('.','/');
  311. subReturnTypeSig = subReturnTypeSig.replace('.','/');
  312. if (!superReturnTypeSig.equals(subReturnTypeSig)) {
  313. // Allow for covariance - wish I could test this (need Java5...)
  314. ResolvedType subType = weaver.getWorld().resolve(subMethod.getReturnType());
  315. ResolvedType superType = weaver.getWorld().resolve(superMethod.getReturnType());
  316. if (!superType.isAssignableFrom(subType)) {
  317. ISourceLocation sloc = subMethod.getSourceLocation();
  318. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  319. "The return type is incompatible with "+superMethod.getDeclaringType()+"."+superMethod.getName()+superMethod.getParameterSignature(),
  320. subMethod.getSourceLocation()));
  321. // this just might be a better error message...
  322. // "The return type '"+subReturnTypeSig+"' is incompatible with the overridden method "+superMethod.getDeclaringType()+"."+
  323. // superMethod.getName()+superMethod.getParameterSignature()+" which returns '"+superReturnTypeSig+"'",
  324. cont=false;
  325. }
  326. }
  327. return cont;
  328. }
  329. /**
  330. * Rule5. Method overrides can't change the staticality (word?) - you can't override and make an instance
  331. * method static or override and make a static method an instance method.
  332. */
  333. private boolean enforceDecpRule5_cantChangeFromStaticToNonstatic(BcelClassWeaver weaver,ISourceLocation mungerLoc,ResolvedMember superMethod, LazyMethodGen subMethod ) {
  334. if (superMethod.isStatic() && !subMethod.isStatic()) {
  335. error(weaver,"This instance method "+subMethod.getName()+subMethod.getParameterSignature()+
  336. " cannot override the static method from "+superMethod.getDeclaringType().getName(),
  337. subMethod.getSourceLocation(),new ISourceLocation[]{mungerLoc});
  338. return false;
  339. } else if (!superMethod.isStatic() && subMethod.isStatic()) {
  340. error(weaver,"The static method "+subMethod.getName()+subMethod.getParameterSignature()+
  341. " cannot hide the instance method from "+superMethod.getDeclaringType().getName(),
  342. subMethod.getSourceLocation(),new ISourceLocation[]{mungerLoc});
  343. return false;
  344. }
  345. return true;
  346. }
  347. public void error(BcelClassWeaver weaver,String text,ISourceLocation primaryLoc,ISourceLocation[] extraLocs) {
  348. IMessage msg = new Message(text, primaryLoc, true, extraLocs);
  349. weaver.getWorld().getMessageHandler().handleMessage(msg);
  350. }
  351. private LazyMethodGen findMatchingMethod(LazyClassGen newParentTarget, ResolvedMember m) {
  352. LazyMethodGen found = null;
  353. // Search the type for methods overriding super methods (methods that come from the new parent)
  354. // Don't use the return value in the comparison as overriding doesnt
  355. for (Iterator i = newParentTarget.getMethodGens().iterator(); i.hasNext() && found==null;) {
  356. LazyMethodGen gen = (LazyMethodGen) i.next();
  357. if (gen.getName().equals(m.getName()) &&
  358. gen.getParameterSignature().equals(m.getParameterSignature())) {
  359. found = gen;
  360. }
  361. }
  362. return found;
  363. }
  364. /**
  365. * The main part of implementing declare parents extends. Modify super ctor calls to target the new type.
  366. */
  367. public boolean attemptToModifySuperCalls(BcelClassWeaver weaver,LazyClassGen newParentTarget, ResolvedType newParent) {
  368. String currentParent = newParentTarget.getSuperClassname();
  369. if (newParent.getGenericType()!=null) newParent = newParent.getGenericType(); // target new super calls at the generic type if its raw or parameterized
  370. List mgs = newParentTarget.getMethodGens();
  371. // Look for ctors to modify
  372. for (Iterator iter = mgs.iterator(); iter.hasNext();) {
  373. LazyMethodGen aMethod = (LazyMethodGen) iter.next();
  374. if (aMethod.getName().equals("<init>")) {
  375. InstructionList insList = aMethod.getBody();
  376. InstructionHandle handle = insList.getStart();
  377. while (handle!= null) {
  378. if (handle.getInstruction() instanceof INVOKESPECIAL) {
  379. ConstantPoolGen cpg = newParentTarget.getConstantPoolGen();
  380. INVOKESPECIAL invokeSpecial = (INVOKESPECIAL)handle.getInstruction();
  381. if (invokeSpecial.getClassName(cpg).equals(currentParent) && invokeSpecial.getMethodName(cpg).equals("<init>")) {
  382. // System.err.println("Transforming super call '<init>"+sp.getSignature(cpg)+"'");
  383. // 1. Check there is a ctor in the new parent with the same signature
  384. ResolvedMember newCtor = getConstructorWithSignature(newParent,invokeSpecial.getSignature(cpg));
  385. if (newCtor == null) {
  386. // 2. Check ITDCs to see if the necessary ctor is provided that way
  387. boolean satisfiedByITDC = false;
  388. for (Iterator ii = newParentTarget.getType().getInterTypeMungersIncludingSupers().iterator(); ii.hasNext() && !satisfiedByITDC; ) {
  389. ConcreteTypeMunger m = (ConcreteTypeMunger)ii.next();
  390. if (m.getMunger() instanceof NewConstructorTypeMunger) {
  391. if (m.getSignature().getSignature().equals(invokeSpecial.getSignature(cpg))) {
  392. satisfiedByITDC = true;
  393. }
  394. }
  395. }
  396. if (!satisfiedByITDC) {
  397. String csig = createReadableCtorSig(newParent, cpg, invokeSpecial);
  398. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  399. "Unable to modify hierarchy for "+newParentTarget.getClassName()+" - the constructor "+
  400. csig+" is missing",this.getSourceLocation()));
  401. return false;
  402. }
  403. }
  404. int idx = cpg.addMethodref(newParent.getName(), invokeSpecial.getMethodName(cpg), invokeSpecial.getSignature(cpg));
  405. invokeSpecial.setIndex(idx);
  406. }
  407. }
  408. handle = handle.getNext();
  409. }
  410. }
  411. }
  412. return true;
  413. }
  414. /**
  415. * Creates a nice signature for the ctor, something like "(int,Integer,String)"
  416. */
  417. private String createReadableCtorSig(ResolvedType newParent, ConstantPoolGen cpg, INVOKESPECIAL invokeSpecial) {
  418. StringBuffer sb = new StringBuffer();
  419. Type[] ctorArgs = invokeSpecial.getArgumentTypes(cpg);
  420. sb.append(newParent.getClassName());
  421. sb.append("(");
  422. for (int i = 0; i < ctorArgs.length; i++) {
  423. String argtype = ctorArgs[i].toString();
  424. if (argtype.lastIndexOf(".")!=-1)
  425. sb.append(argtype.substring(argtype.lastIndexOf(".")+1));
  426. else
  427. sb.append(argtype);
  428. if (i+1<ctorArgs.length) sb.append(",");
  429. }
  430. sb.append(")");
  431. return sb.toString();
  432. }
  433. private ResolvedMember getConstructorWithSignature(ResolvedType tx,String signature) {
  434. ResolvedMember[] mems = tx.getDeclaredJavaMethods();
  435. for (int i = 0; i < mems.length; i++) {
  436. ResolvedMember rm = mems[i];
  437. if (rm.getName().equals("<init>")) {
  438. if (rm.getSignature().equals(signature)) return rm;
  439. }
  440. }
  441. return null;
  442. }
  443. private boolean mungePrivilegedAccess(
  444. BcelClassWeaver weaver,
  445. PrivilegedAccessMunger munger)
  446. {
  447. LazyClassGen gen = weaver.getLazyClassGen();
  448. ResolvedMember member = munger.getMember();
  449. ResolvedType onType = weaver.getWorld().resolve(member.getDeclaringType(),munger.getSourceLocation());
  450. if (onType.isRawType()) onType = onType.getGenericType();
  451. //System.out.println("munging: " + gen + " with " + member);
  452. if (onType.equals(gen.getType())) {
  453. if (member.getKind() == Member.FIELD) {
  454. //System.out.println("matched: " + gen);
  455. addFieldGetter(gen, member,
  456. AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member));
  457. addFieldSetter(gen, member,
  458. AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member));
  459. return true;
  460. } else if (member.getKind() == Member.METHOD) {
  461. addMethodDispatch(gen, member,
  462. AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
  463. return true;
  464. } else if (member.getKind() == Member.CONSTRUCTOR) {
  465. for (Iterator i = gen.getMethodGens().iterator(); i.hasNext(); ) {
  466. LazyMethodGen m = (LazyMethodGen)i.next();
  467. if (m.getMemberView() != null
  468. && m.getMemberView().getKind() == Member.CONSTRUCTOR) {
  469. // m.getMemberView().equals(member)) {
  470. m.forcePublic();
  471. //return true;
  472. }
  473. }
  474. return true;
  475. //throw new BCException("no match for " + member + " in " + gen);
  476. } else if (member.getKind() == Member.STATIC_INITIALIZATION) {
  477. gen.forcePublic();
  478. return true;
  479. } else {
  480. throw new RuntimeException("unimplemented");
  481. }
  482. }
  483. return false;
  484. }
  485. private void addFieldGetter(
  486. LazyClassGen gen,
  487. ResolvedMember field,
  488. ResolvedMember accessMethod)
  489. {
  490. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  491. InstructionList il = new InstructionList();
  492. InstructionFactory fact = gen.getFactory();
  493. if (field.isStatic()) {
  494. il.append(fact.createFieldAccess(
  495. gen.getClassName(),
  496. field.getName(),
  497. BcelWorld.makeBcelType(field.getType()), Constants.GETSTATIC));
  498. } else {
  499. il.append(InstructionConstants.ALOAD_0);
  500. il.append(fact.createFieldAccess(
  501. gen.getClassName(),
  502. field.getName(),
  503. BcelWorld.makeBcelType(field.getType()), Constants.GETFIELD));
  504. }
  505. il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(field.getType())));
  506. mg.getBody().insert(il);
  507. gen.addMethodGen(mg,getSignature().getSourceLocation());
  508. }
  509. private void addFieldSetter(
  510. LazyClassGen gen,
  511. ResolvedMember field,
  512. ResolvedMember accessMethod)
  513. {
  514. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  515. InstructionList il = new InstructionList();
  516. InstructionFactory fact = gen.getFactory();
  517. Type fieldType = BcelWorld.makeBcelType(field.getType());
  518. if (field.isStatic()) {
  519. il.append(InstructionFactory.createLoad(fieldType, 0));
  520. il.append(fact.createFieldAccess(
  521. gen.getClassName(),
  522. field.getName(),
  523. fieldType, Constants.PUTSTATIC));
  524. } else {
  525. il.append(InstructionConstants.ALOAD_0);
  526. il.append(InstructionFactory.createLoad(fieldType, 1));
  527. il.append(fact.createFieldAccess(
  528. gen.getClassName(),
  529. field.getName(),
  530. fieldType, Constants.PUTFIELD));
  531. }
  532. il.append(InstructionFactory.createReturn(Type.VOID));
  533. mg.getBody().insert(il);
  534. gen.addMethodGen(mg,getSignature().getSourceLocation());
  535. }
  536. private void addMethodDispatch(
  537. LazyClassGen gen,
  538. ResolvedMember method,
  539. ResolvedMember accessMethod)
  540. {
  541. LazyMethodGen mg = makeMethodGen(gen, accessMethod);
  542. InstructionList il = new InstructionList();
  543. InstructionFactory fact = gen.getFactory();
  544. //Type fieldType = BcelWorld.makeBcelType(field.getType());
  545. Type[] paramTypes = BcelWorld.makeBcelTypes(method.getParameterTypes());
  546. int pos = 0;
  547. if (!method.isStatic()) {
  548. il.append(InstructionConstants.ALOAD_0);
  549. pos++;
  550. }
  551. for (int i = 0, len = paramTypes.length; i < len; i++) {
  552. Type paramType = paramTypes[i];
  553. il.append(InstructionFactory.createLoad(paramType, pos));
  554. pos+=paramType.getSize();
  555. }
  556. il.append(Utility.createInvoke(fact, (BcelWorld)aspectType.getWorld(),
  557. method));
  558. il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(method.getReturnType())));
  559. mg.getBody().insert(il);
  560. gen.addMethodGen(mg);
  561. }
  562. protected LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) {
  563. LazyMethodGen ret = new LazyMethodGen(
  564. member.getModifiers(),
  565. BcelWorld.makeBcelType(member.getReturnType()),
  566. member.getName(),
  567. BcelWorld.makeBcelTypes(member.getParameterTypes()),
  568. UnresolvedType.getNames(member.getExceptions()),
  569. gen);
  570. // 43972 : Static crosscutting makes interfaces unusable for javac
  571. // ret.makeSynthetic();
  572. return ret;
  573. }
  574. protected FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) {
  575. return new FieldGen(
  576. member.getModifiers(),
  577. BcelWorld.makeBcelType(member.getReturnType()),
  578. member.getName(),
  579. gen.getConstantPoolGen());
  580. }
  581. private boolean mungePerObjectInterface(
  582. BcelClassWeaver weaver,
  583. PerObjectInterfaceTypeMunger munger)
  584. {
  585. //System.err.println("Munging perobject ["+munger+"] onto "+weaver.getLazyClassGen().getClassName());
  586. LazyClassGen gen = weaver.getLazyClassGen();
  587. if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
  588. FieldGen fg = makeFieldGen(gen,
  589. AjcMemberMaker.perObjectField(gen.getType(), aspectType));
  590. gen.addField(fg.getField(),getSourceLocation());
  591. Type fieldType = BcelWorld.makeBcelType(aspectType);
  592. LazyMethodGen mg = new LazyMethodGen(
  593. Modifier.PUBLIC,
  594. fieldType,
  595. NameMangler.perObjectInterfaceGet(aspectType),
  596. new Type[0], new String[0],
  597. gen);
  598. InstructionList il = new InstructionList();
  599. InstructionFactory fact = gen.getFactory();
  600. il.append(InstructionConstants.ALOAD_0);
  601. il.append(fact.createFieldAccess(
  602. gen.getClassName(),
  603. fg.getName(),
  604. fieldType, Constants.GETFIELD));
  605. il.append(InstructionFactory.createReturn(fieldType));
  606. mg.getBody().insert(il);
  607. gen.addMethodGen(mg);
  608. LazyMethodGen mg1 = new LazyMethodGen(
  609. Modifier.PUBLIC,
  610. Type.VOID,
  611. NameMangler.perObjectInterfaceSet(aspectType),
  612. new Type[]{fieldType,}, new String[0],
  613. gen);
  614. InstructionList il1 = new InstructionList();
  615. il1.append(InstructionConstants.ALOAD_0);
  616. il1.append(InstructionFactory.createLoad(fieldType, 1));
  617. il1.append(fact.createFieldAccess(
  618. gen.getClassName(),
  619. fg.getName(),
  620. fieldType, Constants.PUTFIELD));
  621. il1.append(InstructionFactory.createReturn(Type.VOID));
  622. mg1.getBody().insert(il1);
  623. gen.addMethodGen(mg1);
  624. gen.addInterface(munger.getInterfaceType(),getSourceLocation());
  625. return true;
  626. } else {
  627. return false;
  628. }
  629. }
  630. // PTWIMPL Add field to hold aspect instance and an accessor
  631. private boolean mungePerTypeWithinTransformer(BcelClassWeaver weaver) {
  632. LazyClassGen gen = weaver.getLazyClassGen();
  633. // if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
  634. // Add (to the target type) the field that will hold the aspect instance
  635. // e.g ajc$com_blah_SecurityAspect$ptwAspectInstance
  636. FieldGen fg = makeFieldGen(gen, AjcMemberMaker.perTypeWithinField(gen.getType(), aspectType));
  637. gen.addField(fg.getField(),getSourceLocation());
  638. // Add an accessor for this new field, the ajc$<aspectname>$localAspectOf() method
  639. // e.g. "public com_blah_SecurityAspect ajc$com_blah_SecurityAspect$localAspectOf()"
  640. Type fieldType = BcelWorld.makeBcelType(aspectType);
  641. LazyMethodGen mg = new LazyMethodGen(
  642. Modifier.PUBLIC | Modifier.STATIC,fieldType,
  643. NameMangler.perTypeWithinLocalAspectOf(aspectType),
  644. new Type[0], new String[0],gen);
  645. InstructionList il = new InstructionList();
  646. //PTWIMPL ?? Should check if it is null and throw NoAspectBoundException
  647. InstructionFactory fact = gen.getFactory();
  648. il.append(fact.createFieldAccess(
  649. gen.getClassName(),
  650. fg.getName(),
  651. fieldType, Constants.GETSTATIC));
  652. il.append(InstructionFactory.createReturn(fieldType));
  653. mg.getBody().insert(il);
  654. gen.addMethodGen(mg);
  655. return true;
  656. // } else {
  657. // return false;
  658. // }
  659. }
  660. // ??? Why do we have this method? I thought by now we would know if it matched or not
  661. private boolean couldMatch(
  662. BcelObjectType bcelObjectType,
  663. Pointcut pointcut) {
  664. return !bcelObjectType.isInterface();
  665. }
  666. private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) {
  667. World w = weaver.getWorld();
  668. // Resolving it will sort out the tvars
  669. ResolvedMember unMangledInterMethod = munger.getSignature().resolve(w);
  670. // do matching on the unMangled one, but actually add them to the mangled method
  671. ResolvedMember interMethodBody = munger.getDeclaredInterMethodBody(aspectType,w);
  672. ResolvedMember interMethodDispatcher = munger.getDeclaredInterMethodDispatcher(aspectType,w);
  673. ResolvedMember memberHoldingAnyAnnotations = interMethodDispatcher;
  674. ResolvedType onType = weaver.getWorld().resolve(unMangledInterMethod.getDeclaringType(),munger.getSourceLocation());
  675. LazyClassGen gen = weaver.getLazyClassGen();
  676. boolean mungingInterface = gen.isInterface();
  677. if (onType.isRawType()) onType = onType.getGenericType();
  678. boolean onInterface = onType.isInterface();
  679. // Simple checks, can't ITD on annotations or enums
  680. if (onType.isAnnotation()) {
  681. signalError(WeaverMessages.ITDM_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
  682. return false;
  683. }
  684. if (onType.isEnum()) {
  685. signalError(WeaverMessages.ITDM_ON_ENUM_NOT_ALLOWED,weaver,onType);
  686. return false;
  687. }
  688. if (onInterface && gen.getLazyMethodGen(unMangledInterMethod.getName(), unMangledInterMethod.getSignature(),true) != null) {
  689. // this is ok, we could be providing the default implementation of a method
  690. // that the target has already declared
  691. return false;
  692. }
  693. // If we are processing the intended ITD target type (might be an interface)
  694. if (onType.equals(gen.getType())) {
  695. ResolvedMember mangledInterMethod =
  696. AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface);
  697. LazyMethodGen newMethod = makeMethodGen(gen, mangledInterMethod);
  698. if (mungingInterface) {
  699. // we want the modifiers of the ITD to be used for all *implementors* of the
  700. // interface, but the method itself we add to the interface must be public abstract
  701. newMethod.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
  702. }
  703. // pr98901
  704. // For copying the annotations across, we have to discover the real member in the aspect
  705. // which is holding them.
  706. if (weaver.getWorld().isInJava5Mode()){
  707. AnnotationX annotationsOnRealMember[] = null;
  708. ResolvedType toLookOn = aspectType;
  709. if (aspectType.isRawType()) toLookOn = aspectType.getGenericType();
  710. ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn,memberHoldingAnyAnnotations,false);
  711. if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
  712. memberHoldingAnyAnnotations+"' on aspect "+aspectType);
  713. annotationsOnRealMember = realMember.getAnnotations();
  714. if (annotationsOnRealMember!=null) {
  715. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  716. AnnotationX annotationX = annotationsOnRealMember[i];
  717. Annotation a = annotationX.getBcelAnnotation();
  718. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  719. newMethod.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
  720. }
  721. }
  722. // the below loop fixes the very special (and very stupid)
  723. // case where an aspect declares an annotation
  724. // on an ITD it declared on itself.
  725. List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods();
  726. for (Iterator i = allDecams.iterator(); i.hasNext();){
  727. DeclareAnnotation decaMC = (DeclareAnnotation) i.next();
  728. if (decaMC.matches(unMangledInterMethod,weaver.getWorld())
  729. && newMethod.getEnclosingClass().getType() == aspectType) {
  730. newMethod.addAnnotation(decaMC.getAnnotationX());
  731. }
  732. }
  733. }
  734. // If it doesn't target an interface and there is a body (i.e. it isnt abstract)
  735. if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) {
  736. InstructionList body = newMethod.getBody();
  737. InstructionFactory fact = gen.getFactory();
  738. int pos = 0;
  739. if (!unMangledInterMethod.isStatic()) {
  740. body.append(InstructionFactory.createThis());
  741. pos++;
  742. }
  743. Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
  744. for (int i = 0, len = paramTypes.length; i < len; i++) {
  745. Type paramType = paramTypes[i];
  746. body.append(InstructionFactory.createLoad(paramType, pos));
  747. pos+=paramType.getSize();
  748. }
  749. body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody));
  750. body.append(
  751. InstructionFactory.createReturn(
  752. BcelWorld.makeBcelType(mangledInterMethod.getReturnType())));
  753. if (weaver.getWorld().isInJava5Mode()) { // Don't need bridge methods if not in 1.5 mode.
  754. createAnyBridgeMethodsForCovariance(weaver, munger, unMangledInterMethod, onType, gen, paramTypes);
  755. }
  756. } else {
  757. //??? this is okay
  758. //if (!(mg.getBody() == null)) throw new RuntimeException("bas");
  759. }
  760. // XXX make sure to check that we set exceptions properly on this guy.
  761. weaver.addLazyMethodGen(newMethod);
  762. weaver.getLazyClassGen().warnOnAddedMethod(newMethod.getMethod(),getSignature().getSourceLocation());
  763. addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
  764. return true;
  765. } else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) {
  766. // This means the 'gen' should be the top most implementor
  767. // - if it is *not* then something went wrong after we worked
  768. // out that it was the top most implementor (see pr49657)
  769. if (!gen.getType().isTopmostImplementor(onType)) {
  770. ResolvedType rtx = gen.getType().getTopmostImplementor(onType);
  771. if (!rtx.isExposedToWeaver()) {
  772. ISourceLocation sLoc = munger.getSourceLocation();
  773. weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
  774. WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR,rtx,getAspectType().getName()),
  775. (sLoc==null?getAspectType().getSourceLocation():sLoc)));
  776. } else {
  777. // XXX what does this state mean?
  778. // We have incorrectly identified what is the top most implementor and its not because
  779. // a type wasn't exposed to the weaver
  780. }
  781. return false;
  782. } else {
  783. ResolvedMember mangledInterMethod =
  784. AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false);
  785. LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod);
  786. // From 98901#29 - need to copy annotations across
  787. if (weaver.getWorld().isInJava5Mode()){
  788. AnnotationX annotationsOnRealMember[] = null;
  789. ResolvedType toLookOn = aspectType;
  790. if (aspectType.isRawType()) toLookOn = aspectType.getGenericType();
  791. ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn,memberHoldingAnyAnnotations,false);
  792. if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
  793. memberHoldingAnyAnnotations+"' on aspect "+aspectType);
  794. annotationsOnRealMember = realMember.getAnnotations();
  795. if (annotationsOnRealMember!=null) {
  796. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  797. AnnotationX annotationX = annotationsOnRealMember[i];
  798. Annotation a = annotationX.getBcelAnnotation();
  799. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  800. mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
  801. }
  802. }
  803. }
  804. if (mungingInterface) {
  805. // we want the modifiers of the ITD to be used for all *implementors* of the
  806. // interface, but the method itself we add to the interface must be public abstract
  807. mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
  808. }
  809. Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
  810. Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType());
  811. InstructionList body = mg.getBody();
  812. InstructionFactory fact = gen.getFactory();
  813. int pos = 0;
  814. if (!mangledInterMethod.isStatic()) {
  815. body.append(InstructionFactory.createThis());
  816. pos++;
  817. }
  818. for (int i = 0, len = paramTypes.length; i < len; i++) {
  819. Type paramType = paramTypes[i];
  820. body.append(InstructionFactory.createLoad(paramType, pos));
  821. pos+=paramType.getSize();
  822. }
  823. body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody));
  824. Type t= BcelWorld.makeBcelType(interMethodBody.getReturnType());
  825. if (!t.equals(returnType)) {
  826. body.append(fact.createCast(t,returnType));
  827. }
  828. body.append(InstructionFactory.createReturn(returnType));
  829. mg.definingType = onType;
  830. weaver.addOrReplaceLazyMethodGen(mg);
  831. addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
  832. // Work out if we need a bridge method for the new method added to the topmostimplementor.
  833. if (munger.getDeclaredSignature()!=null) { // Check if the munger being processed is a parameterized form of some original munger.
  834. boolean needsbridging = false;
  835. ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,munger.getSignature().getDeclaringType().resolve(getWorld()),false,munger.getTypeVariableAliases());
  836. if (!toBridgeTo.getReturnType().getErasureSignature().equals(munger.getSignature().getReturnType().getErasureSignature())) needsbridging = true;
  837. UnresolvedType[] originalParams = toBridgeTo.getParameterTypes();
  838. UnresolvedType[] newParams = munger.getSignature().getParameterTypes();
  839. for (int ii = 0;ii<originalParams.length;ii++) {
  840. if (!originalParams[ii].getErasureSignature().equals(newParams[ii].getErasureSignature())) needsbridging=true;
  841. }
  842. if (toBridgeTo!=null && needsbridging) {
  843. ResolvedMember bridgerMethod = AjcMemberMaker.bridgerToInterMethod(unMangledInterMethod,gen.getType());
  844. ResolvedMember bridgingSetter = AjcMemberMaker.interMethod(toBridgeTo, aspectType, false);
  845. // FIXME asc ----------------8<---------------- extract method
  846. LazyMethodGen bridgeMethod = makeMethodGen(gen,bridgingSetter);
  847. paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
  848. Type[] bridgingToParms = BcelWorld.makeBcelTypes(unMangledInterMethod.getParameterTypes());
  849. returnType = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
  850. body = bridgeMethod.getBody();
  851. fact = gen.getFactory();
  852. pos = 0;
  853. if (!bridgingSetter.isStatic()) {
  854. body.append(InstructionFactory.createThis());
  855. pos++;
  856. }
  857. for (int i = 0, len = paramTypes.length; i < len; i++) {
  858. Type paramType = paramTypes[i];
  859. body.append(InstructionFactory.createLoad(paramType, pos));
  860. if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(unMangledInterMethod.getParameterTypes()[i].getErasureSignature()) ) {
  861. // System.err.println("Putting in cast from "+paramType+" to "+bridgingToParms[i]);
  862. body.append(fact.createCast(paramType,bridgingToParms[i]));
  863. }
  864. pos+=paramType.getSize();
  865. }
  866. body.append(Utility.createInvoke(fact, weaver.getWorld(), bridgerMethod));
  867. body.append(InstructionFactory.createReturn(returnType));
  868. gen.addMethodGen(bridgeMethod);
  869. // mg.definingType = onType;
  870. // FIXME asc (see above) ---------------------8<--------------- extract method
  871. }
  872. }
  873. return true;
  874. }
  875. } else {
  876. return false;
  877. }
  878. }
  879. /**
  880. * Create any bridge method required because of covariant returns being used. This method is used in the case
  881. * where an ITD is applied to some type and it may be in an override relationship with a method from the supertype - but
  882. * due to covariance there is a mismatch in return values.
  883. * Example of when required:
  884. Super defines: Object m(String s)
  885. Sub defines: String m(String s)
  886. then we need a bridge method in Sub called 'Object m(String s)' that forwards to 'String m(String s)'
  887. */
  888. private void createAnyBridgeMethodsForCovariance(BcelClassWeaver weaver, NewMethodTypeMunger munger, ResolvedMember unMangledInterMethod, ResolvedType onType, LazyClassGen gen, Type[] paramTypes) {
  889. // PERFORMANCE BOTTLENECK? Might need investigating, method analysis between types in a hierarchy just seems expensive...
  890. // COVARIANCE BRIDGING
  891. // Algorithm: Step1. Check in this type - has someone already created the bridge method?
  892. // Step2. Look above us - do we 'override' a method and yet differ in return type (i.e. covariance)
  893. // Step3. Create a forwarding bridge method
  894. ResolvedType superclass = onType.getSuperclass();
  895. boolean quitRightNow = false;
  896. String localMethodName = unMangledInterMethod.getName();
  897. String localParameterSig = unMangledInterMethod.getParameterSignature();
  898. String localReturnTypeESig = unMangledInterMethod.getReturnType().getErasureSignature();
  899. // Step1
  900. boolean alreadyDone = false; // Compiler might have done it
  901. ResolvedMember[] localMethods = onType.getDeclaredMethods();
  902. for (int i = 0; i < localMethods.length; i++) {
  903. ResolvedMember member = localMethods[i];
  904. if (member.getName().equals(localMethodName)) {
  905. // Check the params
  906. if (member.getParameterSignature().equals(localParameterSig)) alreadyDone = true;
  907. }
  908. }
  909. // Step2
  910. if (!alreadyDone) {
  911. // Use the iterator form of 'getMethods()' so we do as little work as necessary
  912. for (Iterator iter = onType.getSuperclass().getMethods();iter.hasNext() && !quitRightNow;) {
  913. ResolvedMember aMethod = (ResolvedMember) iter.next();
  914. if (aMethod.getName().equals(localMethodName) && aMethod.getParameterSignature().equals(localParameterSig)) {
  915. // check the return types, if they are different we need a bridging method.
  916. if (!aMethod.getReturnType().getErasureSignature().equals(localReturnTypeESig) && !Modifier.isPrivate(aMethod.getModifiers())) {
  917. // Step3
  918. createBridgeMethod(weaver.getWorld(), munger, unMangledInterMethod, gen, paramTypes, aMethod);
  919. quitRightNow = true;
  920. }
  921. }
  922. }
  923. }
  924. }
  925. /**
  926. * Create a bridge method for a particular munger.
  927. * @param world
  928. * @param munger
  929. * @param unMangledInterMethod the method to bridge 'to' that we have already created in the 'subtype'
  930. * @param clazz the class in which to put the bridge method
  931. * @param paramTypes Parameter types for the bridge method, passed in as an optimization since the caller is likely to have already created them.
  932. * @param theBridgeMethod
  933. */
  934. private void createBridgeMethod(BcelWorld world, NewMethodTypeMunger munger,
  935. ResolvedMember unMangledInterMethod, LazyClassGen clazz, Type[] paramTypes, ResolvedMember theBridgeMethod) {
  936. InstructionList body;
  937. InstructionFactory fact;
  938. int pos = 0;
  939. LazyMethodGen bridgeMethod = makeMethodGen(clazz,theBridgeMethod); // The bridge method in this type will have the same signature as the one in the supertype
  940. bridgeMethod.setAccessFlags(bridgeMethod.getAccessFlags() | 0x00000040 /*BRIDGE = 0x00000040*/ );
  941. UnresolvedType[] newParams = munger.getSignature().getParameterTypes();
  942. Type returnType = BcelWorld.makeBcelType(theBridgeMethod.getReturnType());
  943. body = bridgeMethod.getBody();
  944. fact = clazz.getFactory();
  945. if (!unMangledInterMethod.isStatic()) {
  946. body.append(InstructionFactory.createThis());
  947. pos++;
  948. }
  949. for (int i = 0, len = paramTypes.length; i < len; i++) {
  950. Type paramType = paramTypes[i];
  951. body.append(InstructionFactory.createLoad(paramType, pos));
  952. // if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(unMangledInterMethod.getParameterTypes()[i].getErasureSignature())) {
  953. // System.err.println("Putting in cast from "+paramType+" to "+bridgingToParms[i]);
  954. // body.append(fact.createCast(paramType,bridgingToParms[i]));
  955. // }
  956. pos+=paramType.getSize();
  957. }
  958. body.append(Utility.createInvoke(fact, world,unMangledInterMethod));
  959. body.append(InstructionFactory.createReturn(returnType));
  960. clazz.addMethodGen(bridgeMethod);
  961. }
  962. private boolean mungeMethodDelegate(BcelClassWeaver weaver, MethodDelegateTypeMunger munger) {
  963. ResolvedMember introduced = munger.getSignature();
  964. LazyClassGen gen = weaver.getLazyClassGen();
  965. ResolvedType fromType = weaver.getWorld().resolve(introduced.getDeclaringType(),munger.getSourceLocation());
  966. if (fromType.isRawType()) fromType = fromType.getGenericType();
  967. if (gen.getType().isAnnotation() || gen.getType().isEnum()) {
  968. // don't signal error as it could be a consequence of a wild type pattern
  969. return false;
  970. }
  971. boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
  972. if (shouldApply) {
  973. LazyMethodGen mg = new LazyMethodGen(
  974. introduced.getModifiers() - Modifier.ABSTRACT,
  975. BcelWorld.makeBcelType(introduced.getReturnType()),
  976. introduced.getName(),
  977. BcelWorld.makeBcelTypes(introduced.getParameterTypes()),
  978. BcelWorld.makeBcelTypesAsClassNames(introduced.getExceptions()),
  979. gen
  980. );
  981. //annotation copy from annotation on ITD interface
  982. if (weaver.getWorld().isInJava5Mode()){
  983. AnnotationX annotationsOnRealMember[] = null;
  984. ResolvedType toLookOn = weaver.getWorld().lookupOrCreateName(introduced.getDeclaringType());
  985. if (fromType.isRawType()) toLookOn = fromType.getGenericType();
  986. // lookup the method
  987. ResolvedMember[] ms = toLookOn.getDeclaredJavaMethods();
  988. for (int i = 0; i < ms.length; i++) {
  989. ResolvedMember m = ms[i];
  990. if (introduced.getName().equals(m.getName()) && introduced.getSignature().equals(m.getSignature())) {
  991. annotationsOnRealMember = m.getAnnotations();
  992. }
  993. }
  994. if (annotationsOnRealMember!=null) {
  995. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  996. AnnotationX annotationX = annotationsOnRealMember[i];
  997. Annotation a = annotationX.getBcelAnnotation();
  998. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  999. mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
  1000. }
  1001. }
  1002. }
  1003. InstructionList body = new InstructionList();
  1004. InstructionFactory fact = gen.getFactory();
  1005. // getfield
  1006. body.append(InstructionConstants.ALOAD_0);
  1007. body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
  1008. BranchInstruction ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
  1009. body.append(ifNonNull);
  1010. // Create and store a new instance
  1011. body.append(InstructionConstants.ALOAD_0);
  1012. body.append(fact.createNew(munger.getImplClassName()));
  1013. body.append(InstructionConstants.DUP);
  1014. body.append(fact.createInvoke(munger.getImplClassName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
  1015. body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
  1016. // if not null use the instance we've got
  1017. InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0);
  1018. ifNonNull.setTarget(ifNonNullElse);
  1019. body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
  1020. //args
  1021. int pos = 0;
  1022. if (!introduced.isStatic()) { // skip 'this' (?? can this really happen)
  1023. //body.append(InstructionFactory.createThis());
  1024. pos++;
  1025. }
  1026. Type[] paramTypes = BcelWorld.makeBcelTypes(introduced.getParameterTypes());
  1027. for (int i = 0, len = paramTypes.length; i < len; i++) {
  1028. Type paramType = paramTypes[i];
  1029. body.append(InstructionFactory.createLoad(paramType, pos));
  1030. pos+=paramType.getSize();
  1031. }
  1032. body.append(Utility.createInvoke(fact, Constants.INVOKEINTERFACE, introduced));
  1033. body.append(
  1034. InstructionFactory.createReturn(
  1035. BcelWorld.makeBcelType(introduced.getReturnType())
  1036. )
  1037. );
  1038. mg.getBody().append(body);
  1039. weaver.addLazyMethodGen(mg);
  1040. weaver.getLazyClassGen().warnOnAddedMethod(mg.getMethod(),getSignature().getSourceLocation());
  1041. return true;
  1042. }
  1043. return false;
  1044. }
  1045. private boolean mungeFieldHost(BcelClassWeaver weaver, MethodDelegateTypeMunger.FieldHostTypeMunger munger) {
  1046. LazyClassGen gen = weaver.getLazyClassGen();
  1047. if (gen.getType().isAnnotation() || gen.getType().isEnum()) {
  1048. // don't signal error as it could be a consequence of a wild type pattern
  1049. return false;
  1050. }
  1051. boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
  1052. ResolvedMember host = AjcMemberMaker.itdAtDeclareParentsField(
  1053. weaver.getLazyClassGen().getType(),
  1054. munger.getSignature().getType(),
  1055. aspectType);
  1056. weaver.getLazyClassGen().addField(makeFieldGen(
  1057. weaver.getLazyClassGen(),
  1058. host).getField(), null);
  1059. return true;
  1060. }
  1061. private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor,boolean isCtorRelated) {
  1062. World world = aspectType.getWorld();
  1063. boolean debug = false;
  1064. if (debug) {
  1065. System.err.println("Searching for a member on type: "+aspectType);
  1066. System.err.println("Member we are looking for: "+lookingFor);
  1067. }
  1068. ResolvedMember aspectMethods[] = aspectType.getDeclaredMethods();
  1069. UnresolvedType [] lookingForParams = lookingFor.getParameterTypes();
  1070. ResolvedMember realMember = null;
  1071. for (int i = 0; realMember==null && i < aspectMethods.length; i++) {
  1072. ResolvedMember member = aspectMethods[i];
  1073. if (member.getName().equals(lookingFor.getName())){
  1074. UnresolvedType [] memberParams = member.getGenericParameterTypes();
  1075. if (memberParams.length == lookingForParams.length){
  1076. if (debug) System.err.println("Reviewing potential candidates: "+member);
  1077. boolean matchOK = true;
  1078. // If not related to a ctor ITD then the name is enough to confirm we have the
  1079. // right one. If it is ctor related we need to check the params all match, although
  1080. // only the erasure.
  1081. if (isCtorRelated) {
  1082. for (int j = 0; j < memberParams.length && matchOK; j++){
  1083. ResolvedType pMember = memberParams[j].resolve(world);
  1084. ResolvedType pLookingFor = lookingForParams[j].resolve(world);
  1085. if (pMember.isTypeVariableReference())
  1086. pMember = ((TypeVariableReference)pMember).getTypeVariable().getFirstBound().resolve(world);
  1087. if (pMember.isParameterizedType() || pMember.isGenericType())
  1088. pMember = pMember.getRawType().resolve(aspectType.getWorld());
  1089. if (pLookingFor.isTypeVariableReference())
  1090. pLookingFor = ((TypeVariableReference)pLookingFor).getTypeVariable().getFirstBound().resolve(world);
  1091. if (pLookingFor.isParameterizedType() || pLookingFor.isGenericType())
  1092. pLookingFor = pLookingFor.getRawType().resolve(world);
  1093. if (debug) System.err.println("Comparing parameter "+j+" member="+pMember+" lookingFor="+pLookingFor);
  1094. if (!pMember.equals(pLookingFor)){
  1095. matchOK=false;
  1096. }
  1097. }
  1098. }
  1099. if (matchOK) realMember = member;
  1100. }
  1101. }
  1102. }
  1103. if (debug && realMember==null) System.err.println("Didn't find a match");
  1104. return realMember;
  1105. }
  1106. private void addNeededSuperCallMethods(
  1107. BcelClassWeaver weaver,
  1108. ResolvedType onType,
  1109. Set neededSuperCalls)
  1110. {
  1111. LazyClassGen gen = weaver.getLazyClassGen();
  1112. for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext();) {
  1113. ResolvedMember superMethod = (ResolvedMember) iter.next();
  1114. if (weaver.addDispatchTarget(superMethod)) {
  1115. //System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
  1116. boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
  1117. String dispatchName;
  1118. if (isSuper)
  1119. dispatchName =
  1120. NameMangler.superDispatchMethod(onType, superMethod.getName());
  1121. else
  1122. dispatchName =
  1123. NameMangler.protectedDispatchMethod(
  1124. onType,
  1125. superMethod.getName());
  1126. LazyMethodGen dispatcher =
  1127. makeDispatcher(
  1128. gen,
  1129. dispatchName,
  1130. superMethod,
  1131. weaver.getWorld(),
  1132. isSuper);
  1133. weaver.addLazyMethodGen(dispatcher);
  1134. }
  1135. }
  1136. }
  1137. private void signalError(String msgid,BcelClassWeaver weaver,UnresolvedType onType) {
  1138. IMessage msg = MessageUtil.error(
  1139. WeaverMessages.format(msgid,onType.getName()),getSourceLocation());
  1140. weaver.getWorld().getMessageHandler().handleMessage(msg);
  1141. }
  1142. private boolean mungeNewConstructor(
  1143. BcelClassWeaver weaver,
  1144. NewConstructorTypeMunger newConstructorTypeMunger)
  1145. {
  1146. final LazyClassGen currentClass = weaver.getLazyClassGen();
  1147. final InstructionFactory fact = currentClass.getFactory();
  1148. ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor();
  1149. ResolvedType onType = newConstructorMember.getDeclaringType().resolve(weaver.getWorld());
  1150. if (onType.isRawType()) onType = onType.getGenericType();
  1151. if (onType.isAnnotation()) {
  1152. signalError(WeaverMessages.ITDC_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
  1153. return false;
  1154. }
  1155. if (onType.isEnum()) {
  1156. signalError(WeaverMessages.ITDC_ON_ENUM_NOT_ALLOWED,weaver,onType);
  1157. return false;
  1158. }
  1159. if (! onType.equals(currentClass.getType())) return false;
  1160. ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor();
  1161. //int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount();
  1162. LazyMethodGen mg =
  1163. makeMethodGen(currentClass, newConstructorMember);
  1164. mg.setEffectiveSignature(newConstructorTypeMunger.getSignature(),Shadow.ConstructorExecution,true);
  1165. // pr98901
  1166. // For copying the annotations across, we have to discover the real member in the aspect
  1167. // which is holding them.
  1168. if (weaver.getWorld().isInJava5Mode()){
  1169. ResolvedMember interMethodDispatcher =AjcMemberMaker.postIntroducedConstructor(aspectType,onType,newConstructorTypeMunger.getSignature().getParameterTypes());
  1170. AnnotationX annotationsOnRealMember[] = null;
  1171. ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodDispatcher,true);
  1172. if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
  1173. interMethodDispatcher+"' on aspect "+aspectType);
  1174. annotationsOnRealMember = realMember.getAnnotations();
  1175. if (annotationsOnRealMember!=null) {
  1176. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  1177. AnnotationX annotationX = annotationsOnRealMember[i];
  1178. Annotation a = annotationX.getBcelAnnotation();
  1179. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  1180. mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld()));
  1181. }
  1182. }
  1183. // the below loop fixes the very special (and very stupid)
  1184. // case where an aspect declares an annotation
  1185. // on an ITD it declared on itself.
  1186. List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods();
  1187. for (Iterator i = allDecams.iterator(); i.hasNext();){
  1188. DeclareAnnotation decaMC = (DeclareAnnotation) i.next();
  1189. if (decaMC.matches(explicitConstructor,weaver.getWorld())
  1190. && mg.getEnclosingClass().getType() == aspectType) {
  1191. mg.addAnnotation(decaMC.getAnnotationX());
  1192. }
  1193. }
  1194. }
  1195. currentClass.addMethodGen(mg);
  1196. //weaver.addLazyMethodGen(freshConstructor);
  1197. InstructionList body = mg.getBody();
  1198. // add to body: push arts for call to pre, from actual args starting at 1 (skipping this), going to
  1199. // declared argcount + 1
  1200. UnresolvedType[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes();
  1201. Type[] paramTypes = mg.getArgumentTypes();
  1202. int frameIndex = 1;
  1203. for (int i = 0, len = declaredParams.length; i < len; i++) {
  1204. body.append(InstructionFactory.createLoad(paramTypes[i], frameIndex));
  1205. frameIndex += paramTypes[i].getSize();
  1206. }
  1207. // do call to pre
  1208. Member preMethod =
  1209. AjcMemberMaker.preIntroducedConstructor(aspectType, onType, declaredParams);
  1210. body.append(Utility.createInvoke(fact, null, preMethod));
  1211. // create a local, and store return pre stuff into it.
  1212. int arraySlot = mg.allocateLocal(1);
  1213. body.append(InstructionFactory.createStore(Type.OBJECT, arraySlot));
  1214. // put this on the stack
  1215. body.append(InstructionConstants.ALOAD_0);
  1216. // unpack pre args onto stack
  1217. UnresolvedType[] superParamTypes = explicitConstructor.getParameterTypes();
  1218. for (int i = 0, len = superParamTypes.length; i < len; i++) {
  1219. body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
  1220. body.append(Utility.createConstant(fact, i));
  1221. body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
  1222. body.append(
  1223. Utility.createConversion(
  1224. fact,
  1225. Type.OBJECT,
  1226. BcelWorld.makeBcelType(superParamTypes[i])));
  1227. }
  1228. // call super/this
  1229. body.append(Utility.createInvoke(fact, null, explicitConstructor));
  1230. // put this back on the stack
  1231. body.append(InstructionConstants.ALOAD_0);
  1232. // unpack params onto stack
  1233. Member postMethod =
  1234. AjcMemberMaker.postIntroducedConstructor(aspectType, onType, declaredParams);
  1235. UnresolvedType[] postParamTypes = postMethod.getParameterTypes();
  1236. for (int i = 1, len = postParamTypes.length; i < len; i++) {
  1237. body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
  1238. body.append(Utility.createConstant(fact, superParamTypes.length + i-1));
  1239. body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
  1240. body.append(
  1241. Utility.createConversion(
  1242. fact,
  1243. Type.OBJECT,
  1244. BcelWorld.makeBcelType(postParamTypes[i])));
  1245. }
  1246. // call post
  1247. body.append(Utility.createInvoke(fact, null, postMethod));
  1248. // don't forget to return!!
  1249. body.append(InstructionConstants.RETURN);
  1250. return true;
  1251. }
  1252. private static LazyMethodGen makeDispatcher(
  1253. LazyClassGen onGen,
  1254. String dispatchName,
  1255. ResolvedMember superMethod,
  1256. BcelWorld world,
  1257. boolean isSuper)
  1258. {
  1259. Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
  1260. Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
  1261. int modifiers = Modifier.PUBLIC;
  1262. if (onGen.isInterface()) modifiers |= Modifier.ABSTRACT;
  1263. LazyMethodGen mg =
  1264. new LazyMethodGen(
  1265. modifiers,
  1266. returnType,
  1267. dispatchName,
  1268. paramTypes,
  1269. UnresolvedType.getNames(superMethod.getExceptions()),
  1270. onGen);
  1271. InstructionList body = mg.getBody();
  1272. if (onGen.isInterface()) return mg;
  1273. // assert (!superMethod.isStatic())
  1274. InstructionFactory fact = onGen.getFactory();
  1275. int pos = 0;
  1276. body.append(InstructionFactory.createThis());
  1277. pos++;
  1278. for (int i = 0, len = paramTypes.length; i < len; i++) {
  1279. Type paramType = paramTypes[i];
  1280. body.append(InstructionFactory.createLoad(paramType, pos));
  1281. pos+=paramType.getSize();
  1282. }
  1283. if (isSuper) {
  1284. body.append(Utility.createSuperInvoke(fact, world, superMethod));
  1285. } else {
  1286. body.append(Utility.createInvoke(fact, world, superMethod));
  1287. }
  1288. body.append(InstructionFactory.createReturn(returnType));
  1289. return mg;
  1290. }
  1291. private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) {
  1292. /*ResolvedMember initMethod = */munger.getInitMethod(aspectType);
  1293. LazyClassGen gen = weaver.getLazyClassGen();
  1294. ResolvedMember field = munger.getSignature();
  1295. ResolvedType onType = weaver.getWorld().resolve(field.getDeclaringType(),munger.getSourceLocation());
  1296. if (onType.isRawType()) onType = onType.getGenericType();
  1297. boolean onInterface = onType.isInterface();
  1298. if (onType.isAnnotation()) {
  1299. signalError(WeaverMessages.ITDF_ON_ANNOTATION_NOT_ALLOWED,weaver,onType);
  1300. return false;
  1301. }
  1302. if (onType.isEnum()) {
  1303. signalError(WeaverMessages.ITDF_ON_ENUM_NOT_ALLOWED,weaver,onType);
  1304. return false;
  1305. }
  1306. ResolvedMember interMethodBody = munger.getInitMethod(aspectType);
  1307. AnnotationX annotationsOnRealMember[] = null;
  1308. // pr98901
  1309. // For copying the annotations across, we have to discover the real member in the aspect
  1310. // which is holding them.
  1311. if (weaver.getWorld().isInJava5Mode()){
  1312. // the below line just gets the method with the same name in aspectType.getDeclaredMethods();
  1313. ResolvedType toLookOn = aspectType;
  1314. if (aspectType.isRawType()) toLookOn = aspectType.getGenericType();
  1315. ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn,interMethodBody,false);
  1316. if (realMember==null) throw new BCException("Couldn't find ITD init member '"+
  1317. interMethodBody+"' on aspect "+aspectType);
  1318. annotationsOnRealMember = realMember.getAnnotations();
  1319. }
  1320. if (onType.equals(gen.getType())) {
  1321. if (onInterface) {
  1322. ResolvedMember itdfieldGetter = AjcMemberMaker.interFieldInterfaceGetter(field, onType, aspectType);
  1323. LazyMethodGen mg = makeMethodGen(gen, itdfieldGetter);
  1324. gen.addMethodGen(mg);
  1325. LazyMethodGen mg1 = makeMethodGen(gen,
  1326. AjcMemberMaker.interFieldInterfaceSetter(field, onType, aspectType));
  1327. gen.addMethodGen(mg1);
  1328. } else {
  1329. weaver.addInitializer(this);
  1330. FieldGen fg = makeFieldGen(gen,
  1331. AjcMemberMaker.interFieldClassField(field, aspectType));
  1332. if (annotationsOnRealMember!=null) {
  1333. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  1334. AnnotationX annotationX = annotationsOnRealMember[i];
  1335. Annotation a = annotationX.getBcelAnnotation();
  1336. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  1337. fg.addAnnotation(ag);
  1338. }
  1339. }
  1340. gen.addField(fg.getField(),getSourceLocation());
  1341. }
  1342. return true;
  1343. } else if (onInterface && gen.getType().isTopmostImplementor(onType)) {
  1344. // wew know that we can't be static since we don't allow statics on interfaces
  1345. if (field.isStatic()) throw new RuntimeException("unimplemented");
  1346. weaver.addInitializer(this);
  1347. //System.err.println("impl body on " + gen.getType() + " for " + munger);
  1348. Type fieldType = BcelWorld.makeBcelType(field.getType());
  1349. FieldGen fg = makeFieldGen(gen,AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));
  1350. if (annotationsOnRealMember!=null) {
  1351. for (int i = 0; i < annotationsOnRealMember.length; i++) {
  1352. AnnotationX annotationX = annotationsOnRealMember[i];
  1353. Annotation a = annotationX.getBcelAnnotation();
  1354. AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true);
  1355. fg.addAnnotation(ag);
  1356. }
  1357. }
  1358. gen.addField(fg.getField(),getSourceLocation());
  1359. //this uses a shadow munger to add init method to constructors
  1360. //weaver.getShadowMungers().add(makeInitCallShadowMunger(initMethod));
  1361. ResolvedMember itdfieldGetter = AjcMemberMaker.interFieldInterfaceGetter(field, gen.getType()/*onType*/, aspectType);
  1362. LazyMethodGen mg = makeMethodGen(gen, itdfieldGetter);
  1363. InstructionList il = new InstructionList();
  1364. InstructionFactory fact = gen.getFactory();
  1365. if (field.isStatic()) {
  1366. il.append(fact.createFieldAccess(
  1367. gen.getClassName(),
  1368. fg.getName(),
  1369. fieldType, Constants.GETSTATIC));
  1370. } else {
  1371. il.append(InstructionConstants.ALOAD_0);
  1372. il.append(fact.createFieldAccess(
  1373. gen.getClassName(),
  1374. fg.getName(),
  1375. fieldType, Constants.GETFIELD));
  1376. }
  1377. il.append(InstructionFactory.createReturn(fieldType));
  1378. mg.getBody().insert(il);
  1379. gen.addMethodGen(mg);
  1380. // Check if we need bridge methods for the field getter and setter
  1381. if (munger.getDeclaredSignature()!=null) { // is this munger a parameterized form of some original munger?
  1382. ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,munger.getSignature().getDeclaringType().resolve(getWorld()),false,munger.getTypeVariableAliases());
  1383. boolean needsbridging = false;
  1384. if (!toBridgeTo.getReturnType().getErasureSignature().equals(munger.getSignature().getReturnType().getErasureSignature())) needsbridging = true;
  1385. if (toBridgeTo!=null && needsbridging) {
  1386. ResolvedMember bridgingGetter = AjcMemberMaker.interFieldInterfaceGetter(toBridgeTo, gen.getType(), aspectType);
  1387. createBridgeMethodForITDF(weaver,gen,itdfieldGetter,bridgingGetter);
  1388. }
  1389. }
  1390. ResolvedMember itdfieldSetter = AjcMemberMaker.interFieldInterfaceSetter(field, gen.getType(), aspectType);
  1391. LazyMethodGen mg1 = makeMethodGen(gen, itdfieldSetter);
  1392. InstructionList il1 = new InstructionList();
  1393. if (field.isStatic()) {
  1394. il1.append(InstructionFactory.createLoad(fieldType, 0));
  1395. il1.append(fact.createFieldAccess(
  1396. gen.getClassName(),
  1397. fg.getName(),
  1398. fieldType, Constants.PUTSTATIC));
  1399. } else {
  1400. il1.append(InstructionConstants.ALOAD_0);
  1401. il1.append(InstructionFactory.createLoad(fieldType, 1));
  1402. il1.append(fact.createFieldAccess(
  1403. gen.getClassName(),
  1404. fg.getName(),
  1405. fieldType, Constants.PUTFIELD));
  1406. }
  1407. il1.append(InstructionFactory.createReturn(Type.VOID));
  1408. mg1.getBody().insert(il1);
  1409. gen.addMethodGen(mg1);
  1410. if (munger.getDeclaredSignature()!=null) {
  1411. ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,munger.getSignature().getDeclaringType().resolve(getWorld()),false,munger.getTypeVariableAliases());
  1412. boolean needsbridging = false;
  1413. if (!toBridgeTo.getReturnType().getErasureSignature().equals(munger.getSignature().getReturnType().getErasureSignature())) needsbridging = true;
  1414. if (toBridgeTo!=null && needsbridging) {
  1415. ResolvedMember bridgingSetter = AjcMemberMaker.interFieldInterfaceSetter(toBridgeTo, gen.getType(), aspectType);
  1416. createBridgeMethodForITDF(weaver, gen, itdfieldSetter, bridgingSetter);
  1417. }
  1418. }
  1419. return true;
  1420. } else {
  1421. return false;
  1422. }
  1423. }
  1424. // FIXME asc combine with other createBridge.. method in this class, avoid the duplication...
  1425. private void createBridgeMethodForITDF(BcelClassWeaver weaver, LazyClassGen gen, ResolvedMember itdfieldSetter, ResolvedMember bridgingSetter) {
  1426. InstructionFactory fact;
  1427. LazyMethodGen bridgeMethod = makeMethodGen(gen,bridgingSetter);
  1428. Type[] paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
  1429. Type[] bridgingToParms = BcelWorld.makeBcelTypes(itdfieldSetter.getParameterTypes());
  1430. Type returnType = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
  1431. InstructionList body = bridgeMethod.getBody();
  1432. fact = gen.getFactory();
  1433. int pos = 0;
  1434. if (!bridgingSetter.isStatic()) {
  1435. body.append(InstructionFactory.createThis());
  1436. pos++;
  1437. }
  1438. for (int i = 0, len = paramTypes.length; i < len; i++) {
  1439. Type paramType = paramTypes[i];
  1440. body.append(InstructionFactory.createLoad(paramType, pos));
  1441. if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(itdfieldSetter.getParameterTypes()[i].getErasureSignature()) ) {
  1442. // une cast est required
  1443. System.err.println("Putting in cast from "+paramType+" to "+bridgingToParms[i]);
  1444. body.append(fact.createCast(paramType,bridgingToParms[i]));
  1445. }
  1446. pos+=paramType.getSize();
  1447. }
  1448. body.append(Utility.createInvoke(fact, weaver.getWorld(), itdfieldSetter));
  1449. body.append(InstructionFactory.createReturn(returnType));
  1450. gen.addMethodGen(bridgeMethod);
  1451. }
  1452. public ConcreteTypeMunger parameterizedFor(ResolvedType target) {
  1453. return new BcelTypeMunger(munger.parameterizedFor(target),aspectType);
  1454. }
  1455. /**
  1456. * Returns a list of type variable aliases used in this munger. For example, if the
  1457. * ITD is 'int I<A,B>.m(List<A> las,List<B> lbs) {}' then this returns a list containing
  1458. * the strings "A" and "B".
  1459. */
  1460. public List /*String*/ getTypeVariableAliases() {
  1461. return munger.getTypeVariableAliases();
  1462. }
  1463. public boolean equals(Object other) {
  1464. if (! (other instanceof BcelTypeMunger)) return false;
  1465. BcelTypeMunger o = (BcelTypeMunger) other;
  1466. return ((o.getMunger() == null) ? (getMunger() == null) : o.getMunger().equals(getMunger()))
  1467. && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType()))
  1468. && (AsmManager.getDefault().getHandleProvider().dependsOnLocation()
  1469. ?((o.getSourceLocation()==null)? (getSourceLocation()==null): o.getSourceLocation().equals(getSourceLocation())):true); // pr134471 - remove when handles are improved to be independent of location
  1470. }
  1471. private volatile int hashCode = 0;
  1472. public int hashCode() {
  1473. if (hashCode == 0) {
  1474. int result = 17;
  1475. result = 37*result + ((getMunger() == null) ? 0 : getMunger().hashCode());
  1476. result = 37*result + ((getAspectType() == null) ? 0 : getAspectType().hashCode());
  1477. hashCode = result;
  1478. }
  1479. return hashCode;
  1480. }
  1481. /**
  1482. * Some type mungers are created purely to help with the implementation of shadow mungers.
  1483. * For example to support the cflow() pointcut we create a new cflow field in the aspect, and
  1484. * that is added via a BcelCflowCounterFieldAdder.
  1485. *
  1486. * During compilation we need to compare sets of type mungers, and if some only come into
  1487. * existence after the 'shadowy' type things have been processed, we need to ignore
  1488. * them during the comparison.
  1489. *
  1490. * Returning true from this method indicates the type munger exists to support 'shadowy' stuff -
  1491. * and so can be ignored in some comparison.
  1492. */
  1493. public boolean existsToSupportShadowMunging() {
  1494. if (munger != null) {
  1495. return munger.existsToSupportShadowMunging();
  1496. }
  1497. return false;
  1498. }
  1499. }