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.

LazyClassGen.java 66KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925
  1. /* *******************************************************************
  2. * Copyright (c) 2002-2010 Contributors
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Andy Clement 6Jul05 generics - signature attribute
  12. * Abraham Nevado
  13. * ******************************************************************/
  14. package org.aspectj.weaver.bcel;
  15. import java.io.ByteArrayOutputStream;
  16. import java.io.File;
  17. import java.io.IOException;
  18. import java.io.PrintStream;
  19. import java.lang.reflect.Modifier;
  20. import java.util.ArrayList;
  21. import java.util.Collection;
  22. import java.util.Collections;
  23. import java.util.Comparator;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Set;
  29. import java.util.SortedMap;
  30. import java.util.TreeMap;
  31. import java.util.Vector;
  32. import org.aspectj.apache.bcel.Constants;
  33. import org.aspectj.apache.bcel.classfile.Attribute;
  34. import org.aspectj.apache.bcel.classfile.ConstantPool;
  35. import org.aspectj.apache.bcel.classfile.Field;
  36. import org.aspectj.apache.bcel.classfile.JavaClass;
  37. import org.aspectj.apache.bcel.classfile.Method;
  38. import org.aspectj.apache.bcel.classfile.Signature;
  39. import org.aspectj.apache.bcel.classfile.Synthetic;
  40. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  41. import org.aspectj.apache.bcel.generic.BasicType;
  42. import org.aspectj.apache.bcel.generic.ClassGen;
  43. import org.aspectj.apache.bcel.generic.FieldGen;
  44. import org.aspectj.apache.bcel.generic.InstructionConstants;
  45. import org.aspectj.apache.bcel.generic.InstructionFactory;
  46. import org.aspectj.apache.bcel.generic.InstructionHandle;
  47. import org.aspectj.apache.bcel.generic.InstructionList;
  48. import org.aspectj.apache.bcel.generic.ObjectType;
  49. import org.aspectj.apache.bcel.generic.Type;
  50. import org.aspectj.bridge.IMessage;
  51. import org.aspectj.bridge.ISourceLocation;
  52. import org.aspectj.bridge.SourceLocation;
  53. import org.aspectj.weaver.AjAttribute;
  54. import org.aspectj.weaver.AjAttribute.WeaverState;
  55. import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  56. import org.aspectj.weaver.BCException;
  57. import org.aspectj.weaver.Member;
  58. import org.aspectj.weaver.MemberKind;
  59. import org.aspectj.weaver.NameMangler;
  60. import org.aspectj.weaver.ResolvedMember;
  61. import org.aspectj.weaver.ResolvedType;
  62. import org.aspectj.weaver.RuntimeVersion;
  63. import org.aspectj.weaver.Shadow;
  64. import org.aspectj.weaver.SignatureUtils;
  65. import org.aspectj.weaver.TypeVariable;
  66. import org.aspectj.weaver.UnresolvedType;
  67. import org.aspectj.weaver.UnresolvedType.TypeKind;
  68. import org.aspectj.weaver.WeaverMessages;
  69. import org.aspectj.weaver.WeaverStateInfo;
  70. import org.aspectj.weaver.World;
  71. import org.aspectj.weaver.bcel.asm.AsmDetector;
  72. import org.aspectj.weaver.bcel.asm.StackMapAdder;
  73. /**
  74. * Lazy lazy lazy. We don't unpack the underlying class unless necessary. Things like new methods and annotations accumulate in here
  75. * until they must be written out, don't add them to the underlying MethodGen! Things are slightly different if this represents an
  76. * Aspect.
  77. */
  78. public final class LazyClassGen {
  79. private static final Type[] ARRAY_7STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
  80. Type.STRING, Type.STRING, Type.INT };
  81. private static final Type[] ARRAY_8STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
  82. Type.STRING, Type.STRING, Type.STRING, Type.INT };
  83. private static final Type[] PARAMSIGNATURE_MAKESJP_METHOD = new Type[] {
  84. Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.CLASS, Type.INT
  85. };
  86. private static final Type[] PARAMSIGNATURE_MAKESJP_CONSTRUCTOR = new Type[] {
  87. Type.STRING, Type.INT, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.INT
  88. };
  89. private static final Type[] PARAMSIGNATURE_MAKESJP_CATCHCLAUSE = new Type[] {
  90. Type.STRING, Type.CLASS, Type.CLASS, Type.STRING, Type.INT
  91. };
  92. private static final Type[] PARAMSIGNATURE_MAKESJP_FIELD = new Type[] {
  93. Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS, Type.INT
  94. };
  95. private static final Type[] PARAMSIGNATURE_MAKESJP_INITIALIZER = new Type[] {
  96. Type.STRING, Type.INT, Type.CLASS, Type.INT
  97. };
  98. private static final Type[] PARAMSIGNATURE_MAKESJP_MONITOR = new Type[] {
  99. Type.STRING, Type.CLASS, Type.INT
  100. };
  101. private static final Type[] PARAMSIGNATURE_MAKESJP_ADVICE = new Type[] {
  102. Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY,
  103. Type.CLASS_ARRAY, Type.CLASS, Type.INT
  104. };
  105. private static final int ACC_SYNTHETIC = 0x1000;
  106. private static final String[] NO_STRINGS = new String[0];
  107. int highestLineNumber = 0; // ---- JSR 45 info
  108. private final SortedMap<String, InlinedSourceFileInfo> inlinedFiles = new TreeMap<>();
  109. private boolean regenerateGenericSignatureAttribute = false;
  110. private BcelObjectType myType; // XXX is not set for types we create
  111. private ClassGen myGen;
  112. private final ConstantPool cp;
  113. private final World world;
  114. private final String packageName = null;
  115. private final List<BcelField> fields = new ArrayList<>();
  116. private final List<LazyMethodGen> methodGens = new ArrayList<>();
  117. private final List<LazyClassGen> classGens = new ArrayList<>();
  118. private final List<AnnotationGen> annotations = new ArrayList<>();
  119. private int childCounter = 0;
  120. private final InstructionFactory fact;
  121. private boolean isSerializable = false;
  122. private boolean hasSerialVersionUIDField = false;
  123. private boolean serialVersionUIDRequiresInitialization = false;
  124. private long calculatedSerialVersionUID;
  125. private boolean hasClinit = false;
  126. private ResolvedType[] extraSuperInterfaces = null;
  127. private ResolvedType superclass = null;
  128. // ---
  129. static class InlinedSourceFileInfo {
  130. int highestLineNumber;
  131. int offset; // calculated
  132. InlinedSourceFileInfo(int highestLineNumber) {
  133. this.highestLineNumber = highestLineNumber;
  134. }
  135. }
  136. void addInlinedSourceFileInfo(String fullpath, int highestLineNumber) {
  137. InlinedSourceFileInfo info = inlinedFiles.get(fullpath);
  138. if (info != null) {
  139. if (info.highestLineNumber < highestLineNumber) {
  140. info.highestLineNumber = highestLineNumber;
  141. }
  142. } else {
  143. inlinedFiles.put(fullpath, new InlinedSourceFileInfo(highestLineNumber));
  144. }
  145. }
  146. void calculateSourceDebugExtensionOffsets() {
  147. int i = roundUpToHundreds(highestLineNumber);
  148. for (InlinedSourceFileInfo element : inlinedFiles.values()) {
  149. element.offset = i;
  150. i = roundUpToHundreds(i + element.highestLineNumber);
  151. }
  152. }
  153. private static int roundUpToHundreds(int i) {
  154. return ((i / 100) + 1) * 100;
  155. }
  156. int getSourceDebugExtensionOffset(String fullpath) {
  157. return inlinedFiles.get(fullpath).offset;
  158. }
  159. // private Unknown getSourceDebugExtensionAttribute() {
  160. // int nameIndex = cp.addUtf8("SourceDebugExtension");
  161. // String data = getSourceDebugExtensionString();
  162. // //System.err.println(data);
  163. // byte[] bytes = Utility.stringToUTF(data);
  164. // int length = bytes.length;
  165. //
  166. // return new Unknown(nameIndex, length, bytes, cp);
  167. // }
  168. // private LazyClassGen() {}
  169. // public static void main(String[] args) {
  170. // LazyClassGen m = new LazyClassGen();
  171. // m.highestLineNumber = 37;
  172. // m.inlinedFiles.put("boo/baz/foo.java", new InlinedSourceFileInfo( 83));
  173. // m.inlinedFiles.put("boo/barz/foo.java", new InlinedSourceFileInfo(292));
  174. // m.inlinedFiles.put("boo/baz/moo.java", new InlinedSourceFileInfo(128));
  175. // m.calculateSourceDebugExtensionOffsets();
  176. // System.err.println(m.getSourceDebugExtensionString());
  177. // }
  178. // For the entire pathname, we're using package names. This is probably
  179. // wrong.
  180. // private String getSourceDebugExtensionString() {
  181. // StringBuffer out = new StringBuffer();
  182. // String myFileName = getFileName();
  183. // // header section
  184. // out.append("SMAP\n");
  185. // out.append(myFileName);
  186. // out.append("\nAspectJ\n");
  187. // // stratum section
  188. // out.append("*S AspectJ\n");
  189. // // file section
  190. // out.append("*F\n");
  191. // out.append("1 ");
  192. // out.append(myFileName);
  193. // out.append("\n");
  194. // int i = 2;
  195. // for (Iterator iter = inlinedFiles.keySet().iterator(); iter.hasNext();) {
  196. // String element = (String) iter.next();
  197. // int ii = element.lastIndexOf('/');
  198. // if (ii == -1) {
  199. // out.append(i++); out.append(' ');
  200. // out.append(element); out.append('\n');
  201. // } else {
  202. // out.append("+ "); out.append(i++); out.append(' ');
  203. // out.append(element.substring(ii+1)); out.append('\n');
  204. // out.append(element); out.append('\n');
  205. // }
  206. // }
  207. // // emit line section
  208. // out.append("*L\n");
  209. // out.append("1#1,");
  210. // out.append(highestLineNumber);
  211. // out.append(":1,1\n");
  212. // i = 2;
  213. // for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
  214. // InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
  215. // out.append("1#");
  216. // out.append(i++); out.append(',');
  217. // out.append(element.highestLineNumber); out.append(":");
  218. // out.append(element.offset + 1); out.append(",1\n");
  219. // }
  220. // // end section
  221. // out.append("*E\n");
  222. // // and finish up...
  223. // return out.toString();
  224. // }
  225. // ---- end JSR45-related stuff
  226. /** Emit disassembled class and newline to out */
  227. public static void disassemble(String path, String name, PrintStream out) throws IOException {
  228. if (null == out) {
  229. return;
  230. }
  231. // out.println("classPath: " + classPath);
  232. BcelWorld world = new BcelWorld(path);
  233. UnresolvedType ut = UnresolvedType.forName(name);
  234. ut.setNeedsModifiableDelegate(true);
  235. LazyClassGen clazz = new LazyClassGen(BcelWorld.getBcelObjectType(world.resolve(ut)));
  236. clazz.print(out);
  237. out.println();
  238. }
  239. public String getNewGeneratedNameTag() {
  240. return Integer.toString(childCounter++);
  241. }
  242. // ----
  243. public LazyClassGen(String class_name, String super_class_name, String file_name, int access_flags, String[] interfaces,
  244. World world) {
  245. myGen = new ClassGen(class_name, super_class_name, file_name, access_flags, interfaces);
  246. cp = myGen.getConstantPool();
  247. fact = new InstructionFactory(myGen, cp);
  248. regenerateGenericSignatureAttribute = true;
  249. this.world = world;
  250. }
  251. public void setMajorMinor(int major, int minor) {
  252. myGen.setMajor(major);
  253. myGen.setMinor(minor);
  254. }
  255. public int getMajor() {
  256. return myGen.getMajor();
  257. }
  258. public int getMinor() {
  259. return myGen.getMinor();
  260. }
  261. // Non child type, so it comes from a real type in the world.
  262. public LazyClassGen(BcelObjectType myType) {
  263. myGen = new ClassGen(myType.getJavaClass());
  264. cp = myGen.getConstantPool();
  265. fact = new InstructionFactory(myGen, cp);
  266. this.myType = myType;
  267. world = myType.getResolvedTypeX().getWorld();
  268. /* Does this class support serialization */
  269. if (implementsSerializable(getType())) {
  270. isSerializable = true;
  271. // ResolvedMember[] fields = getType().getDeclaredFields();
  272. // for (int i = 0; i < fields.length; i++) {
  273. // ResolvedMember field = fields[i];
  274. // if (field.getName().equals("serialVersionUID")
  275. // && field.isStatic() && field.getType().equals(UnresolvedType.LONG))
  276. // {
  277. // hasSerialVersionUIDField = true;
  278. // }
  279. // }
  280. hasSerialVersionUIDField = hasSerialVersionUIDField(getType());
  281. ResolvedMember[] methods = getType().getDeclaredMethods();
  282. for (ResolvedMember method : methods) {
  283. if (method.getName().equals("<clinit>")) {
  284. if (method.getKind() != Member.STATIC_INITIALIZATION) {
  285. throw new RuntimeException("qui?");
  286. }
  287. hasClinit = true;
  288. }
  289. }
  290. // Do we need to calculate an SUID and add it?
  291. if (!getType().isInterface() && !hasSerialVersionUIDField && world.isAddSerialVerUID()) {
  292. calculatedSerialVersionUID = myGen.getSUID();
  293. FieldGen fg = new FieldGen(Constants.ACC_PRIVATE | Constants.ACC_FINAL | Constants.ACC_STATIC, BasicType.LONG,
  294. "serialVersionUID", getConstantPool());
  295. addField(fg);
  296. hasSerialVersionUIDField = true;
  297. serialVersionUIDRequiresInitialization = true;
  298. // warn about what we've done?
  299. if (world.getLint().calculatingSerialVersionUID.isEnabled()) {
  300. world.getLint().calculatingSerialVersionUID.signal(
  301. new String[] { getClassName(), Long.toString(calculatedSerialVersionUID) + "L" }, null, null);
  302. }
  303. }
  304. }
  305. ResolvedMember[] methods = myType.getDeclaredMethods();
  306. for (ResolvedMember method : methods) {
  307. addMethodGen(new LazyMethodGen((BcelMethod) method, this));
  308. }
  309. // Method[] methods = myGen.getMethods();
  310. // for (int i = 0; i < methods.length; i++) {
  311. // addMethodGen(new LazyMethodGen(methods[i], this));
  312. // }
  313. ResolvedMember[] fields = myType.getDeclaredFields();
  314. for (ResolvedMember field : fields) {
  315. this.fields.add((BcelField) field);
  316. }
  317. }
  318. public static boolean hasSerialVersionUIDField(ResolvedType type) {
  319. ResolvedMember[] fields = type.getDeclaredFields();
  320. for (ResolvedMember field : fields) {
  321. if (field.getName().equals("serialVersionUID") && Modifier.isStatic(field.getModifiers())
  322. && field.getType().equals(UnresolvedType.LONG)) {
  323. return true;
  324. }
  325. }
  326. return false;
  327. }
  328. // public void addAttribute(Attribute i) {
  329. // myGen.addAttribute(i);
  330. // }
  331. // ----
  332. public String getInternalClassName() {
  333. return getConstantPool().getConstantString_CONSTANTClass(myGen.getClassNameIndex());
  334. // getConstantPool().getConstantString(
  335. // myGen.getClassNameIndex(),
  336. // Constants.CONSTANT_Class);
  337. }
  338. public String getInternalFileName() {
  339. String str = getInternalClassName();
  340. int index = str.lastIndexOf('/');
  341. if (index == -1) {
  342. return getFileName();
  343. } else {
  344. return str.substring(0, index + 1) + getFileName();
  345. }
  346. }
  347. /**
  348. * Returns the packagename - if its the default package we return an empty string
  349. */
  350. public String getPackageName() {
  351. if (packageName != null) {
  352. return packageName;
  353. }
  354. String str = getInternalClassName();
  355. int index = str.indexOf("<");
  356. if (index != -1) {
  357. str = str.substring(0, index); // strip off the generics guff
  358. }
  359. index = str.lastIndexOf("/");
  360. if (index == -1) {
  361. return "";
  362. }
  363. return str.substring(0, index).replace('/', '.');
  364. }
  365. public void addMethodGen(LazyMethodGen gen) {
  366. // assert gen.getClassName() == super.getClassName();
  367. methodGens.add(gen);
  368. if (highestLineNumber < gen.highestLineNumber) {
  369. highestLineNumber = gen.highestLineNumber;
  370. }
  371. }
  372. public boolean removeMethodGen(LazyMethodGen gen) {
  373. return methodGens.remove(gen);
  374. }
  375. public void addMethodGen(LazyMethodGen gen, ISourceLocation sourceLocation) {
  376. addMethodGen(gen);
  377. if (!gen.getMethod().isPrivate()) {
  378. warnOnAddedMethod(gen.getMethod(), sourceLocation);
  379. }
  380. }
  381. public void errorOnAddedField(FieldGen field, ISourceLocation sourceLocation) {
  382. if (isSerializable && !hasSerialVersionUIDField) {
  383. getWorld().getLint().serialVersionUIDBroken.signal(
  384. new String[] { myType.getResolvedTypeX().getName(), field.getName() }, sourceLocation, null);
  385. }
  386. }
  387. public void warnOnAddedInterface(String name, ISourceLocation sourceLocation) {
  388. warnOnModifiedSerialVersionUID(sourceLocation, "added interface " + name);
  389. }
  390. public void warnOnAddedMethod(Method method, ISourceLocation sourceLocation) {
  391. warnOnModifiedSerialVersionUID(sourceLocation, "added non-private method " + method.getName());
  392. }
  393. public void warnOnAddedStaticInitializer(Shadow shadow, ISourceLocation sourceLocation) {
  394. if (!hasClinit) {
  395. warnOnModifiedSerialVersionUID(sourceLocation, "added static initializer");
  396. }
  397. }
  398. public void warnOnModifiedSerialVersionUID(ISourceLocation sourceLocation, String reason) {
  399. if (isSerializable && !hasSerialVersionUIDField) {
  400. getWorld().getLint().needsSerialVersionUIDField.signal(new String[] { myType.getResolvedTypeX().getName().toString(),
  401. reason }, sourceLocation, null);
  402. }
  403. }
  404. public World getWorld() {
  405. return world;
  406. }
  407. public List<LazyMethodGen> getMethodGens() {
  408. return methodGens; // ???Collections.unmodifiableList(methodGens);
  409. }
  410. public List<BcelField> getFieldGens() {
  411. return fields;
  412. }
  413. public boolean fieldExists(String name) {
  414. // Field[] allFields = myGen.getFields();
  415. // if (allFields!=null) {
  416. // for (int i=0;i<allFields.length;i++) {
  417. // Field f = allFields[i];
  418. // if (f.getName().equals(name)) {
  419. // return f;
  420. // }
  421. // }
  422. // }
  423. for (BcelField f: fields) {
  424. if (f.getName().equals(name)) {
  425. return true;
  426. }
  427. }
  428. return false;
  429. }
  430. private void writeBack(BcelWorld world) {
  431. if (getConstantPool().getSize() > Short.MAX_VALUE) {
  432. reportClassTooBigProblem();
  433. return;
  434. }
  435. if (annotations.size() > 0) {
  436. for (AnnotationGen element : annotations) {
  437. myGen.addAnnotation(element);
  438. }
  439. // Attribute[] annAttributes =
  440. // org.aspectj.apache.bcel.classfile.Utility.getAnnotationAttributes(
  441. // getConstantPool(),annotations);
  442. // for (int i = 0; i < annAttributes.length; i++) {
  443. // Attribute attribute = annAttributes[i];
  444. // System.err.println("Adding attribute for "+attribute);
  445. // myGen.addAttribute(attribute);
  446. // }
  447. }
  448. // Add a weaver version attribute to the file being produced (if
  449. // necessary...)
  450. if (!myGen.hasAttribute("org.aspectj.weaver.WeaverVersion")) {
  451. myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverVersionInfo(), getConstantPool()));
  452. }
  453. // see 389678: TODO more finessing possible here?
  454. if (world.isOverWeaving()) {
  455. if (myGen.hasAttribute(WeaverState.AttributeName) && myType!=null && myType.getWeaverState() != null) {
  456. myGen.removeAttribute(myGen.getAttribute(WeaverState.AttributeName));
  457. myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
  458. }
  459. } else {
  460. if (!myGen.hasAttribute(WeaverState.AttributeName) && myType != null && myType.getWeaverState() != null) {
  461. myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
  462. }
  463. }
  464. // FIXME ATAJ needed only for slow Aspects.aspectOf() - keep or remove
  465. // make a lot of test fail since the test compare weaved class file
  466. // based on some test data as text files...
  467. // if (!myGen.isInterface()) {
  468. // addAjClassField();
  469. // }
  470. addAjcInitializers();
  471. // 17Feb05 - ASC - Skip this for now - it crashes IBM 1.4.2 jvms
  472. // (pr80430). Will be revisited when contents
  473. // of attribute are confirmed to be correct.
  474. boolean sourceDebugExtensionSupportSwitchedOn = false;
  475. if (sourceDebugExtensionSupportSwitchedOn) {
  476. calculateSourceDebugExtensionOffsets();
  477. }
  478. int len = methodGens.size();
  479. myGen.setMethods(Method.NoMethods);
  480. for (LazyMethodGen gen : methodGens) {
  481. // we skip empty clinits
  482. if (isEmptyClinit(gen)) {
  483. continue;
  484. }
  485. myGen.addMethod(gen.getMethod());
  486. }
  487. len = fields.size();
  488. myGen.setFields(Field.NoFields);
  489. for (int i = 0; i < len; i++) {
  490. BcelField gen = fields.get(i);
  491. myGen.addField(gen.getField(cp));
  492. }
  493. if (sourceDebugExtensionSupportSwitchedOn) {
  494. if (inlinedFiles.size() != 0) {
  495. if (hasSourceDebugExtensionAttribute(myGen)) {
  496. world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45, getFileName()), null,
  497. null);
  498. }
  499. // myGen.addAttribute(getSourceDebugExtensionAttribute());
  500. }
  501. }
  502. fixupGenericSignatureAttribute();
  503. }
  504. /**
  505. * When working with Java generics, a signature attribute is attached to the type which indicates how it was declared. This
  506. * routine ensures the signature attribute for the class we are about to write out is correct. Basically its responsibilities
  507. * are:
  508. * <ol>
  509. * <li>
  510. * Checking whether the attribute needs changing (ie. did weaving change the type hierarchy) - if it did, remove the old
  511. * attribute
  512. * <li>
  513. * Check if we need an attribute at all, are we generic? are our supertypes parameterized/generic?
  514. * <li>
  515. * Build the new attribute which includes all typevariable, supertype and superinterface information
  516. * </ol>
  517. */
  518. private void fixupGenericSignatureAttribute() {
  519. if (getWorld() != null && !getWorld().isInJava5Mode()) {
  520. return;
  521. }
  522. // TODO asc generics Temporarily assume that types we generate dont need
  523. // a signature attribute (closure/etc).. will need
  524. // revisiting no doubt...
  525. // if (myType == null) {
  526. // return;
  527. // }
  528. // 1. Has anything changed that would require us to modify this
  529. // attribute?
  530. if (!regenerateGenericSignatureAttribute) {
  531. return;
  532. }
  533. // 2. Find the old attribute
  534. Signature sigAttr = null;
  535. if (myType != null) { // if null, this is a type built from scratch, it
  536. // won't already have a sig attribute
  537. sigAttr = (Signature) myGen.getAttribute("Signature");
  538. }
  539. // 3. Do we need an attribute?
  540. boolean needAttribute = false;
  541. // If we had one before, we definetly still need one as types can't be
  542. // 'removed' from the hierarchy
  543. if (sigAttr != null) {
  544. needAttribute = true;
  545. }
  546. // check the interfaces
  547. if (!needAttribute) {
  548. if (myType != null) {
  549. ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
  550. for (ResolvedType typeX : interfaceRTXs) {
  551. if (typeX.isGenericType() || typeX.isParameterizedType()) {
  552. needAttribute = true;
  553. }
  554. }
  555. if (extraSuperInterfaces != null) {
  556. for (ResolvedType interfaceType : extraSuperInterfaces) {
  557. if (interfaceType.isGenericType() || interfaceType.isParameterizedType()) {
  558. needAttribute = true;
  559. }
  560. }
  561. }
  562. }
  563. if (myType == null) {
  564. ResolvedType superclassRTX = superclass;
  565. if (superclassRTX != null) {
  566. if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
  567. needAttribute = true;
  568. }
  569. }
  570. } else {
  571. // check the supertype
  572. ResolvedType superclassRTX = getSuperClass();
  573. if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
  574. needAttribute = true;
  575. }
  576. }
  577. }
  578. if (needAttribute) {
  579. StringBuilder signature = new StringBuilder();
  580. // first, the type variables...
  581. if (myType != null) {
  582. TypeVariable[] tVars = myType.getTypeVariables();
  583. if (tVars.length > 0) {
  584. signature.append("<");
  585. for (TypeVariable variable : tVars) {
  586. signature.append(variable.getSignatureForAttribute());
  587. }
  588. signature.append(">");
  589. }
  590. }
  591. // now the supertype
  592. String supersig = getSuperClass().getSignatureForAttribute();
  593. signature.append(supersig);
  594. if (myType != null) {
  595. ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
  596. for (ResolvedType interfaceRTX : interfaceRTXs) {
  597. String s = interfaceRTX.getSignatureForAttribute();
  598. signature.append(s);
  599. }
  600. if (extraSuperInterfaces != null) {
  601. for (ResolvedType extraSuperInterface : extraSuperInterfaces) {
  602. String s = extraSuperInterface.getSignatureForAttribute();
  603. signature.append(s);
  604. }
  605. }
  606. }
  607. if (sigAttr != null) {
  608. myGen.removeAttribute(sigAttr);
  609. }
  610. myGen.addAttribute(createSignatureAttribute(signature.toString()));
  611. }
  612. }
  613. /**
  614. * Helper method to create a signature attribute based on a string signature: e.g. "Ljava/lang/Object;LI<Ljava/lang/Double;>;"
  615. */
  616. private Signature createSignatureAttribute(String signature) {
  617. int nameIndex = cp.addUtf8("Signature");
  618. int sigIndex = cp.addUtf8(signature);
  619. return new Signature(nameIndex, 2, sigIndex, cp);
  620. }
  621. /**
  622. *
  623. */
  624. private void reportClassTooBigProblem() {
  625. // PR 59208
  626. // we've generated a class that is just toooooooooo big (you've been
  627. // generating programs
  628. // again haven't you? come on, admit it, no-one writes classes this big
  629. // by hand).
  630. // create an empty myGen so that we can give back a return value that
  631. // doesn't upset the
  632. // rest of the process.
  633. myGen = new ClassGen(myGen.getClassName(), myGen.getSuperclassName(), myGen.getFileName(), myGen.getModifiers(),
  634. myGen.getInterfaceNames());
  635. // raise an error against this compilation unit.
  636. getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CLASS_TOO_BIG, this.getClassName()),
  637. new SourceLocation(new File(myGen.getFileName()), 0), null);
  638. }
  639. private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
  640. return gen.hasAttribute("SourceDebugExtension");
  641. }
  642. public JavaClass getJavaClass(BcelWorld world) {
  643. writeBack(world);
  644. return myGen.getJavaClass();
  645. }
  646. public byte[] getJavaClassBytesIncludingReweavable(BcelWorld world) {
  647. writeBack(world);
  648. byte[] wovenClassFileData = myGen.getJavaClass().getBytes();
  649. // At 1.6 stackmaps are optional, whilst at 1.7 and later they
  650. // are required (unless turning off the verifier)
  651. if ((myGen.getMajor() == Constants.MAJOR_1_6 && world.shouldGenerateStackMaps()) || myGen.getMajor() > Constants.MAJOR_1_6) {
  652. if (!AsmDetector.isAsmAround) {
  653. throw new BCException(
  654. "Unable to find ASM classes (" + AsmDetector.CLASS_READER + ", " + AsmDetector.CLASS_VISITOR + ") " +
  655. "for stackmap generation. Stackmap generation for woven code is required to avoid verify errors " +
  656. "on a Java 1.7 or higher runtime.", AsmDetector.reasonAsmIsMissing
  657. );
  658. }
  659. wovenClassFileData = StackMapAdder.addStackMaps(world, myGen.getClassName(), wovenClassFileData);
  660. }
  661. WeaverStateInfo wsi = myType.getWeaverState();// getOrCreateWeaverStateInfo();
  662. if (wsi != null && wsi.isReweavable() && !world.isOverWeaving()) { // && !reweavableDataInserted
  663. // reweavableDataInserted = true;
  664. return wsi.replaceKeyWithDiff(wovenClassFileData);
  665. } else {
  666. return wovenClassFileData;
  667. }
  668. }
  669. public void addGeneratedInner(LazyClassGen newClass) {
  670. classGens.add(newClass);
  671. }
  672. public void addInterface(ResolvedType newInterface, ISourceLocation sourceLocation) {
  673. regenerateGenericSignatureAttribute = true;
  674. if (extraSuperInterfaces == null) {
  675. extraSuperInterfaces = new ResolvedType[1];
  676. extraSuperInterfaces[0] = newInterface;
  677. } else {
  678. ResolvedType[] x = new ResolvedType[extraSuperInterfaces.length + 1];
  679. System.arraycopy(extraSuperInterfaces, 0, x, 1, extraSuperInterfaces.length);
  680. x[0] = newInterface;
  681. extraSuperInterfaces = x;
  682. }
  683. myGen.addInterface(newInterface.getRawName());
  684. if (!newInterface.equals(UnresolvedType.SERIALIZABLE)) {
  685. warnOnAddedInterface(newInterface.getName(), sourceLocation);
  686. }
  687. }
  688. public void setSuperClass(ResolvedType newSuperclass) {
  689. regenerateGenericSignatureAttribute = true;
  690. superclass = newSuperclass;
  691. // myType.addParent(typeX); // used for the attribute
  692. if (newSuperclass.getGenericType() != null) {
  693. newSuperclass = newSuperclass.getGenericType();
  694. }
  695. myGen.setSuperclassName(newSuperclass.getName()); // used in the real
  696. // class data
  697. }
  698. // public String getSuperClassname() {
  699. // return myGen.getSuperclassName();
  700. // }
  701. public ResolvedType getSuperClass() {
  702. if (superclass != null) {
  703. return superclass;
  704. }
  705. return myType.getSuperclass();
  706. }
  707. public String[] getInterfaceNames() {
  708. return myGen.getInterfaceNames();
  709. }
  710. // non-recursive, may be a bug, ha ha.
  711. private List<LazyClassGen> getClassGens() {
  712. List<LazyClassGen> ret = new ArrayList<>();
  713. ret.add(this);
  714. ret.addAll(classGens);
  715. return ret;
  716. }
  717. public List<UnwovenClassFile.ChildClass> getChildClasses(BcelWorld world) {
  718. if (classGens.isEmpty()) {
  719. return Collections.emptyList();
  720. }
  721. List<UnwovenClassFile.ChildClass> ret = new ArrayList<>();
  722. for (LazyClassGen clazz : classGens) {
  723. byte[] bytes = clazz.getJavaClass(world).getBytes();
  724. String name = clazz.getName();
  725. int index = name.lastIndexOf('$');
  726. // XXX this could be bad, check use of dollar signs.
  727. name = name.substring(index + 1);
  728. ret.add(new UnwovenClassFile.ChildClass(name, bytes));
  729. }
  730. return ret;
  731. }
  732. @Override
  733. public String toString() {
  734. return toShortString();
  735. }
  736. public String toShortString() {
  737. String s = org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getModifiers(), true);
  738. if (!s.equals("")) {
  739. s += " ";
  740. }
  741. s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getModifiers());
  742. s += " ";
  743. s += myGen.getClassName();
  744. return s;
  745. }
  746. public String toLongString() {
  747. ByteArrayOutputStream s = new ByteArrayOutputStream();
  748. print(new PrintStream(s));
  749. return new String(s.toByteArray());
  750. }
  751. public void print() {
  752. print(System.out);
  753. }
  754. public void print(PrintStream out) {
  755. List<LazyClassGen> classGens = getClassGens();
  756. for (Iterator<LazyClassGen> iter = classGens.iterator(); iter.hasNext();) {
  757. LazyClassGen element = iter.next();
  758. element.printOne(out);
  759. if (iter.hasNext()) {
  760. out.println();
  761. }
  762. }
  763. }
  764. private void printOne(PrintStream out) {
  765. out.print(toShortString());
  766. out.print(" extends ");
  767. out.print(org.aspectj.apache.bcel.classfile.Utility.compactClassName(myGen.getSuperclassName(), false));
  768. int size = myGen.getInterfaces().length;
  769. if (size > 0) {
  770. out.print(" implements ");
  771. for (int i = 0; i < size; i++) {
  772. out.print(myGen.getInterfaceNames()[i]);
  773. if (i < size - 1) {
  774. out.print(", ");
  775. }
  776. }
  777. }
  778. out.print(":");
  779. out.println();
  780. // XXX make sure to pass types correctly around, so this doesn't happen.
  781. if (myType != null) {
  782. myType.printWackyStuff(out);
  783. }
  784. Field[] fields = myGen.getFields();
  785. for (Field field : fields) {
  786. out.print(" ");
  787. out.println(field);
  788. }
  789. List<LazyMethodGen> methodGens = getMethodGens();
  790. for (Iterator<LazyMethodGen> iter = methodGens.iterator(); iter.hasNext();) {
  791. LazyMethodGen gen = iter.next();
  792. // we skip empty clinits
  793. if (isEmptyClinit(gen)) {
  794. continue;
  795. }
  796. gen.print(out, (myType != null ? myType.getWeaverVersionAttribute() : WeaverVersionInfo.UNKNOWN));
  797. if (iter.hasNext()) {
  798. out.println();
  799. }
  800. }
  801. // out.println(" ATTRIBS: " + Arrays.asList(myGen.getAttributes()));
  802. out.println("end " + toShortString());
  803. }
  804. private boolean isEmptyClinit(LazyMethodGen gen) {
  805. if (!gen.getName().equals("<clinit>")) {
  806. return false;
  807. }
  808. // System.err.println("checking clinig: " + gen);
  809. InstructionHandle start = gen.getBody().getStart();
  810. while (start != null) {
  811. if (Range.isRangeHandle(start) || (start.getInstruction().opcode == Constants.RETURN)) {
  812. start = start.getNext();
  813. } else {
  814. return false;
  815. }
  816. }
  817. return true;
  818. }
  819. public ConstantPool getConstantPool() {
  820. return cp;
  821. }
  822. public String getName() {
  823. return myGen.getClassName();
  824. }
  825. public boolean isWoven() {
  826. return myType.getWeaverState() != null;
  827. }
  828. public boolean isReweavable() {
  829. if (myType.getWeaverState() == null) {
  830. return true;
  831. }
  832. return myType.getWeaverState().isReweavable();
  833. }
  834. public Set<String> getAspectsAffectingType() {
  835. if (myType.getWeaverState() == null) {
  836. return null;
  837. }
  838. return myType.getWeaverState().getAspectsAffectingType();
  839. }
  840. public WeaverStateInfo getOrCreateWeaverStateInfo(boolean inReweavableMode) {
  841. WeaverStateInfo ret = myType.getWeaverState();
  842. if (ret != null) {
  843. return ret;
  844. }
  845. ret = new WeaverStateInfo(inReweavableMode);
  846. myType.setWeaverState(ret);
  847. return ret;
  848. }
  849. public InstructionFactory getFactory() {
  850. return fact;
  851. }
  852. public LazyMethodGen getStaticInitializer() {
  853. for (LazyMethodGen gen : methodGens) {
  854. // OPTIMIZE persist kind of member into the gen object? for clinit
  855. if (gen.getName().equals("<clinit>")) {
  856. return gen;
  857. }
  858. }
  859. LazyMethodGen clinit = new LazyMethodGen(Modifier.STATIC, Type.VOID, "<clinit>", Type.NO_ARGS, NO_STRINGS, this);
  860. clinit.getBody().insert(InstructionConstants.RETURN);
  861. methodGens.add(clinit);
  862. return clinit;
  863. }
  864. /**
  865. * Retrieve the ajc$preClinit method - this method captures any initialization AspectJ wants to ensure happens in a class. It is
  866. * called from the static initializer. Maintaining this separation enables overweaving to ignore join points added due to
  867. * earlier weaves. If the ajc$preClinit method cannot be found, it is created and a call to it is placed in the real static
  868. * initializer (the call is placed at the start of the static initializer).
  869. *
  870. * @return the LazyMethodGen representing the ajc$ clinit
  871. */
  872. public LazyMethodGen getAjcPreClinit() {
  873. if (this.isInterface()) {
  874. throw new IllegalStateException();
  875. }
  876. for (LazyMethodGen methodGen : methodGens) {
  877. if (methodGen.getName().equals(NameMangler.AJC_PRE_CLINIT_NAME)) {
  878. return methodGen;
  879. }
  880. }
  881. LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
  882. NameMangler.AJC_PRE_CLINIT_NAME, Type.NO_ARGS, NO_STRINGS, this);
  883. ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
  884. methodGens.add(ajcPreClinit);
  885. InstructionList clinitBody = getStaticInitializer().getBody();
  886. clinitBody.insert(Utility.createInvoke(fact, ajcPreClinit));
  887. if (serialVersionUIDRequiresInitialization) {
  888. InstructionList il = new InstructionList();
  889. il.append(InstructionFactory.PUSH(getConstantPool(), calculatedSerialVersionUID));
  890. il.append(getFactory().createFieldAccess(getClassName(), "serialVersionUID", BasicType.LONG,
  891. Constants.PUTSTATIC));
  892. clinitBody.insert(il);
  893. }
  894. return ajcPreClinit;
  895. }
  896. /**
  897. * factory method for building multiple extended clinit methods. Constructs a new clinit method that invokes the previous one
  898. * and then returns it. The index is used as a name suffix.
  899. *
  900. * @param previousPreClinit
  901. * @param i
  902. */
  903. public LazyMethodGen createExtendedAjcPreClinit(LazyMethodGen previousPreClinit, int i) {
  904. LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
  905. NameMangler.AJC_PRE_CLINIT_NAME + i, Type.NO_ARGS, NO_STRINGS, this);
  906. ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
  907. methodGens.add(ajcPreClinit);
  908. previousPreClinit.getBody().insert(Utility.createInvoke(fact, ajcPreClinit));
  909. return ajcPreClinit;
  910. }
  911. //
  912. // reflective thisJoinPoint support
  913. private Map<BcelShadow, Field> tjpFields = new HashMap<>();
  914. Map<CacheKey, Field> annotationCachingFieldCache = new HashMap<>();
  915. private int tjpFieldsCounter = -1; // -1 means not yet initialized
  916. private int annoFieldsCounter = 0;
  917. public static final ObjectType proceedingTjpType = new ObjectType("org.aspectj.lang.ProceedingJoinPoint");
  918. public static final ObjectType tjpType = new ObjectType("org.aspectj.lang.JoinPoint");
  919. public static final ObjectType staticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$StaticPart");
  920. public static final ObjectType typeForAnnotation = new ObjectType("java.lang.annotation.Annotation");
  921. public static final ObjectType enclosingStaticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$EnclosingStaticPart");
  922. private static final ObjectType sigType = new ObjectType("org.aspectj.lang.Signature");
  923. // private static final ObjectType slType =
  924. // new ObjectType("org.aspectj.lang.reflect.SourceLocation");
  925. private static final ObjectType factoryType = new ObjectType("org.aspectj.runtime.reflect.Factory");
  926. private static final ObjectType classType = new ObjectType("java.lang.Class");
  927. public Field getTjpField(BcelShadow shadow, final boolean isEnclosingJp) {
  928. Field tjpField = tjpFields.get(shadow);
  929. if (tjpField != null) {
  930. return tjpField;
  931. }
  932. int modifiers = Modifier.STATIC;
  933. // J9: Can't always be final on Java 9 because it is set outside of clinit
  934. // But must be final in interface
  935. if (shadow.getEnclosingClass().isInterface()) {
  936. modifiers |= Modifier.FINAL;
  937. }
  938. // XXX - Do we ever inline before or after advice? If we do, then we
  939. // better include them in the check below. (or just change it to
  940. // shadow.getEnclosingMethod().getCanInline())
  941. // If the enclosing method is around advice, we could inline the join
  942. // point that has led to this shadow. If we do that then the TJP we are
  943. // creating here must be PUBLIC so it is visible to the type in which the
  944. // advice is inlined. (PR71377)
  945. LazyMethodGen encMethod = shadow.getEnclosingMethod();
  946. boolean shadowIsInAroundAdvice = false;
  947. if (encMethod != null && encMethod.getName().startsWith(NameMangler.PREFIX + "around")) {
  948. shadowIsInAroundAdvice = true;
  949. }
  950. if (getType().isInterface() || shadowIsInAroundAdvice) {
  951. modifiers |= Modifier.PUBLIC;
  952. } else {
  953. modifiers |= Modifier.PRIVATE;
  954. }
  955. ObjectType jpType = null;
  956. // Did not have different static joinpoint types in 1.2
  957. if (world.isTargettingAspectJRuntime12()) {
  958. jpType = staticTjpType;
  959. } else {
  960. jpType = isEnclosingJp ? enclosingStaticTjpType : staticTjpType;
  961. }
  962. if (tjpFieldsCounter == -1) {
  963. // not yet initialized, do it now
  964. if (!world.isOverWeaving()) {
  965. tjpFieldsCounter = 0;
  966. } else {
  967. List<BcelField> existingFields = getFieldGens();
  968. if (existingFields == null) {
  969. tjpFieldsCounter = 0;
  970. } else {
  971. BcelField lastField = null;
  972. // OPTIMIZE: go from last to first?
  973. for (BcelField field : existingFields) {
  974. if (field.getName().startsWith("ajc$tjp_")) {
  975. lastField = field;
  976. }
  977. }
  978. if (lastField == null) {
  979. tjpFieldsCounter = 0;
  980. } else {
  981. tjpFieldsCounter = Integer.parseInt(lastField.getName().substring(8)) + 1;
  982. // System.out.println("tjp counter starting at " + tjpFieldsCounter);
  983. }
  984. }
  985. }
  986. }
  987. if (!isInterface() && world.isTransientTjpFields()) {
  988. modifiers|=Modifier.TRANSIENT;
  989. }
  990. FieldGen fGen = new FieldGen(modifiers, jpType, "ajc$tjp_" + tjpFieldsCounter++, getConstantPool());
  991. addField(fGen);
  992. tjpField = fGen.getField();
  993. tjpFields.put(shadow, tjpField);
  994. return tjpField;
  995. }
  996. /**
  997. * Create a field in the type containing the shadow where the annotation retrieved during binding can be stored - for later fast
  998. * access.
  999. *
  1000. * @param shadow the shadow at which the @annotation result is being cached
  1001. * @return a field
  1002. */
  1003. public Field getAnnotationCachingField(BcelShadow shadow, ResolvedType toType, boolean isWithin) {
  1004. // Multiple annotation types at a shadow. A different field would be required for each
  1005. CacheKey cacheKey = new CacheKey(shadow, toType, isWithin);
  1006. Field field = annotationCachingFieldCache.get(cacheKey);
  1007. // System.out.println(field + " for shadow " + shadow);
  1008. if (field == null) {
  1009. // private static Annotation ajc$anno$<nnn>
  1010. StringBuilder sb = new StringBuilder();
  1011. sb.append(NameMangler.ANNOTATION_CACHE_FIELD_NAME);
  1012. sb.append(annoFieldsCounter++);
  1013. FieldGen annotationCacheField = new FieldGen(Modifier.PRIVATE | Modifier.STATIC, typeForAnnotation, sb.toString(), cp);
  1014. addField(annotationCacheField);
  1015. field = annotationCacheField.getField();
  1016. annotationCachingFieldCache.put(cacheKey, field);
  1017. }
  1018. return field;
  1019. }
  1020. static class CacheKey {
  1021. private Object key;
  1022. private ResolvedType annotationType;
  1023. // If the annotation is being accessed via @annotation on a shadow then we can use the shadows toString() (so two shadows
  1024. // the same share a variable), but if it is @withincode() or @within() we can't share them (as the shadows may look the same
  1025. // but be occurring 'within' different things). In the within cases we continue to use the shadow itself as the key.
  1026. CacheKey(BcelShadow shadow, ResolvedType annotationType, boolean isWithin) {
  1027. this.key = isWithin ? shadow : shadow.toString();
  1028. this.annotationType = annotationType;
  1029. }
  1030. @Override
  1031. public int hashCode() {
  1032. return key.hashCode() * 37 + annotationType.hashCode();
  1033. }
  1034. @Override
  1035. public boolean equals(Object other) {
  1036. if (!(other instanceof CacheKey)) {
  1037. return false;
  1038. }
  1039. CacheKey oCacheKey = (CacheKey) other;
  1040. return key.equals(oCacheKey.key) && annotationType.equals(oCacheKey.annotationType);
  1041. }
  1042. }
  1043. // FIXME ATAJ needed only for slow Aspects.aspectOf - keep or remove
  1044. // private void addAjClassField() {
  1045. // // Andy: Why build it again??
  1046. // Field ajClassField = new FieldGen(
  1047. // Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC,
  1048. // classType,
  1049. // "aj$class",
  1050. // getConstantPool()).getField();
  1051. // addField(ajClassField);
  1052. //
  1053. // InstructionList il = new InstructionList();
  1054. // il.append(new PUSH(getConstantPool(), getClassName()));
  1055. // il.append(fact.createInvoke("java.lang.Class", "forName", classType,
  1056. // new Type[] {Type.STRING}, Constants.INVOKESTATIC));
  1057. // il.append(fact.createFieldAccess(getClassName(), ajClassField.getName(),
  1058. // classType, Constants.PUTSTATIC));
  1059. //
  1060. // getStaticInitializer().getBody().insert(il);
  1061. // }
  1062. private void addAjcInitializers() {
  1063. if (tjpFields.size() == 0 && !serialVersionUIDRequiresInitialization) {
  1064. return;
  1065. }
  1066. InstructionList[] il = initializeAllTjps();
  1067. LazyMethodGen prevMethod;
  1068. LazyMethodGen nextMethod = null;
  1069. if (this.isInterface()) { // Cannot sneak stuff into another static method in an interface
  1070. prevMethod = getStaticInitializer();
  1071. } else {
  1072. prevMethod = getAjcPreClinit();
  1073. }
  1074. for (int counter = 1; counter <= il.length; counter++) {
  1075. if (il.length > counter) {
  1076. nextMethod = createExtendedAjcPreClinit(prevMethod, counter);
  1077. }
  1078. prevMethod.getBody().insert(il[counter - 1]);
  1079. prevMethod = nextMethod;
  1080. }
  1081. }
  1082. private InstructionList initInstructionList() {
  1083. InstructionList list = new InstructionList();
  1084. InstructionFactory fact = getFactory();
  1085. // make a new factory
  1086. list.append(fact.createNew(factoryType));
  1087. list.append(InstructionFactory.createDup(1));
  1088. list.append(InstructionFactory.PUSH(getConstantPool(), getFileName()));
  1089. // load the current Class object
  1090. // XXX check that this works correctly for inners/anonymous
  1091. list.append(fact.PUSHCLASS(cp, myGen.getClassName()));
  1092. // XXX do we need to worry about the fact the theorectically this could
  1093. // throw
  1094. // a ClassNotFoundException
  1095. list.append(fact.createInvoke(factoryType.getClassName(), "<init>", Type.VOID, new Type[] { Type.STRING, classType },
  1096. Constants.INVOKESPECIAL));
  1097. list.append(InstructionFactory.createStore(factoryType, 0));
  1098. return list;
  1099. }
  1100. private InstructionList[] initializeAllTjps() {
  1101. Vector<InstructionList> lists = new Vector<>();
  1102. InstructionList list = initInstructionList();
  1103. lists.add(list);
  1104. List<Map.Entry<BcelShadow, Field>> entries = new ArrayList<>(tjpFields.entrySet());
  1105. entries.sort(new Comparator<Map.Entry<BcelShadow, Field>>() {
  1106. @Override
  1107. public int compare(Map.Entry<BcelShadow, Field> a, Map.Entry<BcelShadow, Field> b) {
  1108. return (a.getValue()).getName().compareTo((b.getValue()).getName());
  1109. }
  1110. });
  1111. long estimatedSize = 0;
  1112. for (Map.Entry<BcelShadow, Field> entry : entries) {
  1113. if (estimatedSize > Constants.MAX_CODE_SIZE) {
  1114. estimatedSize = 0;
  1115. list = initInstructionList();
  1116. lists.add(list);
  1117. }
  1118. estimatedSize += entry.getValue().getSignature().getBytes().length;
  1119. initializeTjp(fact, list, entry.getValue(), entry.getKey());
  1120. }
  1121. InstructionList listArrayModel[] = new InstructionList[1];
  1122. return lists.toArray(listArrayModel);
  1123. }
  1124. private void initializeTjp(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
  1125. if (world.getTargetAspectjRuntimeLevel() == RuntimeVersion.V1_9) {
  1126. initializeTjpOptimal(fact, list, field, shadow);
  1127. return;
  1128. }
  1129. boolean fastSJP = false;
  1130. // avoid fast SJP if it is for an enclosing joinpoint
  1131. boolean isFastSJPAvailable = shadow.getWorld().isTargettingRuntime1_6_10()
  1132. && !enclosingStaticTjpType.equals(field.getType());
  1133. Member sig = shadow.getSignature();
  1134. // load the factory
  1135. list.append(InstructionFactory.createLoad(factoryType, 0));
  1136. // load the kind
  1137. list.append(InstructionFactory.PUSH(getConstantPool(), shadow.getKind().getName()));
  1138. // create the signature
  1139. if (world.isTargettingAspectJRuntime12() || !isFastSJPAvailable || !sig.getKind().equals(Member.METHOD)) {
  1140. list.append(InstructionFactory.createLoad(factoryType, 0));
  1141. }
  1142. String signatureMakerName = SignatureUtils.getSignatureMakerName(sig);
  1143. ObjectType signatureType = new ObjectType(SignatureUtils.getSignatureType(sig));
  1144. UnresolvedType[] exceptionTypes = null;
  1145. if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have optimized factory methods in 1.2
  1146. list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
  1147. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1148. Constants.INVOKEVIRTUAL));
  1149. } else if (sig.getKind().equals(Member.METHOD)) {
  1150. BcelWorld w = shadow.getWorld();
  1151. // For methods, push the parts of the signature on.
  1152. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1153. list.append(InstructionFactory.PUSH(cp, sig.getName()));
  1154. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1155. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1156. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1157. exceptionTypes = sig.getExceptions(w);
  1158. if (isFastSJPAvailable && exceptionTypes.length == 0) {
  1159. fastSJP = true;
  1160. } else {
  1161. list.append(InstructionFactory.PUSH(cp, makeString(exceptionTypes)));
  1162. }
  1163. list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
  1164. // And generate a call to the variant of makeMethodSig() that takes the strings
  1165. if (isFastSJPAvailable) {
  1166. fastSJP = true;
  1167. } else {
  1168. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY7,
  1169. Constants.INVOKEVIRTUAL));
  1170. }
  1171. } else if (sig.getKind().equals(Member.MONITORENTER)) {
  1172. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1173. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1174. Constants.INVOKEVIRTUAL));
  1175. } else if (sig.getKind().equals(Member.MONITOREXIT)) {
  1176. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1177. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1178. Constants.INVOKEVIRTUAL));
  1179. } else if (sig.getKind().equals(Member.HANDLER)) {
  1180. BcelWorld w = shadow.getWorld();
  1181. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1182. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1183. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1184. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY3,
  1185. Constants.INVOKEVIRTUAL));
  1186. } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
  1187. BcelWorld w = shadow.getWorld();
  1188. if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
  1189. // its the magical new jp
  1190. list.append(InstructionFactory.PUSH(cp, makeString(Modifier.PUBLIC)));
  1191. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1192. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1193. list.append(InstructionFactory.PUSH(cp, "")); // sig.getParameterNames?
  1194. list.append(InstructionFactory.PUSH(cp, ""));// sig.getExceptions?
  1195. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
  1196. Constants.INVOKEVIRTUAL));
  1197. } else {
  1198. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1199. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1200. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1201. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1202. list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
  1203. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
  1204. Constants.INVOKEVIRTUAL));
  1205. }
  1206. } else if (sig.getKind().equals(Member.FIELD)) {
  1207. BcelWorld w = shadow.getWorld();
  1208. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1209. list.append(InstructionFactory.PUSH(cp, sig.getName()));
  1210. // see pr227401
  1211. UnresolvedType dType = sig.getDeclaringType();
  1212. if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
  1213. dType = sig.getDeclaringType().resolve(world).getGenericType();
  1214. }
  1215. list.append(InstructionFactory.PUSH(cp, makeString(dType)));
  1216. list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
  1217. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY4,
  1218. Constants.INVOKEVIRTUAL));
  1219. } else if (sig.getKind().equals(Member.ADVICE)) {
  1220. BcelWorld w = shadow.getWorld();
  1221. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1222. list.append(InstructionFactory.PUSH(cp, sig.getName()));
  1223. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1224. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
  1225. list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
  1226. list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
  1227. list.append(InstructionFactory.PUSH(cp, makeString((sig.getReturnType()))));
  1228. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, new Type[] { Type.STRING,
  1229. Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING }, Constants.INVOKEVIRTUAL));
  1230. } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
  1231. BcelWorld w = shadow.getWorld();
  1232. list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
  1233. list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
  1234. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY2,
  1235. Constants.INVOKEVIRTUAL));
  1236. } else {
  1237. // TODO looks like this block is unused code
  1238. list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
  1239. list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
  1240. Constants.INVOKEVIRTUAL));
  1241. }
  1242. // XXX should load source location from shadow
  1243. list.append(Utility.createConstant(fact, shadow.getSourceLine()));
  1244. final String factoryMethod;
  1245. // TAG:SUPPORTING12: We didn't have makeESJP() in 1.2
  1246. if (world.isTargettingAspectJRuntime12()) {
  1247. list.append(fact.createInvoke(factoryType.getClassName(), "makeSJP", staticTjpType, new Type[] { Type.STRING, sigType,
  1248. Type.INT }, Constants.INVOKEVIRTUAL));
  1249. // put it in the field
  1250. list.append(fact.createFieldAccess(getClassName(), field.getName(), staticTjpType, Constants.PUTSTATIC));
  1251. } else {
  1252. if (staticTjpType.equals(field.getType())) {
  1253. factoryMethod = "makeSJP";
  1254. } else if (enclosingStaticTjpType.equals(field.getType())) {
  1255. factoryMethod = "makeESJP";
  1256. } else {
  1257. throw new Error("should not happen");
  1258. }
  1259. if (fastSJP) {
  1260. if (exceptionTypes != null && exceptionTypes.length != 0) {
  1261. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_8STRING_INT,
  1262. Constants.INVOKEVIRTUAL));
  1263. } else {
  1264. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_7STRING_INT,
  1265. Constants.INVOKEVIRTUAL));
  1266. }
  1267. } else {
  1268. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), new Type[] { Type.STRING,
  1269. sigType, Type.INT }, Constants.INVOKEVIRTUAL));
  1270. }
  1271. // put it in the field
  1272. list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
  1273. }
  1274. }
  1275. public String getFactoryMethod(Field field, BcelShadow shadow) {
  1276. StringBuilder b = new StringBuilder();
  1277. b.append("make");
  1278. MemberKind kind = shadow.getSignature().getKind();
  1279. if (kind.equals(Member.METHOD)) {
  1280. b.append("Method");
  1281. } else if (kind.equals(Member.CONSTRUCTOR)) {
  1282. b.append("Constructor");
  1283. } else if (kind.equals(Member.HANDLER)) {
  1284. b.append("CatchClause");
  1285. } else if (kind.equals(Member.FIELD)) {
  1286. b.append("Field");
  1287. } else if (kind.equals(Member.STATIC_INITIALIZATION)) {
  1288. b.append("Initializer");
  1289. } else if (kind.equals(Member.MONITORENTER)) {
  1290. b.append("Lock");
  1291. } else if (kind.equals(Member.MONITOREXIT)) {
  1292. b.append("Unlock");
  1293. } else if (kind.equals(Member.ADVICE)) {
  1294. b.append("Advice");
  1295. } else {
  1296. throw new IllegalStateException(kind.toString());
  1297. }
  1298. if (staticTjpType.equals(field.getType())) {
  1299. b.append("SJP");
  1300. } else if (enclosingStaticTjpType.equals(field.getType())) {
  1301. b.append("ESJP");
  1302. }
  1303. return b.toString();
  1304. }
  1305. /**
  1306. * Generate optimal joinpoint initialization code.
  1307. *
  1308. * As of version 1.9.1 the runtime includes new factory methods for joinpoints that take classes, not strings
  1309. * and using them requires different code generation. Using these instead of the old ones means we can avoid
  1310. * deferred classloading for these types. By using the LDC instruction that loads classes, it also means
  1311. * anything modifying woven code and changing type names will also pick up on these references.
  1312. */
  1313. private void initializeTjpOptimal(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
  1314. list.append(InstructionFactory.createLoad(factoryType, 0));
  1315. pushString(list, shadow.getKind().getName());
  1316. String factoryMethod = getFactoryMethod(field, shadow);
  1317. Member sig = shadow.getSignature();
  1318. BcelWorld w = shadow.getWorld();
  1319. if (sig.getKind().equals(Member.METHOD)) {
  1320. pushInt(list, sig.getModifiers(w));
  1321. pushString(list, sig.getName());
  1322. pushClass(list, sig.getDeclaringType());
  1323. pushClasses(list, sig.getParameterTypes());
  1324. pushStrings(list, sig.getParameterNames(w));
  1325. pushClasses(list, sig.getExceptions(w));
  1326. pushClass(list, sig.getReturnType());
  1327. pushInt(list, shadow.getSourceLine());
  1328. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1329. PARAMSIGNATURE_MAKESJP_METHOD, Constants.INVOKEVIRTUAL));
  1330. } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
  1331. if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
  1332. pushInt(list, Modifier.PUBLIC);
  1333. pushClass(list, sig.getDeclaringType());
  1334. pushClasses(list, sig.getParameterTypes());
  1335. pushStrings(list, null);
  1336. pushClasses(list, null);
  1337. } else {
  1338. pushInt(list, sig.getModifiers(w));
  1339. pushClass(list, sig.getDeclaringType());
  1340. pushClasses(list, sig.getParameterTypes());
  1341. pushStrings(list, sig.getParameterNames(w));
  1342. pushClasses(list, sig.getExceptions(w));
  1343. }
  1344. pushInt(list, shadow.getSourceLine());
  1345. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1346. PARAMSIGNATURE_MAKESJP_CONSTRUCTOR, Constants.INVOKEVIRTUAL));
  1347. } else if (sig.getKind().equals(Member.HANDLER)) {
  1348. pushClass(list, sig.getDeclaringType());
  1349. pushClass(list, sig.getParameterTypes()[0]);
  1350. String pname = null;
  1351. String[] pnames = sig.getParameterNames(w);
  1352. if (pnames != null && pnames.length>0) {
  1353. pname = pnames[0];
  1354. }
  1355. pushString(list, pname);
  1356. pushInt(list, shadow.getSourceLine());
  1357. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1358. PARAMSIGNATURE_MAKESJP_CATCHCLAUSE, Constants.INVOKEVIRTUAL));
  1359. } else if (sig.getKind().equals(Member.FIELD)) {
  1360. pushInt(list, sig.getModifiers(w));
  1361. pushString(list, sig.getName());
  1362. // see pr227401
  1363. UnresolvedType dType = sig.getDeclaringType();
  1364. if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
  1365. dType = sig.getDeclaringType().resolve(world).getGenericType();
  1366. }
  1367. pushClass(list, dType);
  1368. pushClass(list, sig.getReturnType());
  1369. pushInt(list,shadow.getSourceLine());
  1370. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1371. PARAMSIGNATURE_MAKESJP_FIELD, Constants.INVOKEVIRTUAL));
  1372. } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
  1373. pushInt(list, sig.getModifiers(w));
  1374. pushClass(list, sig.getDeclaringType());
  1375. pushInt(list, shadow.getSourceLine());
  1376. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1377. PARAMSIGNATURE_MAKESJP_INITIALIZER, Constants.INVOKEVIRTUAL));
  1378. } else if (sig.getKind().equals(Member.MONITORENTER)) {
  1379. pushClass(list, sig.getDeclaringType());
  1380. pushInt(list, shadow.getSourceLine());
  1381. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1382. PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
  1383. } else if (sig.getKind().equals(Member.MONITOREXIT)) {
  1384. pushClass(list, sig.getDeclaringType());
  1385. pushInt(list, shadow.getSourceLine());
  1386. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1387. PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
  1388. } else if (sig.getKind().equals(Member.ADVICE)) {
  1389. pushInt(list, sig.getModifiers(w));
  1390. pushString(list, sig.getName());
  1391. pushClass(list, sig.getDeclaringType());
  1392. pushClasses(list, sig.getParameterTypes());
  1393. pushStrings(list, sig.getParameterNames(w));
  1394. pushClasses(list, sig.getExceptions(w));
  1395. pushClass(list, sig.getReturnType());
  1396. pushInt(list, shadow.getSourceLine());
  1397. list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
  1398. PARAMSIGNATURE_MAKESJP_ADVICE, Constants.INVOKEVIRTUAL));
  1399. } else {
  1400. throw new IllegalStateException("not sure what to do: "+shadow);
  1401. }
  1402. list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
  1403. }
  1404. private void pushStrings(InstructionList list, String[] strings) {
  1405. // Build an array loaded with the strings
  1406. if (strings == null || strings.length == 0) {
  1407. list.append(InstructionFactory.ACONST_NULL);
  1408. } else {
  1409. list.append(InstructionFactory.PUSH(cp, strings.length));
  1410. list.append(fact.createNewArray(Type.STRING, (short)1));
  1411. for (int s=0;s<strings.length;s++) {
  1412. list.append(InstructionFactory.DUP);
  1413. list.append(InstructionFactory.PUSH(cp, s));
  1414. list.append(InstructionFactory.PUSH(cp, strings[s]));
  1415. list.append(InstructionFactory.AASTORE);
  1416. }
  1417. }
  1418. }
  1419. private void pushClass(InstructionList list, UnresolvedType type) {
  1420. if (type.isPrimitiveType()) {
  1421. if (type.getSignature().equals("I")) {
  1422. list.append(fact.createGetStatic("java/lang/Integer","TYPE", Type.CLASS));
  1423. } else if (type.getSignature().equals("D")) {
  1424. list.append(fact.createGetStatic("java/lang/Double","TYPE", Type.CLASS));
  1425. } else if (type.getSignature().equals("S")) {
  1426. list.append(fact.createGetStatic("java/lang/Short","TYPE", Type.CLASS));
  1427. } else if (type.getSignature().equals("J")) {
  1428. list.append(fact.createGetStatic("java/lang/Long","TYPE", Type.CLASS));
  1429. } else if (type.getSignature().equals("F")) {
  1430. list.append(fact.createGetStatic("java/lang/Float","TYPE", Type.CLASS));
  1431. } else if (type.getSignature().equals("C")) {
  1432. list.append(fact.createGetStatic("java/lang/Character","TYPE", Type.CLASS));
  1433. } else if (type.getSignature().equals("B")) {
  1434. list.append(fact.createGetStatic("java/lang/Byte","TYPE", Type.CLASS));
  1435. } else if (type.getSignature().equals("Z")) {
  1436. list.append(fact.createGetStatic("java/lang/Boolean","TYPE", Type.CLASS));
  1437. } else if (type.getSignature().equals("V")) {
  1438. list.append(InstructionFactory.ACONST_NULL);
  1439. }
  1440. return;
  1441. }
  1442. String classString = makeLdcClassString(type);
  1443. if (classString == null) {
  1444. list.append(InstructionFactory.ACONST_NULL);
  1445. } else {
  1446. list.append(fact.PUSHCLASS(cp, classString));
  1447. }
  1448. }
  1449. private void pushClasses(InstructionList list, UnresolvedType[] types) {
  1450. // Build an array loaded with the class objects
  1451. if (types == null || types.length == 0) {
  1452. list.append(InstructionFactory.ACONST_NULL);
  1453. } else {
  1454. list.append(InstructionFactory.PUSH(cp, types.length));
  1455. list.append(fact.createNewArray(Type.CLASS, (short)1));
  1456. for (int t=0;t<types.length;t++) {
  1457. list.append(InstructionFactory.DUP);
  1458. list.append(InstructionFactory.PUSH(cp, t));
  1459. pushClass(list, types[t]);
  1460. list.append(InstructionFactory.AASTORE);
  1461. }
  1462. }
  1463. }
  1464. private final void pushString(InstructionList list, String string) {
  1465. list.append(InstructionFactory.PUSH(cp, string));
  1466. }
  1467. private final void pushInt(InstructionList list, int value) {
  1468. list.append(InstructionFactory.PUSH(cp, value));
  1469. }
  1470. protected String makeString(int i) {
  1471. return Integer.toString(i, 16); // ??? expensive
  1472. }
  1473. protected String makeString(UnresolvedType t) {
  1474. // this is the inverse of the odd behavior for Class.forName w/ arrays
  1475. if (t.isArray()) {
  1476. // this behavior matches the string used by the eclipse compiler for
  1477. // Foo.class literals
  1478. return t.getSignature().replace('/', '.');
  1479. } else {
  1480. if (t.isParameterizedType()) {
  1481. return t.getRawType().getName();
  1482. } else {
  1483. return t.getName();
  1484. }
  1485. }
  1486. }
  1487. protected String makeLdcClassString(UnresolvedType type) {
  1488. if (type.isVoid() || type.isPrimitiveType()) {
  1489. return null;
  1490. }
  1491. if (type.isArray()) {
  1492. return type.getSignature();
  1493. } else {
  1494. if (type.isParameterizedType()) {
  1495. type = type.getRawType();
  1496. }
  1497. String signature = type.getSignature();
  1498. if (signature.length() ==1 ) {
  1499. return signature;
  1500. }
  1501. return signature.substring(1,signature.length()-1);
  1502. }
  1503. }
  1504. protected String makeString(UnresolvedType[] types) {
  1505. if (types == null) {
  1506. return "";
  1507. }
  1508. StringBuilder buf = new StringBuilder();
  1509. for (int i = 0, len = types.length; i < len; i++) {
  1510. if (i > 0) {
  1511. buf.append(':');
  1512. }
  1513. buf.append(makeString(types[i]));
  1514. }
  1515. return buf.toString();
  1516. }
  1517. protected String makeString(String[] names) {
  1518. if (names == null) {
  1519. return "";
  1520. }
  1521. StringBuilder buf = new StringBuilder();
  1522. for (int i = 0, len = names.length; i < len; i++) {
  1523. if (i > 0) {
  1524. buf.append(':');
  1525. }
  1526. buf.append(names[i]);
  1527. }
  1528. return buf.toString();
  1529. }
  1530. public ResolvedType getType() {
  1531. if (myType == null) {
  1532. return null;
  1533. }
  1534. return myType.getResolvedTypeX();
  1535. }
  1536. public BcelObjectType getBcelObjectType() {
  1537. return myType;
  1538. }
  1539. public String getFileName() {
  1540. return myGen.getFileName();
  1541. }
  1542. // for *new* fields
  1543. private void addField(FieldGen field) {
  1544. makeSyntheticAndTransientIfNeeded(field);
  1545. BcelField bcelField = null;
  1546. if (getBcelObjectType() != null) {
  1547. bcelField = new BcelField(getBcelObjectType(), field.getField());
  1548. } else {
  1549. bcelField = new BcelField(getName(), field.getField(), world);
  1550. }
  1551. fields.add(bcelField);
  1552. // myGen.addField(field.getField());
  1553. }
  1554. private void makeSyntheticAndTransientIfNeeded(FieldGen field) {
  1555. if (field.getName().startsWith(NameMangler.PREFIX) && !field.getName().startsWith("ajc$interField$")
  1556. && !field.getName().startsWith("ajc$instance$")) {
  1557. // it's an aj added field
  1558. // first do transient
  1559. if (!field.isStatic()) {
  1560. field.setModifiers(field.getModifiers() | Constants.ACC_TRANSIENT);
  1561. }
  1562. // then do synthetic
  1563. if (getWorld().isInJava5Mode()) {
  1564. // add the synthetic modifier flag
  1565. field.setModifiers(field.getModifiers() | ACC_SYNTHETIC);
  1566. }
  1567. if (!hasSyntheticAttribute(field.getAttributes())) {
  1568. // belt and braces, do the attribute even on Java 5 in addition
  1569. // to the modifier flag
  1570. // Attribute[] oldAttrs = field.getAttributes();
  1571. // Attribute[] newAttrs = new Attribute[oldAttrs.length + 1];
  1572. // System.arraycopy(oldAttrs, 0, newAttrs, 0, oldAttrs.length);
  1573. ConstantPool cpg = myGen.getConstantPool();
  1574. int index = cpg.addUtf8("Synthetic");
  1575. Attribute synthetic = new Synthetic(index, 0, new byte[0], cpg);
  1576. field.addAttribute(synthetic);
  1577. // newAttrs[newAttrs.length - 1] = synthetic;
  1578. // field.setAttributes(newAttrs);
  1579. }
  1580. }
  1581. }
  1582. private boolean hasSyntheticAttribute(List<Attribute> attributes) {
  1583. for (Attribute attribute : attributes) {
  1584. if (attribute.getName().equals("Synthetic")) {
  1585. return true;
  1586. }
  1587. }
  1588. return false;
  1589. }
  1590. public void addField(FieldGen field, ISourceLocation sourceLocation) {
  1591. addField(field);
  1592. if (!(field.isPrivate() && (field.isStatic() || field.isTransient()))) {
  1593. errorOnAddedField(field, sourceLocation);
  1594. }
  1595. }
  1596. public String getClassName() {
  1597. return myGen.getClassName();
  1598. }
  1599. public boolean isInterface() {
  1600. return myGen.isInterface();
  1601. }
  1602. public boolean isAbstract() {
  1603. return myGen.isAbstract();
  1604. }
  1605. public LazyMethodGen getLazyMethodGen(Member m) {
  1606. return getLazyMethodGen(m.getName(), m.getSignature(), false);
  1607. }
  1608. public LazyMethodGen getLazyMethodGen(String name, String signature) {
  1609. return getLazyMethodGen(name, signature, false);
  1610. }
  1611. public LazyMethodGen getLazyMethodGen(String name, String signature, boolean allowMissing) {
  1612. for (LazyMethodGen gen : methodGens) {
  1613. if (gen.getName().equals(name) && gen.getSignature().equals(signature)) {
  1614. return gen;
  1615. }
  1616. }
  1617. if (!allowMissing) {
  1618. throw new BCException("Class " + this.getName() + " does not have a method " + name + " with signature " + signature);
  1619. }
  1620. return null;
  1621. }
  1622. public void forcePublic() {
  1623. myGen.setModifiers(Utility.makePublic(myGen.getModifiers()));
  1624. }
  1625. public boolean hasAnnotation(UnresolvedType t) {
  1626. // annotations on the real thing
  1627. AnnotationGen agens[] = myGen.getAnnotations();
  1628. if (agens == null) {
  1629. return false;
  1630. }
  1631. for (AnnotationGen gen : agens) {
  1632. if (t.equals(UnresolvedType.forSignature(gen.getTypeSignature()))) {
  1633. return true;
  1634. }
  1635. }
  1636. // annotations added during this weave
  1637. return false;
  1638. }
  1639. public void addAnnotation(AnnotationGen a) {
  1640. if (!hasAnnotation(UnresolvedType.forSignature(a.getTypeSignature()))) {
  1641. annotations.add(new AnnotationGen(a, getConstantPool(), true));
  1642. }
  1643. }
  1644. public void addAttribute(AjAttribute attribute) {
  1645. myGen.addAttribute(Utility.bcelAttribute(attribute, getConstantPool()));
  1646. }
  1647. public void addAttribute(Attribute attribute) {
  1648. myGen.addAttribute(attribute);
  1649. }
  1650. public Collection<Attribute> getAttributes() {
  1651. return myGen.getAttributes();
  1652. }
  1653. // this test is like asking:
  1654. // if
  1655. // (UnresolvedType.SERIALIZABLE.resolve(getType().getWorld()).isAssignableFrom
  1656. // (getType())) {
  1657. // only we don't do that because this forces us to find all the supertypes
  1658. // of the type,
  1659. // and if one of them is missing we fail, and it's not worth failing just to
  1660. // put out
  1661. // a warning message!
  1662. private boolean implementsSerializable(ResolvedType aType) {
  1663. if (aType.getSignature().equals(UnresolvedType.SERIALIZABLE.getSignature())) {
  1664. return true;
  1665. }
  1666. ResolvedType[] interfaces = aType.getDeclaredInterfaces();
  1667. for (ResolvedType anInterface : interfaces) {
  1668. if (anInterface.isMissing()) {
  1669. continue;
  1670. }
  1671. if (implementsSerializable(anInterface)) {
  1672. return true;
  1673. }
  1674. }
  1675. ResolvedType superType = aType.getSuperclass();
  1676. if (superType != null && !superType.isMissing()) {
  1677. return implementsSerializable(superType);
  1678. }
  1679. return false;
  1680. }
  1681. public boolean isAtLeastJava5() {
  1682. return (myGen.getMajor() >= Constants.MAJOR_1_5);
  1683. }
  1684. /**
  1685. * Return the next available field name with the specified 'prefix', e.g. for prefix 'class$' where class$0, class$1 exist then
  1686. * return class$2
  1687. */
  1688. public String allocateField(String prefix) {
  1689. int highestAllocated = -1;
  1690. List<BcelField> fs = getFieldGens();
  1691. for (BcelField field : fs) {
  1692. if (field.getName().startsWith(prefix)) {
  1693. try {
  1694. int num = Integer.parseInt(field.getName().substring(prefix.length()));
  1695. if (num > highestAllocated) {
  1696. highestAllocated = num;
  1697. }
  1698. } catch (NumberFormatException nfe) {
  1699. // something wrong with the number on the end of that
  1700. // field...
  1701. }
  1702. }
  1703. }
  1704. return prefix + Integer.toString(highestAllocated + 1);
  1705. }
  1706. }