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

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