Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Contributors
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Andy Clement 6Jul05 generics - signature attribute
  12. * ******************************************************************/
  13. package org.aspectj.weaver.bcel;
  14. import java.io.ByteArrayOutputStream;
  15. import java.io.File;
  16. import java.io.IOException;
  17. import java.io.PrintStream;
  18. import java.lang.reflect.Modifier;
  19. import java.util.ArrayList;
  20. import java.util.Collections;
  21. import java.util.Comparator;
  22. import java.util.HashMap;
  23. import java.util.Iterator;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Set;
  27. import java.util.SortedMap;
  28. import java.util.TreeMap;
  29. import org.aspectj.apache.bcel.Constants;
  30. import org.aspectj.apache.bcel.classfile.Attribute;
  31. import org.aspectj.apache.bcel.classfile.ConstantUtf8;
  32. import org.aspectj.apache.bcel.classfile.Field;
  33. import org.aspectj.apache.bcel.classfile.JavaClass;
  34. import org.aspectj.apache.bcel.classfile.Method;
  35. import org.aspectj.apache.bcel.classfile.Signature;
  36. import org.aspectj.apache.bcel.classfile.Unknown;
  37. import org.aspectj.apache.bcel.classfile.annotation.Annotation;
  38. import org.aspectj.apache.bcel.generic.ClassGen;
  39. import org.aspectj.apache.bcel.generic.ConstantPoolGen;
  40. import org.aspectj.apache.bcel.generic.FieldGen;
  41. import org.aspectj.apache.bcel.generic.InstructionConstants;
  42. import org.aspectj.apache.bcel.generic.InstructionFactory;
  43. import org.aspectj.apache.bcel.generic.InstructionHandle;
  44. import org.aspectj.apache.bcel.generic.InstructionList;
  45. import org.aspectj.apache.bcel.generic.ObjectType;
  46. import org.aspectj.apache.bcel.generic.PUSH;
  47. import org.aspectj.apache.bcel.generic.RETURN;
  48. import org.aspectj.apache.bcel.generic.Type;
  49. import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
  50. import org.aspectj.bridge.IMessage;
  51. import org.aspectj.bridge.ISourceLocation;
  52. import org.aspectj.bridge.SourceLocation;
  53. import org.aspectj.util.CollectionUtil;
  54. import org.aspectj.weaver.AjAttribute;
  55. import org.aspectj.weaver.BCException;
  56. import org.aspectj.weaver.Member;
  57. import org.aspectj.weaver.NameMangler;
  58. import org.aspectj.weaver.ResolvedMember;
  59. import org.aspectj.weaver.ResolvedType;
  60. import org.aspectj.weaver.Shadow;
  61. import org.aspectj.weaver.TypeVariable;
  62. import org.aspectj.weaver.UnresolvedType;
  63. import org.aspectj.weaver.WeaverMessages;
  64. import org.aspectj.weaver.WeaverStateInfo;
  65. import org.aspectj.weaver.World;
  66. import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  67. /**
  68. * Lazy lazy lazy.
  69. * We don't unpack the underlying class unless necessary. Things
  70. * like new methods and annotations accumulate in here until they
  71. * must be written out, don't add them to the underlying MethodGen!
  72. * Things are slightly different if this represents an Aspect.
  73. */
  74. public final class LazyClassGen {
  75. int highestLineNumber = 0; // ---- JSR 45 info
  76. private SortedMap /* <String, InlinedSourceFileInfo> */ inlinedFiles = new TreeMap();
  77. private boolean regenerateGenericSignatureAttribute = false;
  78. private BcelObjectType myType; // XXX is not set for types we create
  79. private ClassGen myGen;
  80. private ConstantPoolGen constantPoolGen;
  81. private World world;
  82. private String packageName = null;
  83. private List /*LazyMethodGen*/ methodGens = new ArrayList();
  84. private List /*LazyClassGen*/ classGens = new ArrayList();
  85. private List /*AnnotationGen*/ annotations = new ArrayList();
  86. private int childCounter = 0;
  87. private InstructionFactory fact;
  88. private boolean isSerializable = false;
  89. private boolean hasSerialVersionUIDField = false;
  90. private boolean hasClinit = false;
  91. // ---
  92. static class InlinedSourceFileInfo {
  93. int highestLineNumber;
  94. int offset; // calculated
  95. InlinedSourceFileInfo(int highestLineNumber) {
  96. this.highestLineNumber = highestLineNumber;
  97. }
  98. }
  99. void addInlinedSourceFileInfo(String fullpath, int highestLineNumber) {
  100. Object o = inlinedFiles.get(fullpath);
  101. if (o != null) {
  102. InlinedSourceFileInfo info = (InlinedSourceFileInfo) o;
  103. if (info.highestLineNumber < highestLineNumber) {
  104. info.highestLineNumber = highestLineNumber;
  105. }
  106. } else {
  107. inlinedFiles.put(fullpath, new InlinedSourceFileInfo(highestLineNumber));
  108. }
  109. }
  110. void calculateSourceDebugExtensionOffsets() {
  111. int i = roundUpToHundreds(highestLineNumber);
  112. for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
  113. InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
  114. element.offset = i;
  115. i = roundUpToHundreds(i + element.highestLineNumber);
  116. }
  117. }
  118. private static int roundUpToHundreds(int i) {
  119. return ((i / 100) + 1) * 100;
  120. }
  121. int getSourceDebugExtensionOffset(String fullpath) {
  122. return ((InlinedSourceFileInfo) inlinedFiles.get(fullpath)).offset;
  123. }
  124. private Unknown getSourceDebugExtensionAttribute() {
  125. int nameIndex = constantPoolGen.addUtf8("SourceDebugExtension");
  126. String data = getSourceDebugExtensionString();
  127. //System.err.println(data);
  128. byte[] bytes = Utility.stringToUTF(data);
  129. int length = bytes.length;
  130. return new Unknown(nameIndex, length, bytes, constantPoolGen.getConstantPool());
  131. }
  132. // private LazyClassGen() {}
  133. // public static void main(String[] args) {
  134. // LazyClassGen m = new LazyClassGen();
  135. // m.highestLineNumber = 37;
  136. // m.inlinedFiles.put("boo/baz/foo.java", new InlinedSourceFileInfo( 83));
  137. // m.inlinedFiles.put("boo/barz/foo.java", new InlinedSourceFileInfo(292));
  138. // m.inlinedFiles.put("boo/baz/moo.java", new InlinedSourceFileInfo(128));
  139. // m.calculateSourceDebugExtensionOffsets();
  140. // System.err.println(m.getSourceDebugExtensionString());
  141. // }
  142. // For the entire pathname, we're using package names. This is probably wrong.
  143. private String getSourceDebugExtensionString() {
  144. StringBuffer out = new StringBuffer();
  145. String myFileName = getFileName();
  146. // header section
  147. out.append("SMAP\n");
  148. out.append(myFileName);
  149. out.append("\nAspectJ\n");
  150. // stratum section
  151. out.append("*S AspectJ\n");
  152. // file section
  153. out.append("*F\n");
  154. out.append("1 ");
  155. out.append(myFileName);
  156. out.append("\n");
  157. int i = 2;
  158. for (Iterator iter = inlinedFiles.keySet().iterator(); iter.hasNext();) {
  159. String element = (String) iter.next();
  160. int ii = element.lastIndexOf('/');
  161. if (ii == -1) {
  162. out.append(i++); out.append(' ');
  163. out.append(element); out.append('\n');
  164. } else {
  165. out.append("+ "); out.append(i++); out.append(' ');
  166. out.append(element.substring(ii+1)); out.append('\n');
  167. out.append(element); out.append('\n');
  168. }
  169. }
  170. // emit line section
  171. out.append("*L\n");
  172. out.append("1#1,");
  173. out.append(highestLineNumber);
  174. out.append(":1,1\n");
  175. i = 2;
  176. for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
  177. InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
  178. out.append("1#");
  179. out.append(i++); out.append(',');
  180. out.append(element.highestLineNumber); out.append(":");
  181. out.append(element.offset + 1); out.append(",1\n");
  182. }
  183. // end section
  184. out.append("*E\n");
  185. // and finish up...
  186. return out.toString();
  187. }
  188. // ---- end JSR45-related stuff
  189. /** Emit disassembled class and newline to out */
  190. public static void disassemble(String path, String name, PrintStream out)
  191. throws IOException {
  192. if (null == out) {
  193. return;
  194. }
  195. //out.println("classPath: " + classPath);
  196. BcelWorld world = new BcelWorld(path);
  197. LazyClassGen clazz = new LazyClassGen(BcelWorld.getBcelObjectType(world.resolve(name)));
  198. clazz.print(out);
  199. out.println();
  200. }
  201. public int getNewGeneratedNameTag() {
  202. return childCounter++;
  203. }
  204. // ----
  205. public LazyClassGen(
  206. String class_name,
  207. String super_class_name,
  208. String file_name,
  209. int access_flags,
  210. String[] interfaces,
  211. World world)
  212. {
  213. myGen = new ClassGen(class_name, super_class_name, file_name, access_flags, interfaces);
  214. constantPoolGen = myGen.getConstantPool();
  215. fact = new InstructionFactory(myGen, constantPoolGen);
  216. regenerateGenericSignatureAttribute = true;
  217. this.world = world;
  218. }
  219. //Non child type, so it comes from a real type in the world.
  220. public LazyClassGen(BcelObjectType myType) {
  221. myGen = new ClassGen(myType.getJavaClass());
  222. constantPoolGen = myGen.getConstantPool();
  223. fact = new InstructionFactory(myGen, constantPoolGen);
  224. this.myType = myType;
  225. this.world = myType.getResolvedTypeX().getWorld();
  226. /* Does this class support serialization */
  227. if (implementsSerializable(getType())) {
  228. isSerializable = true;
  229. // ResolvedMember[] fields = getType().getDeclaredFields();
  230. // for (int i = 0; i < fields.length; i++) {
  231. // ResolvedMember field = fields[i];
  232. // if (field.getName().equals("serialVersionUID")
  233. // && field.isStatic() && field.getType().equals(ResolvedType.LONG)) {
  234. // hasSerialVersionUIDField = true;
  235. // }
  236. // }
  237. hasSerialVersionUIDField = hasSerialVersionUIDField(getType());
  238. ResolvedMember[] methods = getType().getDeclaredMethods();
  239. for (int i = 0; i < methods.length; i++) {
  240. ResolvedMember method = methods[i];
  241. if (method.getName().equals("<clinit>")) {
  242. hasClinit = true;
  243. }
  244. }
  245. }
  246. Method[] methods = myGen.getMethods();
  247. for (int i = 0; i < methods.length; i++) {
  248. addMethodGen(new LazyMethodGen(methods[i], this));
  249. }
  250. }
  251. public static boolean hasSerialVersionUIDField (ResolvedType type) {
  252. ResolvedMember[] fields = type.getDeclaredFields();
  253. for (int i = 0; i < fields.length; i++) {
  254. ResolvedMember field = fields[i];
  255. if (field.getName().equals("serialVersionUID")
  256. && field.isStatic() && field.getType().equals(ResolvedType.LONG)) {
  257. return true;
  258. }
  259. }
  260. return false;
  261. }
  262. // public void addAttribute(Attribute i) {
  263. // myGen.addAttribute(i);
  264. // }
  265. // ----
  266. public String getInternalClassName() {
  267. return getConstantPoolGen().getConstantPool().getConstantString(
  268. myGen.getClassNameIndex(),
  269. Constants.CONSTANT_Class);
  270. }
  271. public String getInternalFileName() {
  272. String str = getInternalClassName();
  273. int index = str.lastIndexOf('/');
  274. if (index == -1) {
  275. return getFileName();
  276. } else {
  277. return str.substring(0, index + 1) + getFileName();
  278. }
  279. }
  280. public File getPackagePath(File root) {
  281. String str = getInternalClassName();
  282. int index = str.lastIndexOf('/');
  283. if (index == -1)
  284. return root;
  285. return new File(root, str.substring(0, index));
  286. }
  287. /** Returns the packagename - if its the default package we return an empty string
  288. */
  289. public String getPackageName() {
  290. if (packageName!=null) return packageName;
  291. String str = getInternalClassName();
  292. int index = str.indexOf("<");
  293. if (index!=-1) str = str.substring(0,index); // strip off the generics guff
  294. index= str.lastIndexOf("/");
  295. if (index==-1) return "";
  296. return str.substring(0,index).replace('/','.');
  297. }
  298. public String getClassId() {
  299. String str = getInternalClassName();
  300. int index = str.lastIndexOf('/');
  301. if (index == -1)
  302. return str;
  303. return str.substring(index + 1);
  304. }
  305. public void addMethodGen(LazyMethodGen gen) {
  306. //assert gen.getClassName() == super.getClassName();
  307. methodGens.add(gen);
  308. if (highestLineNumber < gen.highestLineNumber) highestLineNumber = gen.highestLineNumber;
  309. }
  310. public void addMethodGen(LazyMethodGen gen, ISourceLocation sourceLocation) {
  311. addMethodGen(gen);
  312. if (!gen.getMethod().isPrivate()) {
  313. warnOnAddedMethod(gen.getMethod(),sourceLocation);
  314. }
  315. }
  316. public void errorOnAddedField (Field field, ISourceLocation sourceLocation) {
  317. if (isSerializable && !hasSerialVersionUIDField) {
  318. getWorld().getLint().serialVersionUIDBroken.signal(
  319. new String[] {
  320. myType.getResolvedTypeX().getName().toString(),
  321. field.getName()
  322. },
  323. sourceLocation,
  324. null);
  325. }
  326. }
  327. public void warnOnAddedInterface (String name, ISourceLocation sourceLocation) {
  328. warnOnModifiedSerialVersionUID(sourceLocation,"added interface " + name);
  329. }
  330. public void warnOnAddedMethod (Method method, ISourceLocation sourceLocation) {
  331. warnOnModifiedSerialVersionUID(sourceLocation,"added non-private method " + method.getName());
  332. }
  333. public void warnOnAddedStaticInitializer (Shadow shadow, ISourceLocation sourceLocation) {
  334. if (!hasClinit) {
  335. warnOnModifiedSerialVersionUID(sourceLocation,"added static initializer");
  336. }
  337. }
  338. public void warnOnModifiedSerialVersionUID (ISourceLocation sourceLocation, String reason) {
  339. if (isSerializable && !hasSerialVersionUIDField)
  340. getWorld().getLint().needsSerialVersionUIDField.signal(
  341. new String[] {
  342. myType.getResolvedTypeX().getName().toString(),
  343. reason
  344. },
  345. sourceLocation,
  346. null);
  347. }
  348. public World getWorld () {
  349. return world;
  350. }
  351. public List getMethodGens() {
  352. return methodGens; //???Collections.unmodifiableList(methodGens);
  353. }
  354. // FIXME asc Should be collection returned here
  355. public Field[] getFieldGens() {
  356. return myGen.getFields();
  357. }
  358. public Field getField(String name) {
  359. Field[] allFields = myGen.getFields();
  360. if (allFields==null) return null;
  361. for (int i = 0; i < allFields.length; i++) {
  362. Field field = allFields[i];
  363. if (field.getName().equals(name)) return field;
  364. }
  365. return null;
  366. }
  367. // FIXME asc How do the ones on the underlying class surface if this just returns new ones added?
  368. // FIXME asc ...although no one calls this right now !
  369. public List getAnnotations() {
  370. return annotations;
  371. }
  372. private void writeBack(BcelWorld world) {
  373. if (getConstantPoolGen().getSize() > Short.MAX_VALUE) {
  374. reportClassTooBigProblem();
  375. return;
  376. }
  377. if (annotations.size()>0) {
  378. for (Iterator iter = annotations.iterator(); iter.hasNext();) {
  379. AnnotationGen element = (AnnotationGen) iter.next();
  380. myGen.addAnnotation(element);
  381. }
  382. // Attribute[] annAttributes = org.aspectj.apache.bcel.classfile.Utility.getAnnotationAttributes(getConstantPoolGen(),annotations);
  383. // for (int i = 0; i < annAttributes.length; i++) {
  384. // Attribute attribute = annAttributes[i];
  385. // System.err.println("Adding attribute for "+attribute);
  386. // myGen.addAttribute(attribute);
  387. // }
  388. }
  389. // Add a weaver version attribute to the file being produced (if necessary...)
  390. boolean hasVersionAttribute = false;
  391. Attribute[] attrs = myGen.getAttributes();
  392. for (int i = 0; i < attrs.length && !hasVersionAttribute; i++) {
  393. Attribute attribute = attrs[i];
  394. if (attribute.getName().equals("org.aspectj.weaver.WeaverVersion")) hasVersionAttribute=true;
  395. }
  396. if (!hasVersionAttribute)
  397. myGen.addAttribute(BcelAttributes.bcelAttribute(new AjAttribute.WeaverVersionInfo(),getConstantPoolGen()));
  398. if (myType != null && myType.getWeaverState() != null) {
  399. myGen.addAttribute(BcelAttributes.bcelAttribute(
  400. new AjAttribute.WeaverState(myType.getWeaverState()),
  401. getConstantPoolGen()));
  402. }
  403. //FIXME ATAJ needed only for slow Aspects.aspectOf() - keep or remove
  404. //make a lot of test fail since the test compare weaved class file
  405. // based on some test data as text files...
  406. // if (!myGen.isInterface()) {
  407. // addAjClassField();
  408. // }
  409. addAjcInitializers();
  410. int len = methodGens.size();
  411. myGen.setMethods(new Method[0]);
  412. calculateSourceDebugExtensionOffsets();
  413. for (int i = 0; i < len; i++) {
  414. LazyMethodGen gen = (LazyMethodGen) methodGens.get(i);
  415. // we skip empty clinits
  416. if (isEmptyClinit(gen)) continue;
  417. myGen.addMethod(gen.getMethod());
  418. }
  419. if (inlinedFiles.size() != 0) {
  420. if (hasSourceDebugExtensionAttribute(myGen)) {
  421. world.showMessage(
  422. IMessage.WARNING,
  423. WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45,getFileName()),
  424. null,
  425. null);
  426. }
  427. // 17Feb05 - ASC - Skip this for now - it crashes IBM 1.4.2 jvms (pr80430). Will be revisited when contents
  428. // of attribute are confirmed to be correct.
  429. // myGen.addAttribute(getSourceDebugExtensionAttribute());
  430. }
  431. fixupGenericSignatureAttribute();
  432. }
  433. /**
  434. * When working with 1.5 generics, a signature attribute is attached to the type which indicates
  435. * how it was declared. This routine ensures the signature attribute for what we are about
  436. * to write out is correct. Basically its responsibilities are:
  437. * 1. Checking whether the attribute needs changing (i.e. did weaving change the type hierarchy)
  438. * 2. If it did, removing the old attribute
  439. * 3. Check if we need an attribute at all, are we generic? are our supertypes parameterized/generic?
  440. * 4. Build the new attribute which includes all typevariable, supertype and superinterface information
  441. */
  442. private void fixupGenericSignatureAttribute () {
  443. if (getWorld() != null && !getWorld().isInJava5Mode()) return;
  444. // TODO asc generics Temporarily assume that types we generate dont need a signature attribute (closure/etc).. will need revisiting no doubt...
  445. if (myType==null) return;
  446. // 1. Has anything changed that would require us to modify this attribute?
  447. if (!regenerateGenericSignatureAttribute) return;
  448. // 2. Find the old attribute
  449. Signature sigAttr = null;
  450. if (myType!=null) { // if null, this is a type built from scratch, it won't already have a sig attribute
  451. Attribute[] as = myGen.getAttributes();
  452. for (int i = 0; i < as.length; i++) {
  453. Attribute attribute = as[i];
  454. if (attribute.getName().equals("Signature")) sigAttr = (Signature)attribute;
  455. }
  456. }
  457. // 3. Do we need an attribute?
  458. boolean needAttribute = false;
  459. if (sigAttr!=null) needAttribute = true; // If we had one before, we definetly still need one as types can't be 'removed' from the hierarchy
  460. // check the interfaces
  461. if (!needAttribute) {
  462. if (myType==null) {
  463. boolean stop = true;
  464. }
  465. ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
  466. for (int i = 0; i < interfaceRTXs.length; i++) {
  467. ResolvedType typeX = interfaceRTXs[i];
  468. if (typeX.isGenericType() || typeX.isParameterizedType()) needAttribute = true;
  469. }
  470. // check the supertype
  471. ResolvedType superclassRTX = myType.getSuperclass();
  472. if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) needAttribute = true;
  473. }
  474. if (needAttribute) {
  475. StringBuffer signature = new StringBuffer();
  476. // first, the type variables...
  477. TypeVariable[] tVars = myType.getTypeVariables();
  478. if (tVars.length>0) {
  479. signature.append("<");
  480. for (int i = 0; i < tVars.length; i++) {
  481. TypeVariable variable = tVars[i];
  482. if (i!=0) signature.append(",");
  483. signature.append(variable.getSignature());
  484. }
  485. signature.append(">");
  486. }
  487. // now the supertype
  488. String supersig = myType.getSuperclass().getSignatureForAttribute();
  489. signature.append(supersig);
  490. ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
  491. for (int i = 0; i < interfaceRTXs.length; i++) {
  492. String s = interfaceRTXs[i].getSignatureForAttribute();
  493. signature.append(s);
  494. }
  495. if (sigAttr!=null) myGen.removeAttribute(sigAttr);
  496. myGen.addAttribute(createSignatureAttribute(signature.toString()));
  497. }
  498. }
  499. /**
  500. * Helper method to create a signature attribute based on a string signature:
  501. * e.g. "Ljava/lang/Object;LI<Ljava/lang/Double;>;"
  502. */
  503. private Signature createSignatureAttribute(String signature) {
  504. int nameIndex = constantPoolGen.addUtf8("Signature");
  505. int sigIndex = constantPoolGen.addUtf8(signature);
  506. return new Signature(nameIndex,2,sigIndex,constantPoolGen.getConstantPool());
  507. }
  508. /**
  509. *
  510. */
  511. private void reportClassTooBigProblem() {
  512. // PR 59208
  513. // we've generated a class that is just toooooooooo big (you've been generating programs
  514. // again haven't you? come on, admit it, no-one writes classes this big by hand).
  515. // create an empty myGen so that we can give back a return value that doesn't upset the
  516. // rest of the process.
  517. myGen = new ClassGen(myGen.getClassName(), myGen.getSuperclassName(),
  518. myGen.getFileName(), myGen.getAccessFlags(), myGen.getInterfaceNames());
  519. // raise an error against this compilation unit.
  520. getWorld().showMessage(
  521. IMessage.ERROR,
  522. WeaverMessages.format(WeaverMessages.CLASS_TOO_BIG,
  523. this.getClassName()),
  524. new SourceLocation(new File(myGen.getFileName()),0), null
  525. );
  526. }
  527. private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
  528. ConstantPoolGen pool = gen.getConstantPool();
  529. Attribute[] attrs = gen.getAttributes();
  530. for (int i = 0; i < attrs.length; i++) {
  531. if ("SourceDebugExtension"
  532. .equals(((ConstantUtf8) pool.getConstant(attrs[i].getNameIndex())).getBytes())) {
  533. return true;
  534. }
  535. }
  536. return false;
  537. }
  538. public JavaClass getJavaClass(BcelWorld world) {
  539. writeBack(world);
  540. return myGen.getJavaClass();
  541. }
  542. public byte [] getJavaClassBytesIncludingReweavable(BcelWorld world){
  543. writeBack(world);
  544. byte [] wovenClassFileData = myGen.getJavaClass().getBytes();
  545. WeaverStateInfo wsi = myType.getWeaverState();//getOrCreateWeaverStateInfo();
  546. if(wsi != null && wsi.isReweavable()){ // && !reweavableDataInserted
  547. //reweavableDataInserted = true;
  548. return wsi.replaceKeyWithDiff(wovenClassFileData);
  549. } else{
  550. return wovenClassFileData;
  551. }
  552. }
  553. public void addGeneratedInner(LazyClassGen newClass) {
  554. classGens.add(newClass);
  555. }
  556. public void addInterface(UnresolvedType typeX, ISourceLocation sourceLocation) {
  557. regenerateGenericSignatureAttribute = true;
  558. myGen.addInterface(typeX.getRawName());
  559. if (!typeX.equals(UnresolvedType.SERIALIZABLE))
  560. warnOnAddedInterface(typeX.getName(),sourceLocation);
  561. }
  562. public void setSuperClass(ResolvedType typeX) {
  563. regenerateGenericSignatureAttribute = true;
  564. myType.addParent(typeX); // used for the attribute
  565. if (typeX.getGenericType()!=null) typeX = typeX.getGenericType();
  566. myGen.setSuperclassName(typeX.getName()); // used in the real class data
  567. }
  568. public String getSuperClassname() {
  569. return myGen.getSuperclassName();
  570. }
  571. // FIXME asc not great that some of these ask the gen and some ask the type ! (see the related setters too)
  572. public ResolvedType getSuperClass() {
  573. return myType.getSuperclass();
  574. }
  575. public String[] getInterfaceNames() {
  576. return myGen.getInterfaceNames();
  577. }
  578. // non-recursive, may be a bug, ha ha.
  579. private List getClassGens() {
  580. List ret = new ArrayList();
  581. ret.add(this);
  582. ret.addAll(classGens);
  583. return ret;
  584. }
  585. public List getChildClasses(BcelWorld world) {
  586. if (classGens.isEmpty()) return Collections.EMPTY_LIST;
  587. List ret = new ArrayList();
  588. for (Iterator i = classGens.iterator(); i.hasNext();) {
  589. LazyClassGen clazz = (LazyClassGen) i.next();
  590. byte[] bytes = clazz.getJavaClass(world).getBytes();
  591. String name = clazz.getName();
  592. int index = name.lastIndexOf('$');
  593. // XXX this could be bad, check use of dollar signs.
  594. name = name.substring(index+1);
  595. ret.add(new UnwovenClassFile.ChildClass(name, bytes));
  596. }
  597. return ret;
  598. }
  599. public String toString() {
  600. return toShortString();
  601. }
  602. public String toShortString() {
  603. String s =
  604. org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getAccessFlags(), true);
  605. if (s != "")
  606. s += " ";
  607. s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getAccessFlags());
  608. s += " ";
  609. s += myGen.getClassName();
  610. return s;
  611. }
  612. public String toLongString() {
  613. ByteArrayOutputStream s = new ByteArrayOutputStream();
  614. print(new PrintStream(s));
  615. return new String(s.toByteArray());
  616. }
  617. public void print() { print(System.out); }
  618. public void print(PrintStream out) {
  619. List classGens = getClassGens();
  620. for (Iterator iter = classGens.iterator(); iter.hasNext();) {
  621. LazyClassGen element = (LazyClassGen) iter.next();
  622. element.printOne(out);
  623. if (iter.hasNext()) out.println();
  624. }
  625. }
  626. private void printOne(PrintStream out) {
  627. out.print(toShortString());
  628. out.print(" extends ");
  629. out.print(
  630. org.aspectj.apache.bcel.classfile.Utility.compactClassName(
  631. myGen.getSuperclassName(),
  632. false));
  633. int size = myGen.getInterfaces().length;
  634. if (size > 0) {
  635. out.print(" implements ");
  636. for (int i = 0; i < size; i++) {
  637. out.print(myGen.getInterfaceNames()[i]);
  638. if (i < size - 1)
  639. out.print(", ");
  640. }
  641. }
  642. out.print(":");
  643. out.println();
  644. // XXX make sure to pass types correctly around, so this doesn't happen.
  645. if (myType != null) {
  646. myType.printWackyStuff(out);
  647. }
  648. Field[] fields = myGen.getFields();
  649. for (int i = 0, len = fields.length; i < len; i++) {
  650. out.print(" ");
  651. out.println(fields[i]);
  652. }
  653. List methodGens = getMethodGens();
  654. for (Iterator iter = methodGens.iterator(); iter.hasNext();) {
  655. LazyMethodGen gen = (LazyMethodGen) iter.next();
  656. // we skip empty clinits
  657. if (isEmptyClinit(gen)) continue;
  658. gen.print(out, (myType != null ? myType.getWeaverVersionAttribute() : WeaverVersionInfo.UNKNOWN));
  659. if (iter.hasNext()) out.println();
  660. }
  661. // out.println(" ATTRIBS: " + Arrays.asList(myGen.getAttributes()));
  662. out.println("end " + toShortString());
  663. }
  664. private boolean isEmptyClinit(LazyMethodGen gen) {
  665. if (!gen.getName().equals("<clinit>")) return false;
  666. //System.err.println("checking clinig: " + gen);
  667. InstructionHandle start = gen.getBody().getStart();
  668. while (start != null) {
  669. if (Range.isRangeHandle(start) || (start.getInstruction() instanceof RETURN)) {
  670. start = start.getNext();
  671. } else {
  672. return false;
  673. }
  674. }
  675. return true;
  676. }
  677. public ConstantPoolGen getConstantPoolGen() {
  678. return constantPoolGen;
  679. }
  680. public String getName() {
  681. return myGen.getClassName();
  682. }
  683. public boolean isWoven() {
  684. return myType.getWeaverState() != null;
  685. }
  686. public boolean isReweavable() {
  687. if (myType.getWeaverState()==null) return true;
  688. return myType.getWeaverState().isReweavable();
  689. }
  690. public Set getAspectsAffectingType() {
  691. if (myType.getWeaverState()==null) return null;
  692. return myType.getWeaverState().getAspectsAffectingType();
  693. }
  694. public WeaverStateInfo getOrCreateWeaverStateInfo(boolean inReweavableMode) {
  695. WeaverStateInfo ret = myType.getWeaverState();
  696. if (ret != null) return ret;
  697. ret = new WeaverStateInfo(inReweavableMode);
  698. myType.setWeaverState(ret);
  699. return ret;
  700. }
  701. public InstructionFactory getFactory() {
  702. return fact;
  703. }
  704. public LazyMethodGen getStaticInitializer() {
  705. for (Iterator i = methodGens.iterator(); i.hasNext();) {
  706. LazyMethodGen gen = (LazyMethodGen) i.next();
  707. if (gen.getName().equals("<clinit>")) return gen;
  708. }
  709. LazyMethodGen clinit = new LazyMethodGen(
  710. Modifier.STATIC,
  711. Type.VOID,
  712. "<clinit>",
  713. new Type[0],
  714. CollectionUtil.NO_STRINGS,
  715. this);
  716. clinit.getBody().insert(InstructionConstants.RETURN);
  717. methodGens.add(clinit);
  718. return clinit;
  719. }
  720. public LazyMethodGen getAjcPreClinit() {
  721. for (Iterator i = methodGens.iterator(); i.hasNext();) {
  722. LazyMethodGen gen = (LazyMethodGen) i.next();
  723. if (gen.getName().equals(NameMangler.AJC_PRE_CLINIT_NAME)) return gen;
  724. }
  725. LazyMethodGen ajcClinit = new LazyMethodGen(
  726. Modifier.STATIC,
  727. Type.VOID,
  728. NameMangler.AJC_PRE_CLINIT_NAME,
  729. new Type[0],
  730. CollectionUtil.NO_STRINGS,
  731. this);
  732. ajcClinit.getBody().insert(InstructionConstants.RETURN);
  733. methodGens.add(ajcClinit);
  734. getStaticInitializer().getBody().insert(Utility.createInvoke(getFactory(), ajcClinit));
  735. return ajcClinit;
  736. }
  737. // reflective thisJoinPoint support
  738. Map/*BcelShadow, Field*/ tjpFields = new HashMap();
  739. public static final ObjectType proceedingTjpType =
  740. new ObjectType("org.aspectj.lang.ProceedingJoinPoint");
  741. public static final ObjectType tjpType =
  742. new ObjectType("org.aspectj.lang.JoinPoint");
  743. public static final ObjectType staticTjpType =
  744. new ObjectType("org.aspectj.lang.JoinPoint$StaticPart");
  745. public static final ObjectType enclosingStaticTjpType =
  746. new ObjectType("org.aspectj.lang.JoinPoint$EnclosingStaticPart");
  747. private static final ObjectType sigType =
  748. new ObjectType("org.aspectj.lang.Signature");
  749. // private static final ObjectType slType =
  750. // new ObjectType("org.aspectj.lang.reflect.SourceLocation");
  751. private static final ObjectType factoryType =
  752. new ObjectType("org.aspectj.runtime.reflect.Factory");
  753. private static final ObjectType classType =
  754. new ObjectType("java.lang.Class");
  755. public Field getTjpField(BcelShadow shadow, final boolean isEnclosingJp) {
  756. Field ret = (Field)tjpFields.get(shadow);
  757. if (ret != null) return ret;
  758. int modifiers = Modifier.STATIC | Modifier.FINAL;
  759. // XXX - Do we ever inline before or after advice? If we do, then we
  760. // better include them in the check below. (or just change it to
  761. // shadow.getEnclosingMethod().getCanInline())
  762. // If the enclosing method is around advice, we could inline the join point
  763. // that has led to this shadow. If we do that then the TJP we are creating
  764. // here must be PUBLIC so it is visible to the type in which the
  765. // advice is inlined. (PR71377)
  766. LazyMethodGen encMethod = shadow.getEnclosingMethod();
  767. boolean shadowIsInAroundAdvice = false;
  768. if (encMethod!=null && encMethod.getName().startsWith(NameMangler.PREFIX+"around")) {
  769. shadowIsInAroundAdvice = true;
  770. }
  771. if (getType().isInterface() || shadowIsInAroundAdvice) {
  772. modifiers |= Modifier.PUBLIC;
  773. }
  774. else {
  775. modifiers |= Modifier.PRIVATE;
  776. }
  777. ObjectType jpType = null;
  778. if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have different staticjp types in 1.2
  779. jpType = staticTjpType;
  780. } else {
  781. jpType = isEnclosingJp?enclosingStaticTjpType:staticTjpType;
  782. }
  783. ret = new FieldGen(modifiers,jpType,"ajc$tjp_" + tjpFields.size(),getConstantPoolGen()).getField();
  784. addField(ret);
  785. tjpFields.put(shadow, ret);
  786. return ret;
  787. }
  788. //FIXME ATAJ needed only for slow Aspects.aspectOf - keep or remove
  789. // private void addAjClassField() {
  790. // // Andy: Why build it again??
  791. // Field ajClassField = new FieldGen(
  792. // Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC,
  793. // classType,
  794. // "aj$class",
  795. // getConstantPoolGen()).getField();
  796. // addField(ajClassField);
  797. //
  798. // InstructionList il = new InstructionList();
  799. // il.append(new PUSH(getConstantPoolGen(), getClassName()));
  800. // il.append(fact.createInvoke("java.lang.Class", "forName", classType,
  801. // new Type[] {Type.STRING}, Constants.INVOKESTATIC));
  802. // il.append(fact.createFieldAccess(getClassName(), ajClassField.getName(),
  803. // classType, Constants.PUTSTATIC));
  804. //
  805. // getStaticInitializer().getBody().insert(il);
  806. // }
  807. private void addAjcInitializers() {
  808. if (tjpFields.size() == 0) return;
  809. InstructionList il = initializeAllTjps();
  810. getStaticInitializer().getBody().insert(il);
  811. }
  812. private InstructionList initializeAllTjps() {
  813. InstructionList list = new InstructionList();
  814. InstructionFactory fact = getFactory();
  815. // make a new factory
  816. list.append(fact.createNew(factoryType));
  817. list.append(InstructionFactory.createDup(1));
  818. list.append(new PUSH(getConstantPoolGen(), getFileName()));
  819. // load the current Class object
  820. //XXX check that this works correctly for inners/anonymous
  821. list.append(new PUSH(getConstantPoolGen(), getClassName()));
  822. //XXX do we need to worry about the fact the theorectically this could throw
  823. //a ClassNotFoundException
  824. list.append(fact.createInvoke("java.lang.Class", "forName", classType,
  825. new Type[] {Type.STRING}, Constants.INVOKESTATIC));
  826. list.append(fact.createInvoke(factoryType.getClassName(), "<init>",
  827. Type.VOID, new Type[] {Type.STRING, classType},
  828. Constants.INVOKESPECIAL));
  829. list.append(InstructionFactory.createStore(factoryType, 0));
  830. List entries = new ArrayList(tjpFields.entrySet());
  831. Collections.sort(entries, new Comparator() {
  832. public int compare(Object a, Object b) {
  833. Map.Entry ae = (Map.Entry) a;
  834. Map.Entry be = (Map.Entry) b;
  835. return ((Field) ae.getValue())
  836. .getName()
  837. .compareTo(((Field)be.getValue()).getName());
  838. }
  839. });
  840. for (Iterator i = entries.iterator(); i.hasNext(); ) {
  841. Map.Entry entry = (Map.Entry)i.next();
  842. initializeTjp(fact, list, (Field)entry.getValue(), (BcelShadow)entry.getKey());
  843. }
  844. return list;
  845. }
  846. private void initializeTjp(InstructionFactory fact, InstructionList list,
  847. Field field, BcelShadow shadow)
  848. {
  849. Member sig = shadow.getSignature();
  850. //ResolvedMember mem = shadow.getSignature().resolve(shadow.getWorld());
  851. // load the factory
  852. list.append(InstructionFactory.createLoad(factoryType, 0));
  853. // load the kind
  854. list.append(new PUSH(getConstantPoolGen(), shadow.getKind().getName()));
  855. // create the signature
  856. list.append(InstructionFactory.createLoad(factoryType, 0));
  857. if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have optimized factory methods in 1.2
  858. list.append(new PUSH(getConstantPoolGen(), sig.getSignatureString(shadow.getWorld())));
  859. list.append(fact.createInvoke(factoryType.getClassName(),
  860. sig.getSignatureMakerName(),
  861. new ObjectType(sig.getSignatureType()),
  862. new Type[] { Type.STRING },
  863. Constants.INVOKEVIRTUAL));
  864. } else if (sig.getKind().equals(Member.METHOD)) {
  865. BcelWorld w = shadow.getWorld();
  866. // For methods, push the parts of the signature on.
  867. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
  868. list.append(new PUSH(getConstantPoolGen(),sig.getName()));
  869. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
  870. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
  871. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
  872. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getExceptions(w))));
  873. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getReturnType())));
  874. // And generate a call to the variant of makeMethodSig() that takes 7 strings
  875. list.append(fact.createInvoke(factoryType.getClassName(),
  876. sig.getSignatureMakerName(),
  877. new ObjectType(sig.getSignatureType()),
  878. new Type[] { Type.STRING,Type.STRING,Type.STRING,Type.STRING,Type.STRING,Type.STRING,Type.STRING },
  879. Constants.INVOKEVIRTUAL));
  880. } else if (sig.getKind().equals(Member.HANDLER)) {
  881. BcelWorld w = shadow.getWorld();
  882. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
  883. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
  884. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
  885. list.append(fact.createInvoke(factoryType.getClassName(),
  886. sig.getSignatureMakerName(),
  887. new ObjectType(sig.getSignatureType()),
  888. new Type[] { Type.STRING, Type.STRING, Type.STRING },
  889. Constants.INVOKEVIRTUAL));
  890. } else if(sig.getKind().equals(Member.CONSTRUCTOR)) {
  891. BcelWorld w = shadow.getWorld();
  892. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
  893. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
  894. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
  895. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
  896. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getExceptions(w))));
  897. list.append(fact.createInvoke(factoryType.getClassName(),
  898. sig.getSignatureMakerName(),
  899. new ObjectType(sig.getSignatureType()),
  900. new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING },
  901. Constants.INVOKEVIRTUAL));
  902. } else if(sig.getKind().equals(Member.FIELD)) {
  903. BcelWorld w = shadow.getWorld();
  904. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
  905. list.append(new PUSH(getConstantPoolGen(),sig.getName()));
  906. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
  907. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getReturnType())));
  908. list.append(fact.createInvoke(factoryType.getClassName(),
  909. sig.getSignatureMakerName(),
  910. new ObjectType(sig.getSignatureType()),
  911. new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING },
  912. Constants.INVOKEVIRTUAL));
  913. } else if(sig.getKind().equals(Member.ADVICE)) {
  914. BcelWorld w = shadow.getWorld();
  915. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
  916. list.append(new PUSH(getConstantPoolGen(),sig.getName()));
  917. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
  918. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterTypes())));
  919. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getParameterNames(w))));
  920. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getExceptions(w))));
  921. list.append(new PUSH(getConstantPoolGen(),makeString((sig.getReturnType()))));
  922. list.append(fact.createInvoke(factoryType.getClassName(),
  923. sig.getSignatureMakerName(),
  924. new ObjectType(sig.getSignatureType()),
  925. new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING },
  926. Constants.INVOKEVIRTUAL));
  927. } else if(sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
  928. BcelWorld w = shadow.getWorld();
  929. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getModifiers(w))));
  930. list.append(new PUSH(getConstantPoolGen(),makeString(sig.getDeclaringType())));
  931. list.append(fact.createInvoke(factoryType.getClassName(),
  932. sig.getSignatureMakerName(),
  933. new ObjectType(sig.getSignatureType()),
  934. new Type[] { Type.STRING, Type.STRING },
  935. Constants.INVOKEVIRTUAL));
  936. } else {
  937. list.append(new PUSH(getConstantPoolGen(), sig.getSignatureString(shadow.getWorld())));
  938. list.append(fact.createInvoke(factoryType.getClassName(),
  939. sig.getSignatureMakerName(),
  940. new ObjectType(sig.getSignatureType()),
  941. new Type[] { Type.STRING },
  942. Constants.INVOKEVIRTUAL));
  943. }
  944. //XXX should load source location from shadow
  945. list.append(Utility.createConstant(fact, shadow.getSourceLine()));
  946. final String factoryMethod;
  947. if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have makeESJP() in 1.2
  948. list.append(fact.createInvoke(factoryType.getClassName(),
  949. "makeSJP", staticTjpType,
  950. new Type[] { Type.STRING, sigType, Type.INT},
  951. Constants.INVOKEVIRTUAL));
  952. // put it in the field
  953. list.append(fact.createFieldAccess(getClassName(), field.getName(),staticTjpType, Constants.PUTSTATIC));
  954. } else {
  955. if (staticTjpType.equals(field.getType())) {
  956. factoryMethod = "makeSJP";
  957. } else if (enclosingStaticTjpType.equals(field.getType())) {
  958. factoryMethod = "makeESJP";
  959. } else {
  960. throw new Error("should not happen");
  961. }
  962. list.append(fact.createInvoke(factoryType.getClassName(),
  963. factoryMethod, field.getType(),
  964. new Type[] { Type.STRING, sigType, Type.INT},
  965. Constants.INVOKEVIRTUAL));
  966. // put it in the field
  967. list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
  968. }
  969. }
  970. protected String makeString(int i) {
  971. return Integer.toString(i, 16); //??? expensive
  972. }
  973. protected String makeString(UnresolvedType t) {
  974. // this is the inverse of the odd behavior for Class.forName w/ arrays
  975. if (t.isArray()) {
  976. // this behavior matches the string used by the eclipse compiler for Foo.class literals
  977. return t.getSignature().replace('/', '.');
  978. } else {
  979. return t.getName();
  980. }
  981. }
  982. protected String makeString(UnresolvedType[] types) {
  983. if (types == null) return "";
  984. StringBuffer buf = new StringBuffer();
  985. for (int i = 0, len=types.length; i < len; i++) {
  986. buf.append(makeString(types[i]));
  987. buf.append(':');
  988. }
  989. return buf.toString();
  990. }
  991. protected String makeString(String[] names) {
  992. if (names == null) return "";
  993. StringBuffer buf = new StringBuffer();
  994. for (int i = 0, len=names.length; i < len; i++) {
  995. buf.append(names[i]);
  996. buf.append(':');
  997. }
  998. return buf.toString();
  999. }
  1000. public ResolvedType getType() {
  1001. if (myType == null) return null;
  1002. return myType.getResolvedTypeX();
  1003. }
  1004. public BcelObjectType getBcelObjectType() {
  1005. return myType;
  1006. }
  1007. public String getFileName() {
  1008. return myGen.getFileName();
  1009. }
  1010. private void addField(Field field) {
  1011. myGen.addField(field);
  1012. }
  1013. public void replaceField(Field oldF, Field newF){
  1014. myGen.removeField(oldF);
  1015. myGen.addField(newF);
  1016. }
  1017. public void addField(Field field, ISourceLocation sourceLocation) {
  1018. addField(field);
  1019. if (!(field.isPrivate()
  1020. && (field.isStatic() || field.isTransient()))) {
  1021. errorOnAddedField(field,sourceLocation);
  1022. }
  1023. }
  1024. public String getClassName() {
  1025. return myGen.getClassName();
  1026. }
  1027. public boolean isInterface() {
  1028. return myGen.isInterface();
  1029. }
  1030. public boolean isAbstract() {
  1031. return myGen.isAbstract();
  1032. }
  1033. public LazyMethodGen getLazyMethodGen(Member m) {
  1034. return getLazyMethodGen(m.getName(), m.getSignature(),false);
  1035. }
  1036. public LazyMethodGen getLazyMethodGen(String name, String signature) {
  1037. return getLazyMethodGen(name,signature,false);
  1038. }
  1039. public LazyMethodGen getLazyMethodGen(String name, String signature,boolean allowMissing) {
  1040. for (Iterator i = methodGens.iterator(); i.hasNext();) {
  1041. LazyMethodGen gen = (LazyMethodGen) i.next();
  1042. if (gen.getName().equals(name) && gen.getSignature().equals(signature))
  1043. return gen;
  1044. }
  1045. if (!allowMissing) {
  1046. throw new BCException("Class " + this.getName() + " does not have a method "
  1047. + name + " with signature " + signature);
  1048. }
  1049. return null;
  1050. }
  1051. public void forcePublic() {
  1052. myGen.setAccessFlags(Utility.makePublic(myGen.getAccessFlags()));
  1053. }
  1054. public boolean hasAnnotation(UnresolvedType t) {
  1055. // annotations on the real thing
  1056. AnnotationGen agens[] = myGen.getAnnotations();
  1057. if (agens==null) return false;
  1058. for (int i = 0; i < agens.length; i++) {
  1059. AnnotationGen gen = agens[i];
  1060. if (t.equals(UnresolvedType.forSignature(gen.getTypeSignature()))) return true;
  1061. }
  1062. // annotations added during this weave
  1063. return false;
  1064. }
  1065. public void addAnnotation(Annotation a) {
  1066. if (!hasAnnotation(UnresolvedType.forSignature(a.getTypeSignature()))) {
  1067. annotations.add(new AnnotationGen(a,getConstantPoolGen(),true));
  1068. }
  1069. }
  1070. // this test is like asking:
  1071. // if (UnresolvedType.SERIALIZABLE.resolve(getType().getWorld()).isAssignableFrom(getType())) {
  1072. // only we don't do that because this forces us to find all the supertypes of the type,
  1073. // and if one of them is missing we fail, and it's not worth failing just to put out
  1074. // a warning message!
  1075. private boolean implementsSerializable(ResolvedType aType) {
  1076. ResolvedType[] interfaces = aType.getDeclaredInterfaces();
  1077. for (int i = 0; i < interfaces.length; i++) {
  1078. if (interfaces[i].getSignature().equals(UnresolvedType.SERIALIZABLE.getSignature())) {
  1079. return true;
  1080. } else {
  1081. if (interfaces[i].isMissing()) continue;
  1082. ResolvedType superInterface = interfaces[i].getSuperclass();
  1083. if (superInterface != null && !superInterface.isMissing()) {
  1084. if (implementsSerializable(superInterface)) return true;
  1085. }
  1086. }
  1087. }
  1088. ResolvedType superType = aType.getSuperclass();
  1089. if (superType != null && !superType.isMissing()) {
  1090. return implementsSerializable(superType);
  1091. }
  1092. return false;
  1093. }
  1094. }