Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

CtClassType.java 49KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later.
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist;
  16. import java.lang.ref.WeakReference;
  17. import java.io.BufferedInputStream;
  18. import java.io.ByteArrayOutputStream;
  19. import java.io.ByteArrayInputStream;
  20. import java.io.DataInputStream;
  21. import java.io.DataOutputStream;
  22. import java.io.IOException;
  23. import java.io.InputStream;
  24. import java.net.URL;
  25. import java.util.ArrayList;
  26. import java.util.Enumeration;
  27. import java.util.HashMap;
  28. import java.util.Hashtable;
  29. import java.util.List;
  30. import java.util.Set;
  31. import javassist.bytecode.AccessFlag;
  32. import javassist.bytecode.AttributeInfo;
  33. import javassist.bytecode.AnnotationsAttribute;
  34. import javassist.bytecode.BadBytecode;
  35. import javassist.bytecode.Bytecode;
  36. import javassist.bytecode.ClassFile;
  37. import javassist.bytecode.CodeAttribute;
  38. import javassist.bytecode.ConstantAttribute;
  39. import javassist.bytecode.CodeIterator;
  40. import javassist.bytecode.ConstPool;
  41. import javassist.bytecode.Descriptor;
  42. import javassist.bytecode.EnclosingMethodAttribute;
  43. import javassist.bytecode.FieldInfo;
  44. import javassist.bytecode.InnerClassesAttribute;
  45. import javassist.bytecode.MethodInfo;
  46. import javassist.bytecode.ParameterAnnotationsAttribute;
  47. import javassist.bytecode.annotation.Annotation;
  48. import javassist.compiler.AccessorMaker;
  49. import javassist.compiler.CompileError;
  50. import javassist.compiler.Javac;
  51. import javassist.expr.ExprEditor;
  52. /**
  53. * Class types.
  54. */
  55. class CtClassType extends CtClass {
  56. ClassPool classPool;
  57. boolean wasChanged;
  58. private boolean wasFrozen;
  59. boolean wasPruned;
  60. boolean memberRemoved;
  61. ClassFile classfile;
  62. byte[] rawClassfile; // backup storage
  63. private WeakReference memberCache;
  64. private AccessorMaker accessors;
  65. private FieldInitLink fieldInitializers;
  66. private Hashtable hiddenMethods; // must be synchronous
  67. private int uniqueNumberSeed;
  68. private boolean doPruning = ClassPool.doPruning;
  69. int getCounter;
  70. private static int readCounter = 0;
  71. private static final int READ_THRESHOLD = 100; // see getClassFile2()
  72. private static final int GET_THRESHOLD = 2; // see releaseClassFiles()
  73. CtClassType(String name, ClassPool cp) {
  74. super(name);
  75. classPool = cp;
  76. wasChanged = wasFrozen = wasPruned = memberRemoved = false;
  77. classfile = null;
  78. rawClassfile = null;
  79. memberCache = null;
  80. accessors = null;
  81. fieldInitializers = null;
  82. hiddenMethods = null;
  83. uniqueNumberSeed = 0;
  84. getCounter = 0;
  85. }
  86. CtClassType(InputStream ins, ClassPool cp) throws IOException {
  87. this((String)null, cp);
  88. classfile = new ClassFile(new DataInputStream(ins));
  89. qualifiedName = classfile.getName();
  90. }
  91. protected void extendToString(StringBuffer buffer) {
  92. if (wasChanged)
  93. buffer.append("changed ");
  94. if (wasFrozen)
  95. buffer.append("frozen ");
  96. if (wasPruned)
  97. buffer.append("pruned ");
  98. buffer.append(Modifier.toString(getModifiers()));
  99. buffer.append(" class ");
  100. buffer.append(getName());
  101. try {
  102. CtClass ext = getSuperclass();
  103. if (ext != null) {
  104. String name = ext.getName();
  105. if (!name.equals("java.lang.Object"))
  106. buffer.append(" extends " + ext.getName());
  107. }
  108. }
  109. catch (NotFoundException e) {
  110. buffer.append(" extends ??");
  111. }
  112. try {
  113. CtClass[] intf = getInterfaces();
  114. if (intf.length > 0)
  115. buffer.append(" implements ");
  116. for (int i = 0; i < intf.length; ++i) {
  117. buffer.append(intf[i].getName());
  118. buffer.append(", ");
  119. }
  120. }
  121. catch (NotFoundException e) {
  122. buffer.append(" extends ??");
  123. }
  124. CtMember.Cache memCache = getMembers();
  125. exToString(buffer, " fields=",
  126. memCache.fieldHead(), memCache.lastField());
  127. exToString(buffer, " constructors=",
  128. memCache.consHead(), memCache.lastCons());
  129. exToString(buffer, " methods=",
  130. memCache.methodHead(), memCache.lastMethod());
  131. }
  132. private void exToString(StringBuffer buffer, String msg,
  133. CtMember head, CtMember tail) {
  134. buffer.append(msg);
  135. while (head != tail) {
  136. head = head.next();
  137. buffer.append(head);
  138. buffer.append(", ");
  139. }
  140. }
  141. public AccessorMaker getAccessorMaker() {
  142. if (accessors == null)
  143. accessors = new AccessorMaker(this);
  144. return accessors;
  145. }
  146. public ClassFile getClassFile2() {
  147. ClassFile cfile = classfile;
  148. if (cfile != null)
  149. return cfile;
  150. if (readCounter++ > READ_THRESHOLD) {
  151. getCounter += 2;
  152. releaseClassFiles();
  153. readCounter = 0;
  154. }
  155. if (rawClassfile != null) {
  156. try {
  157. classfile = new ClassFile(new DataInputStream(
  158. new ByteArrayInputStream(rawClassfile)));
  159. rawClassfile = null;
  160. getCounter = GET_THRESHOLD;
  161. return classfile;
  162. }
  163. catch (IOException e) {
  164. throw new RuntimeException(e.toString(), e);
  165. }
  166. }
  167. InputStream fin = null;
  168. try {
  169. fin = classPool.openClassfile(getName());
  170. if (fin == null)
  171. throw new NotFoundException(getName());
  172. fin = new BufferedInputStream(fin);
  173. ClassFile cf = new ClassFile(new DataInputStream(fin));
  174. if (!cf.getName().equals(qualifiedName))
  175. throw new RuntimeException("cannot find " + qualifiedName + ": "
  176. + cf.getName() + " found in "
  177. + qualifiedName.replace('.', '/') + ".class");
  178. classfile = cf;
  179. return cf;
  180. }
  181. catch (NotFoundException e) {
  182. throw new RuntimeException(e.toString(), e);
  183. }
  184. catch (IOException e) {
  185. throw new RuntimeException(e.toString(), e);
  186. }
  187. finally {
  188. if (fin != null)
  189. try {
  190. fin.close();
  191. }
  192. catch (IOException e) {}
  193. }
  194. }
  195. /**
  196. * Converts a ClassFile object into a byte array
  197. * for saving memory space.
  198. */
  199. public synchronized void saveClassFile() {
  200. /* getMembers() and releaseClassFile() are also synchronized.
  201. */
  202. if (classfile == null || hasMemberCache() != null)
  203. return;
  204. ByteArrayOutputStream barray = new ByteArrayOutputStream();
  205. DataOutputStream out = new DataOutputStream(barray);
  206. try {
  207. classfile.write(out);
  208. barray.close();
  209. rawClassfile = barray.toByteArray();
  210. classfile = null;
  211. }
  212. catch (IOException e) {}
  213. }
  214. public synchronized void releaseClassFile() {
  215. if (!isModified())
  216. classfile = null;
  217. }
  218. /* Inherited from CtClass. Called by get() in ClassPool.
  219. *
  220. * @see javassist.CtClass#incGetCounter()
  221. * @see #toBytecode(DataOutputStream)
  222. */
  223. void incGetCounter() { ++getCounter; }
  224. /**
  225. * Releases the class files
  226. * of the CtClasses that have not been recently used
  227. * if they are unmodified.
  228. */
  229. private void releaseClassFiles() {
  230. Enumeration e = classPool.classes.elements();
  231. while (e.hasMoreElements()) {
  232. Object obj = e.nextElement();
  233. if (obj instanceof CtClassType) {
  234. CtClassType cct = (CtClassType)obj;
  235. if (cct.getCounter < GET_THRESHOLD)
  236. if (!cct.isModified() && ClassPool.releaseUnmodifiedClassFile)
  237. cct.releaseClassFile();
  238. else if (cct.isFrozen() && !cct.wasPruned)
  239. cct.saveClassFile();
  240. cct.getCounter = 0;
  241. }
  242. }
  243. }
  244. public ClassPool getClassPool() { return classPool; }
  245. void setClassPool(ClassPool cp) { classPool = cp; }
  246. public URL getURL() throws NotFoundException {
  247. URL url = classPool.find(getName());
  248. if (url == null)
  249. throw new NotFoundException(getName());
  250. else
  251. return url;
  252. }
  253. public boolean isModified() { return wasChanged; }
  254. public boolean isFrozen() { return wasFrozen; }
  255. void freeze() { wasFrozen = true; }
  256. void checkModify() throws RuntimeException {
  257. if (isFrozen()) {
  258. String msg = getName() + " class is frozen";
  259. if (wasPruned)
  260. msg += " and pruned";
  261. throw new RuntimeException(msg);
  262. }
  263. wasChanged = true;
  264. }
  265. public void defrost() {
  266. checkPruned("defrost");
  267. wasFrozen = false;
  268. }
  269. public boolean subtypeOf(CtClass clazz) throws NotFoundException {
  270. int i;
  271. String cname = clazz.getName();
  272. if (this == clazz || getName().equals(cname))
  273. return true;
  274. ClassFile file = getClassFile2();
  275. String supername = file.getSuperclass();
  276. if (supername != null && supername.equals(cname))
  277. return true;
  278. String[] ifs = file.getInterfaces();
  279. int num = ifs.length;
  280. for (i = 0; i < num; ++i)
  281. if (ifs[i].equals(cname))
  282. return true;
  283. if (supername != null && classPool.get(supername).subtypeOf(clazz))
  284. return true;
  285. for (i = 0; i < num; ++i)
  286. if (classPool.get(ifs[i]).subtypeOf(clazz))
  287. return true;
  288. return false;
  289. }
  290. public void setName(String name) throws RuntimeException {
  291. String oldname = getName();
  292. if (name.equals(oldname))
  293. return;
  294. // check this in advance although classNameChanged() below does.
  295. classPool.checkNotFrozen(name);
  296. ClassFile cf = getClassFile2();
  297. super.setName(name);
  298. cf.setName(name);
  299. nameReplaced();
  300. classPool.classNameChanged(oldname, this);
  301. }
  302. public void replaceClassName(ClassMap classnames)
  303. throws RuntimeException
  304. {
  305. String oldClassName = getName();
  306. String newClassName
  307. = (String)classnames.get(Descriptor.toJvmName(oldClassName));
  308. if (newClassName != null) {
  309. newClassName = Descriptor.toJavaName(newClassName);
  310. // check this in advance although classNameChanged() below does.
  311. classPool.checkNotFrozen(newClassName);
  312. }
  313. super.replaceClassName(classnames);
  314. ClassFile cf = getClassFile2();
  315. cf.renameClass(classnames);
  316. nameReplaced();
  317. if (newClassName != null) {
  318. super.setName(newClassName);
  319. classPool.classNameChanged(oldClassName, this);
  320. }
  321. }
  322. public void replaceClassName(String oldname, String newname)
  323. throws RuntimeException
  324. {
  325. String thisname = getName();
  326. if (thisname.equals(oldname))
  327. setName(newname);
  328. else {
  329. super.replaceClassName(oldname, newname);
  330. getClassFile2().renameClass(oldname, newname);
  331. nameReplaced();
  332. }
  333. }
  334. public boolean isInterface() {
  335. return Modifier.isInterface(getModifiers());
  336. }
  337. public boolean isAnnotation() {
  338. return Modifier.isAnnotation(getModifiers());
  339. }
  340. public boolean isEnum() {
  341. return Modifier.isEnum(getModifiers());
  342. }
  343. public int getModifiers() {
  344. ClassFile cf = getClassFile2();
  345. int acc = cf.getAccessFlags();
  346. acc = AccessFlag.clear(acc, AccessFlag.SUPER);
  347. int inner = cf.getInnerAccessFlags();
  348. if (inner != -1 && (inner & AccessFlag.STATIC) != 0)
  349. acc |= AccessFlag.STATIC;
  350. return AccessFlag.toModifier(acc);
  351. }
  352. public CtClass[] getNestedClasses() throws NotFoundException {
  353. ClassFile cf = getClassFile2();
  354. InnerClassesAttribute ica
  355. = (InnerClassesAttribute)cf.getAttribute(InnerClassesAttribute.tag);
  356. if (ica == null)
  357. return new CtClass[0];
  358. String thisName = cf.getName();
  359. int n = ica.tableLength();
  360. ArrayList list = new ArrayList(n);
  361. for (int i = 0; i < n; i++) {
  362. String outer = ica.outerClass(i);
  363. /*
  364. * If a nested class is local or anonymous,
  365. * the outer_class_info_index is 0.
  366. */
  367. if (outer == null || outer.equals(thisName)) {
  368. String inner = ica.innerClass(i);
  369. if (inner != null)
  370. list.add(classPool.get(inner));
  371. }
  372. }
  373. return (CtClass[])list.toArray(new CtClass[list.size()]);
  374. }
  375. public void setModifiers(int mod) {
  376. ClassFile cf = getClassFile2();
  377. if (Modifier.isStatic(mod)) {
  378. int flags = cf.getInnerAccessFlags();
  379. if (flags != -1 && (flags & AccessFlag.STATIC) != 0)
  380. mod = mod & ~Modifier.STATIC;
  381. else
  382. throw new RuntimeException("cannot change " + getName() + " into a static class");
  383. }
  384. checkModify();
  385. cf.setAccessFlags(AccessFlag.of(mod));
  386. }
  387. public Object[] getAnnotations() throws ClassNotFoundException {
  388. return getAnnotations(false);
  389. }
  390. public Object[] getAvailableAnnotations(){
  391. try {
  392. return getAnnotations(true);
  393. }
  394. catch (ClassNotFoundException e) {
  395. throw new RuntimeException("Unexpected exception ", e);
  396. }
  397. }
  398. private Object[] getAnnotations(boolean ignoreNotFound)
  399. throws ClassNotFoundException
  400. {
  401. ClassFile cf = getClassFile2();
  402. AnnotationsAttribute ainfo = (AnnotationsAttribute)
  403. cf.getAttribute(AnnotationsAttribute.invisibleTag);
  404. AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
  405. cf.getAttribute(AnnotationsAttribute.visibleTag);
  406. return toAnnotationType(ignoreNotFound, getClassPool(), ainfo, ainfo2);
  407. }
  408. static Object[] toAnnotationType(boolean ignoreNotFound, ClassPool cp,
  409. AnnotationsAttribute a1, AnnotationsAttribute a2)
  410. throws ClassNotFoundException
  411. {
  412. Annotation[] anno1, anno2;
  413. int size1, size2;
  414. if (a1 == null) {
  415. anno1 = null;
  416. size1 = 0;
  417. }
  418. else {
  419. anno1 = a1.getAnnotations();
  420. size1 = anno1.length;
  421. }
  422. if (a2 == null) {
  423. anno2 = null;
  424. size2 = 0;
  425. }
  426. else {
  427. anno2 = a2.getAnnotations();
  428. size2 = anno2.length;
  429. }
  430. if (!ignoreNotFound){
  431. Object[] result = new Object[size1 + size2];
  432. for (int i = 0; i < size1; i++)
  433. result[i] = toAnnoType(anno1[i], cp);
  434. for (int j = 0; j < size2; j++)
  435. result[j + size1] = toAnnoType(anno2[j], cp);
  436. return result;
  437. }
  438. else{
  439. ArrayList annotations = new ArrayList();
  440. for (int i = 0 ; i < size1 ; i++){
  441. try{
  442. annotations.add(toAnnoType(anno1[i], cp));
  443. }
  444. catch(ClassNotFoundException e){}
  445. }
  446. for (int j = 0; j < size2; j++) {
  447. try{
  448. annotations.add(toAnnoType(anno2[j], cp));
  449. }
  450. catch(ClassNotFoundException e){}
  451. }
  452. return annotations.toArray();
  453. }
  454. }
  455. static Object[][] toAnnotationType(boolean ignoreNotFound, ClassPool cp,
  456. ParameterAnnotationsAttribute a1,
  457. ParameterAnnotationsAttribute a2,
  458. MethodInfo minfo)
  459. throws ClassNotFoundException
  460. {
  461. int numParameters = 0;
  462. if (a1 != null)
  463. numParameters = a1.numParameters();
  464. else if (a2 != null)
  465. numParameters = a2.numParameters();
  466. else
  467. numParameters = Descriptor.numOfParameters(minfo.getDescriptor());
  468. Object[][] result = new Object[numParameters][];
  469. for (int i = 0; i < numParameters; i++) {
  470. Annotation[] anno1, anno2;
  471. int size1, size2;
  472. if (a1 == null) {
  473. anno1 = null;
  474. size1 = 0;
  475. }
  476. else {
  477. anno1 = a1.getAnnotations()[i];
  478. size1 = anno1.length;
  479. }
  480. if (a2 == null) {
  481. anno2 = null;
  482. size2 = 0;
  483. }
  484. else {
  485. anno2 = a2.getAnnotations()[i];
  486. size2 = anno2.length;
  487. }
  488. if (!ignoreNotFound){
  489. result[i] = new Object[size1 + size2];
  490. for (int j = 0; j < size1; ++j)
  491. result[i][j] = toAnnoType(anno1[j], cp);
  492. for (int j = 0; j < size2; ++j)
  493. result[i][j + size1] = toAnnoType(anno2[j], cp);
  494. }
  495. else{
  496. ArrayList annotations = new ArrayList();
  497. for (int j = 0 ; j < size1 ; j++){
  498. try{
  499. annotations.add(toAnnoType(anno1[j], cp));
  500. }
  501. catch(ClassNotFoundException e){}
  502. }
  503. for (int j = 0; j < size2; j++){
  504. try{
  505. annotations.add(toAnnoType(anno2[j], cp));
  506. }
  507. catch(ClassNotFoundException e){}
  508. }
  509. result[i] = annotations.toArray();
  510. }
  511. }
  512. return result;
  513. }
  514. private static Object toAnnoType(Annotation anno, ClassPool cp)
  515. throws ClassNotFoundException
  516. {
  517. try {
  518. ClassLoader cl = cp.getClassLoader();
  519. return anno.toAnnotationType(cl, cp);
  520. }
  521. catch (ClassNotFoundException e) {
  522. ClassLoader cl2 = cp.getClass().getClassLoader();
  523. return anno.toAnnotationType(cl2, cp);
  524. }
  525. }
  526. public boolean subclassOf(CtClass superclass) {
  527. if (superclass == null)
  528. return false;
  529. String superName = superclass.getName();
  530. CtClass curr = this;
  531. try {
  532. while (curr != null) {
  533. if (curr.getName().equals(superName))
  534. return true;
  535. curr = curr.getSuperclass();
  536. }
  537. }
  538. catch (Exception ignored) {}
  539. return false;
  540. }
  541. public CtClass getSuperclass() throws NotFoundException {
  542. String supername = getClassFile2().getSuperclass();
  543. if (supername == null)
  544. return null;
  545. else
  546. return classPool.get(supername);
  547. }
  548. public void setSuperclass(CtClass clazz) throws CannotCompileException {
  549. checkModify();
  550. if (isInterface())
  551. addInterface(clazz);
  552. else
  553. getClassFile2().setSuperclass(clazz.getName());
  554. }
  555. public CtClass[] getInterfaces() throws NotFoundException {
  556. String[] ifs = getClassFile2().getInterfaces();
  557. int num = ifs.length;
  558. CtClass[] ifc = new CtClass[num];
  559. for (int i = 0; i < num; ++i)
  560. ifc[i] = classPool.get(ifs[i]);
  561. return ifc;
  562. }
  563. public void setInterfaces(CtClass[] list) {
  564. checkModify();
  565. String[] ifs;
  566. if (list == null)
  567. ifs = new String[0];
  568. else {
  569. int num = list.length;
  570. ifs = new String[num];
  571. for (int i = 0; i < num; ++i)
  572. ifs[i] = list[i].getName();
  573. }
  574. getClassFile2().setInterfaces(ifs);
  575. }
  576. public void addInterface(CtClass anInterface) {
  577. checkModify();
  578. if (anInterface != null)
  579. getClassFile2().addInterface(anInterface.getName());
  580. }
  581. public CtClass getDeclaringClass() throws NotFoundException {
  582. ClassFile cf = getClassFile2();
  583. InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute(
  584. InnerClassesAttribute.tag);
  585. if (ica == null)
  586. return null;
  587. String name = getName();
  588. int n = ica.tableLength();
  589. for (int i = 0; i < n; ++i)
  590. if (name.equals(ica.innerClass(i))) {
  591. String outName = ica.outerClass(i);
  592. if (outName != null)
  593. return classPool.get(outName);
  594. else {
  595. // maybe anonymous or local class.
  596. EnclosingMethodAttribute ema
  597. = (EnclosingMethodAttribute)cf.getAttribute(
  598. EnclosingMethodAttribute.tag);
  599. if (ema != null)
  600. return classPool.get(ema.className());
  601. }
  602. }
  603. return null;
  604. }
  605. public CtMethod getEnclosingMethod() throws NotFoundException {
  606. ClassFile cf = getClassFile2();
  607. EnclosingMethodAttribute ema
  608. = (EnclosingMethodAttribute)cf.getAttribute(
  609. EnclosingMethodAttribute.tag);
  610. if (ema != null) {
  611. CtClass enc = classPool.get(ema.className());
  612. return enc.getMethod(ema.methodName(), ema.methodDescriptor());
  613. }
  614. return null;
  615. }
  616. public CtClass makeNestedClass(String name, boolean isStatic) {
  617. if (!isStatic)
  618. throw new RuntimeException(
  619. "sorry, only nested static class is supported");
  620. checkModify();
  621. CtClass c = classPool.makeNestedClass(getName() + "$" + name);
  622. ClassFile cf = getClassFile2();
  623. ClassFile cf2 = c.getClassFile2();
  624. InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute(
  625. InnerClassesAttribute.tag);
  626. if (ica == null) {
  627. ica = new InnerClassesAttribute(cf.getConstPool());
  628. cf.addAttribute(ica);
  629. }
  630. ica.append(c.getName(), this.getName(), name,
  631. (cf2.getAccessFlags() & ~AccessFlag.SUPER) | AccessFlag.STATIC);
  632. cf2.addAttribute(ica.copy(cf2.getConstPool(), null));
  633. return c;
  634. }
  635. /* flush cached names.
  636. */
  637. private void nameReplaced() {
  638. CtMember.Cache cache = hasMemberCache();
  639. if (cache != null) {
  640. CtMember mth = cache.methodHead();
  641. CtMember tail = cache.lastMethod();
  642. while (mth != tail) {
  643. mth = mth.next();
  644. mth.nameReplaced();
  645. }
  646. }
  647. }
  648. /**
  649. * Returns null if members are not cached.
  650. */
  651. protected CtMember.Cache hasMemberCache() {
  652. if (memberCache != null)
  653. return (CtMember.Cache)memberCache.get();
  654. else
  655. return null;
  656. }
  657. protected synchronized CtMember.Cache getMembers() {
  658. CtMember.Cache cache = null;
  659. if (memberCache == null
  660. || (cache = (CtMember.Cache)memberCache.get()) == null) {
  661. cache = new CtMember.Cache(this);
  662. makeFieldCache(cache);
  663. makeBehaviorCache(cache);
  664. memberCache = new WeakReference(cache);
  665. }
  666. return cache;
  667. }
  668. private void makeFieldCache(CtMember.Cache cache) {
  669. List list = getClassFile2().getFields();
  670. int n = list.size();
  671. for (int i = 0; i < n; ++i) {
  672. FieldInfo finfo = (FieldInfo)list.get(i);
  673. CtField newField = new CtField(finfo, this);
  674. cache.addField(newField);
  675. }
  676. }
  677. private void makeBehaviorCache(CtMember.Cache cache) {
  678. List list = getClassFile2().getMethods();
  679. int n = list.size();
  680. for (int i = 0; i < n; ++i) {
  681. MethodInfo minfo = (MethodInfo)list.get(i);
  682. if (minfo.isMethod()) {
  683. CtMethod newMethod = new CtMethod(minfo, this);
  684. cache.addMethod(newMethod);
  685. }
  686. else {
  687. CtConstructor newCons = new CtConstructor(minfo, this);
  688. cache.addConstructor(newCons);
  689. }
  690. }
  691. }
  692. public CtField[] getFields() {
  693. ArrayList alist = new ArrayList();
  694. getFields(alist, this);
  695. return (CtField[])alist.toArray(new CtField[alist.size()]);
  696. }
  697. private static void getFields(ArrayList alist, CtClass cc) {
  698. int i, num;
  699. if (cc == null)
  700. return;
  701. try {
  702. getFields(alist, cc.getSuperclass());
  703. }
  704. catch (NotFoundException e) {}
  705. try {
  706. CtClass[] ifs = cc.getInterfaces();
  707. num = ifs.length;
  708. for (i = 0; i < num; ++i)
  709. getFields(alist, ifs[i]);
  710. }
  711. catch (NotFoundException e) {}
  712. CtMember.Cache memCache = ((CtClassType)cc).getMembers();
  713. CtMember field = memCache.fieldHead();
  714. CtMember tail = memCache.lastField();
  715. while (field != tail) {
  716. field = field.next();
  717. if (!Modifier.isPrivate(field.getModifiers()))
  718. alist.add(field);
  719. }
  720. }
  721. public CtField getField(String name) throws NotFoundException {
  722. CtField f = getField2(name);
  723. if (f == null)
  724. throw new NotFoundException("field: " + name + " in " + getName());
  725. else
  726. return f;
  727. }
  728. CtField getField2(String name) {
  729. CtField df = getDeclaredField2(name);
  730. if (df != null)
  731. return df;
  732. try {
  733. CtClass[] ifs = getInterfaces();
  734. int num = ifs.length;
  735. for (int i = 0; i < num; ++i) {
  736. CtField f = ifs[i].getField2(name);
  737. if (f != null)
  738. return f;
  739. }
  740. CtClass s = getSuperclass();
  741. if (s != null)
  742. return s.getField2(name);
  743. }
  744. catch (NotFoundException e) {}
  745. return null;
  746. }
  747. public CtField[] getDeclaredFields() {
  748. CtMember.Cache memCache = getMembers();
  749. CtMember field = memCache.fieldHead();
  750. CtMember tail = memCache.lastField();
  751. int num = CtMember.Cache.count(field, tail);
  752. CtField[] cfs = new CtField[num];
  753. int i = 0;
  754. while (field != tail) {
  755. field = field.next();
  756. cfs[i++] = (CtField)field;
  757. }
  758. return cfs;
  759. }
  760. public CtField getDeclaredField(String name) throws NotFoundException {
  761. CtField f = getDeclaredField2(name);
  762. if (f == null)
  763. throw new NotFoundException("field: " + name + " in " + getName());
  764. else
  765. return f;
  766. }
  767. private CtField getDeclaredField2(String name) {
  768. CtMember.Cache memCache = getMembers();
  769. CtMember field = memCache.fieldHead();
  770. CtMember tail = memCache.lastField();
  771. while (field != tail) {
  772. field = field.next();
  773. if (field.getName().equals(name))
  774. return (CtField)field;
  775. }
  776. return null;
  777. }
  778. public CtBehavior[] getDeclaredBehaviors() {
  779. CtMember.Cache memCache = getMembers();
  780. CtMember cons = memCache.consHead();
  781. CtMember consTail = memCache.lastCons();
  782. int cnum = CtMember.Cache.count(cons, consTail);
  783. CtMember mth = memCache.methodHead();
  784. CtMember mthTail = memCache.lastMethod();
  785. int mnum = CtMember.Cache.count(mth, mthTail);
  786. CtBehavior[] cb = new CtBehavior[cnum + mnum];
  787. int i = 0;
  788. while (cons != consTail) {
  789. cons = cons.next();
  790. cb[i++] = (CtBehavior)cons;
  791. }
  792. while (mth != mthTail) {
  793. mth = mth.next();
  794. cb[i++] = (CtBehavior)mth;
  795. }
  796. return cb;
  797. }
  798. public CtConstructor[] getConstructors() {
  799. CtMember.Cache memCache = getMembers();
  800. CtMember cons = memCache.consHead();
  801. CtMember consTail = memCache.lastCons();
  802. int n = 0;
  803. CtMember mem = cons;
  804. while (mem != consTail) {
  805. mem = mem.next();
  806. if (isPubCons((CtConstructor)mem))
  807. n++;
  808. }
  809. CtConstructor[] result = new CtConstructor[n];
  810. int i = 0;
  811. mem = cons;
  812. while (mem != consTail) {
  813. mem = mem.next();
  814. CtConstructor cc = (CtConstructor)mem;
  815. if (isPubCons(cc))
  816. result[i++] = cc;
  817. }
  818. return result;
  819. }
  820. private static boolean isPubCons(CtConstructor cons) {
  821. return !Modifier.isPrivate(cons.getModifiers())
  822. && cons.isConstructor();
  823. }
  824. public CtConstructor getConstructor(String desc)
  825. throws NotFoundException
  826. {
  827. CtMember.Cache memCache = getMembers();
  828. CtMember cons = memCache.consHead();
  829. CtMember consTail = memCache.lastCons();
  830. while (cons != consTail) {
  831. cons = cons.next();
  832. CtConstructor cc = (CtConstructor)cons;
  833. if (cc.getMethodInfo2().getDescriptor().equals(desc)
  834. && cc.isConstructor())
  835. return cc;
  836. }
  837. return super.getConstructor(desc);
  838. }
  839. public CtConstructor[] getDeclaredConstructors() {
  840. CtMember.Cache memCache = getMembers();
  841. CtMember cons = memCache.consHead();
  842. CtMember consTail = memCache.lastCons();
  843. int n = 0;
  844. CtMember mem = cons;
  845. while (mem != consTail) {
  846. mem = mem.next();
  847. CtConstructor cc = (CtConstructor)mem;
  848. if (cc.isConstructor())
  849. n++;
  850. }
  851. CtConstructor[] result = new CtConstructor[n];
  852. int i = 0;
  853. mem = cons;
  854. while (mem != consTail) {
  855. mem = mem.next();
  856. CtConstructor cc = (CtConstructor)mem;
  857. if (cc.isConstructor())
  858. result[i++] = cc;
  859. }
  860. return result;
  861. }
  862. public CtConstructor getClassInitializer() {
  863. CtMember.Cache memCache = getMembers();
  864. CtMember cons = memCache.consHead();
  865. CtMember consTail = memCache.lastCons();
  866. while (cons != consTail) {
  867. cons = cons.next();
  868. CtConstructor cc = (CtConstructor)cons;
  869. if (cc.isClassInitializer())
  870. return cc;
  871. }
  872. return null;
  873. }
  874. public CtMethod[] getMethods() {
  875. HashMap h = new HashMap();
  876. getMethods0(h, this);
  877. return (CtMethod[])h.values().toArray(new CtMethod[h.size()]);
  878. }
  879. private static void getMethods0(HashMap h, CtClass cc) {
  880. try {
  881. CtClass[] ifs = cc.getInterfaces();
  882. int size = ifs.length;
  883. for (int i = 0; i < size; ++i)
  884. getMethods0(h, ifs[i]);
  885. }
  886. catch (NotFoundException e) {}
  887. try {
  888. CtClass s = cc.getSuperclass();
  889. if (s != null)
  890. getMethods0(h, s);
  891. }
  892. catch (NotFoundException e) {}
  893. if (cc instanceof CtClassType) {
  894. CtMember.Cache memCache = ((CtClassType)cc).getMembers();
  895. CtMember mth = memCache.methodHead();
  896. CtMember mthTail = memCache.lastMethod();
  897. while (mth != mthTail) {
  898. mth = mth.next();
  899. if (!Modifier.isPrivate(mth.getModifiers()))
  900. h.put(((CtMethod)mth).getStringRep(), mth);
  901. }
  902. }
  903. }
  904. public CtMethod getMethod(String name, String desc)
  905. throws NotFoundException
  906. {
  907. CtMethod m = getMethod0(this, name, desc);
  908. if (m != null)
  909. return m;
  910. else
  911. throw new NotFoundException(name + "(..) is not found in "
  912. + getName());
  913. }
  914. private static CtMethod getMethod0(CtClass cc,
  915. String name, String desc) {
  916. if (cc instanceof CtClassType) {
  917. CtMember.Cache memCache = ((CtClassType)cc).getMembers();
  918. CtMember mth = memCache.methodHead();
  919. CtMember mthTail = memCache.lastMethod();
  920. while (mth != mthTail) {
  921. mth = mth.next();
  922. if (mth.getName().equals(name)
  923. && ((CtMethod)mth).getMethodInfo2().getDescriptor().equals(desc))
  924. return (CtMethod)mth;
  925. }
  926. }
  927. try {
  928. CtClass s = cc.getSuperclass();
  929. if (s != null) {
  930. CtMethod m = getMethod0(s, name, desc);
  931. if (m != null)
  932. return m;
  933. }
  934. }
  935. catch (NotFoundException e) {}
  936. try {
  937. CtClass[] ifs = cc.getInterfaces();
  938. int size = ifs.length;
  939. for (int i = 0; i < size; ++i) {
  940. CtMethod m = getMethod0(ifs[i], name, desc);
  941. if (m != null)
  942. return m;
  943. }
  944. }
  945. catch (NotFoundException e) {}
  946. return null;
  947. }
  948. public CtMethod[] getDeclaredMethods() {
  949. CtMember.Cache memCache = getMembers();
  950. CtMember mth = memCache.methodHead();
  951. CtMember mthTail = memCache.lastMethod();
  952. int num = CtMember.Cache.count(mth, mthTail);
  953. CtMethod[] cms = new CtMethod[num];
  954. int i = 0;
  955. while (mth != mthTail) {
  956. mth = mth.next();
  957. cms[i++] = (CtMethod)mth;
  958. }
  959. return cms;
  960. }
  961. public CtMethod getDeclaredMethod(String name) throws NotFoundException {
  962. CtMember.Cache memCache = getMembers();
  963. CtMember mth = memCache.methodHead();
  964. CtMember mthTail = memCache.lastMethod();
  965. while (mth != mthTail) {
  966. mth = mth.next();
  967. if (mth.getName().equals(name))
  968. return (CtMethod)mth;
  969. }
  970. throw new NotFoundException(name + "(..) is not found in "
  971. + getName());
  972. }
  973. public CtMethod getDeclaredMethod(String name, CtClass[] params)
  974. throws NotFoundException
  975. {
  976. String desc = Descriptor.ofParameters(params);
  977. CtMember.Cache memCache = getMembers();
  978. CtMember mth = memCache.methodHead();
  979. CtMember mthTail = memCache.lastMethod();
  980. while (mth != mthTail) {
  981. mth = mth.next();
  982. if (mth.getName().equals(name)
  983. && ((CtMethod)mth).getMethodInfo2().getDescriptor().startsWith(desc))
  984. return (CtMethod)mth;
  985. }
  986. throw new NotFoundException(name + "(..) is not found in "
  987. + getName());
  988. }
  989. public void addField(CtField f, String init)
  990. throws CannotCompileException
  991. {
  992. addField(f, CtField.Initializer.byExpr(init));
  993. }
  994. public void addField(CtField f, CtField.Initializer init)
  995. throws CannotCompileException
  996. {
  997. checkModify();
  998. if (f.getDeclaringClass() != this)
  999. throw new CannotCompileException("cannot add");
  1000. if (init == null)
  1001. init = f.getInit();
  1002. if (init != null) {
  1003. int mod = f.getModifiers();
  1004. if (Modifier.isStatic(mod) && Modifier.isFinal(mod))
  1005. try {
  1006. ConstPool cp = getClassFile2().getConstPool();
  1007. int index = init.getConstantValue(cp, f.getType());
  1008. if (index != 0) {
  1009. f.getFieldInfo2().addAttribute(new ConstantAttribute(cp, index));
  1010. init = null;
  1011. }
  1012. }
  1013. catch (NotFoundException e) {}
  1014. }
  1015. getMembers().addField(f);
  1016. getClassFile2().addField(f.getFieldInfo2());
  1017. if (init != null) {
  1018. FieldInitLink fil = new FieldInitLink(f, init);
  1019. FieldInitLink link = fieldInitializers;
  1020. if (link == null)
  1021. fieldInitializers = fil;
  1022. else {
  1023. while (link.next != null)
  1024. link = link.next;
  1025. link.next = fil;
  1026. }
  1027. }
  1028. }
  1029. public void removeField(CtField f) throws NotFoundException {
  1030. checkModify();
  1031. FieldInfo fi = f.getFieldInfo2();
  1032. ClassFile cf = getClassFile2();
  1033. if (cf.getFields().remove(fi)) {
  1034. getMembers().remove(f);
  1035. memberRemoved = true;
  1036. }
  1037. else
  1038. throw new NotFoundException(f.toString());
  1039. }
  1040. public CtConstructor makeClassInitializer()
  1041. throws CannotCompileException
  1042. {
  1043. CtConstructor clinit = getClassInitializer();
  1044. if (clinit != null)
  1045. return clinit;
  1046. checkModify();
  1047. ClassFile cf = getClassFile2();
  1048. Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
  1049. modifyClassConstructor(cf, code, 0, 0);
  1050. return getClassInitializer();
  1051. }
  1052. public void addConstructor(CtConstructor c)
  1053. throws CannotCompileException
  1054. {
  1055. checkModify();
  1056. if (c.getDeclaringClass() != this)
  1057. throw new CannotCompileException("cannot add");
  1058. getMembers().addConstructor(c);
  1059. getClassFile2().addMethod(c.getMethodInfo2());
  1060. }
  1061. public void removeConstructor(CtConstructor m) throws NotFoundException {
  1062. checkModify();
  1063. MethodInfo mi = m.getMethodInfo2();
  1064. ClassFile cf = getClassFile2();
  1065. if (cf.getMethods().remove(mi)) {
  1066. getMembers().remove(m);
  1067. memberRemoved = true;
  1068. }
  1069. else
  1070. throw new NotFoundException(m.toString());
  1071. }
  1072. public void addMethod(CtMethod m) throws CannotCompileException {
  1073. checkModify();
  1074. if (m.getDeclaringClass() != this)
  1075. throw new CannotCompileException("cannot add");
  1076. getMembers().addMethod(m);
  1077. getClassFile2().addMethod(m.getMethodInfo2());
  1078. if ((m.getModifiers() & Modifier.ABSTRACT) != 0)
  1079. setModifiers(getModifiers() | Modifier.ABSTRACT);
  1080. }
  1081. public void removeMethod(CtMethod m) throws NotFoundException {
  1082. checkModify();
  1083. MethodInfo mi = m.getMethodInfo2();
  1084. ClassFile cf = getClassFile2();
  1085. if (cf.getMethods().remove(mi)) {
  1086. getMembers().remove(m);
  1087. memberRemoved = true;
  1088. }
  1089. else
  1090. throw new NotFoundException(m.toString());
  1091. }
  1092. public byte[] getAttribute(String name) {
  1093. AttributeInfo ai = getClassFile2().getAttribute(name);
  1094. if (ai == null)
  1095. return null;
  1096. else
  1097. return ai.get();
  1098. }
  1099. public void setAttribute(String name, byte[] data) {
  1100. checkModify();
  1101. ClassFile cf = getClassFile2();
  1102. cf.addAttribute(new AttributeInfo(cf.getConstPool(), name, data));
  1103. }
  1104. public void instrument(CodeConverter converter)
  1105. throws CannotCompileException
  1106. {
  1107. checkModify();
  1108. ClassFile cf = getClassFile2();
  1109. ConstPool cp = cf.getConstPool();
  1110. List list = cf.getMethods();
  1111. int n = list.size();
  1112. for (int i = 0; i < n; ++i) {
  1113. MethodInfo minfo = (MethodInfo)list.get(i);
  1114. converter.doit(this, minfo, cp);
  1115. }
  1116. }
  1117. public void instrument(ExprEditor editor)
  1118. throws CannotCompileException
  1119. {
  1120. checkModify();
  1121. ClassFile cf = getClassFile2();
  1122. List list = cf.getMethods();
  1123. int n = list.size();
  1124. for (int i = 0; i < n; ++i) {
  1125. MethodInfo minfo = (MethodInfo)list.get(i);
  1126. editor.doit(this, minfo);
  1127. }
  1128. }
  1129. /**
  1130. * @see javassist.CtClass#prune()
  1131. * @see javassist.CtClass#stopPruning(boolean)
  1132. */
  1133. public void prune() {
  1134. if (wasPruned)
  1135. return;
  1136. wasPruned = wasFrozen = true;
  1137. getClassFile2().prune();
  1138. }
  1139. public void toBytecode(DataOutputStream out)
  1140. throws CannotCompileException, IOException
  1141. {
  1142. try {
  1143. if (isModified()) {
  1144. checkPruned("toBytecode");
  1145. ClassFile cf = getClassFile2();
  1146. if (memberRemoved) {
  1147. cf.compact();
  1148. memberRemoved = false;
  1149. }
  1150. modifyClassConstructor(cf);
  1151. modifyConstructors(cf);
  1152. cf.write(out);
  1153. out.flush();
  1154. fieldInitializers = null;
  1155. if (doPruning) {
  1156. // to save memory
  1157. cf.prune();
  1158. wasPruned = true;
  1159. }
  1160. }
  1161. else {
  1162. classPool.writeClassfile(getName(), out);
  1163. // to save memory
  1164. // classfile = null;
  1165. }
  1166. getCounter = 0;
  1167. wasFrozen = true;
  1168. }
  1169. catch (NotFoundException e) {
  1170. throw new CannotCompileException(e);
  1171. }
  1172. catch (IOException e) {
  1173. throw new CannotCompileException(e);
  1174. }
  1175. }
  1176. /* See also checkModified()
  1177. */
  1178. private void checkPruned(String method) {
  1179. if (wasPruned)
  1180. throw new RuntimeException(method + "(): " + getName()
  1181. + " was pruned.");
  1182. }
  1183. public boolean stopPruning(boolean stop) {
  1184. boolean prev = !doPruning;
  1185. doPruning = !stop;
  1186. return prev;
  1187. }
  1188. private void modifyClassConstructor(ClassFile cf)
  1189. throws CannotCompileException, NotFoundException
  1190. {
  1191. if (fieldInitializers == null)
  1192. return;
  1193. Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
  1194. Javac jv = new Javac(code, this);
  1195. int stacksize = 0;
  1196. boolean doInit = false;
  1197. for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next) {
  1198. CtField f = fi.field;
  1199. if (Modifier.isStatic(f.getModifiers())) {
  1200. doInit = true;
  1201. int s = fi.init.compileIfStatic(f.getType(), f.getName(),
  1202. code, jv);
  1203. if (stacksize < s)
  1204. stacksize = s;
  1205. }
  1206. }
  1207. if (doInit) // need an initializer for static fileds.
  1208. modifyClassConstructor(cf, code, stacksize, 0);
  1209. }
  1210. private void modifyClassConstructor(ClassFile cf, Bytecode code,
  1211. int stacksize, int localsize)
  1212. throws CannotCompileException
  1213. {
  1214. MethodInfo m = cf.getStaticInitializer();
  1215. if (m == null) {
  1216. code.add(Bytecode.RETURN);
  1217. code.setMaxStack(stacksize);
  1218. code.setMaxLocals(localsize);
  1219. m = new MethodInfo(cf.getConstPool(), "<clinit>", "()V");
  1220. m.setAccessFlags(AccessFlag.STATIC);
  1221. m.setCodeAttribute(code.toCodeAttribute());
  1222. cf.addMethod(m);
  1223. CtMember.Cache cache = hasMemberCache();
  1224. if (cache != null)
  1225. cache.addConstructor(new CtConstructor(m, this));
  1226. }
  1227. else {
  1228. CodeAttribute codeAttr = m.getCodeAttribute();
  1229. if (codeAttr == null)
  1230. throw new CannotCompileException("empty <clinit>");
  1231. try {
  1232. CodeIterator it = codeAttr.iterator();
  1233. int pos = it.insertEx(code.get());
  1234. it.insert(code.getExceptionTable(), pos);
  1235. int maxstack = codeAttr.getMaxStack();
  1236. if (maxstack < stacksize)
  1237. codeAttr.setMaxStack(stacksize);
  1238. int maxlocals = codeAttr.getMaxLocals();
  1239. if (maxlocals < localsize)
  1240. codeAttr.setMaxLocals(localsize);
  1241. }
  1242. catch (BadBytecode e) {
  1243. throw new CannotCompileException(e);
  1244. }
  1245. }
  1246. try {
  1247. m.rebuildStackMapIf6(classPool, cf);
  1248. }
  1249. catch (BadBytecode e) {
  1250. throw new CannotCompileException(e);
  1251. }
  1252. }
  1253. private void modifyConstructors(ClassFile cf)
  1254. throws CannotCompileException, NotFoundException
  1255. {
  1256. if (fieldInitializers == null)
  1257. return;
  1258. ConstPool cp = cf.getConstPool();
  1259. List list = cf.getMethods();
  1260. int n = list.size();
  1261. for (int i = 0; i < n; ++i) {
  1262. MethodInfo minfo = (MethodInfo)list.get(i);
  1263. if (minfo.isConstructor()) {
  1264. CodeAttribute codeAttr = minfo.getCodeAttribute();
  1265. if (codeAttr != null)
  1266. try {
  1267. Bytecode init = new Bytecode(cp, 0,
  1268. codeAttr.getMaxLocals());
  1269. CtClass[] params
  1270. = Descriptor.getParameterTypes(
  1271. minfo.getDescriptor(),
  1272. classPool);
  1273. int stacksize = makeFieldInitializer(init, params);
  1274. insertAuxInitializer(codeAttr, init, stacksize);
  1275. minfo.rebuildStackMapIf6(classPool, cf);
  1276. }
  1277. catch (BadBytecode e) {
  1278. throw new CannotCompileException(e);
  1279. }
  1280. }
  1281. }
  1282. }
  1283. private static void insertAuxInitializer(CodeAttribute codeAttr,
  1284. Bytecode initializer,
  1285. int stacksize)
  1286. throws BadBytecode
  1287. {
  1288. CodeIterator it = codeAttr.iterator();
  1289. int index = it.skipSuperConstructor();
  1290. if (index < 0) {
  1291. index = it.skipThisConstructor();
  1292. if (index >= 0)
  1293. return; // this() is called.
  1294. // Neither this() or super() is called.
  1295. }
  1296. int pos = it.insertEx(initializer.get());
  1297. it.insert(initializer.getExceptionTable(), pos);
  1298. int maxstack = codeAttr.getMaxStack();
  1299. if (maxstack < stacksize)
  1300. codeAttr.setMaxStack(stacksize);
  1301. }
  1302. private int makeFieldInitializer(Bytecode code, CtClass[] parameters)
  1303. throws CannotCompileException, NotFoundException
  1304. {
  1305. int stacksize = 0;
  1306. Javac jv = new Javac(code, this);
  1307. try {
  1308. jv.recordParams(parameters, false);
  1309. }
  1310. catch (CompileError e) {
  1311. throw new CannotCompileException(e);
  1312. }
  1313. for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next) {
  1314. CtField f = fi.field;
  1315. if (!Modifier.isStatic(f.getModifiers())) {
  1316. int s = fi.init.compile(f.getType(), f.getName(), code,
  1317. parameters, jv);
  1318. if (stacksize < s)
  1319. stacksize = s;
  1320. }
  1321. }
  1322. return stacksize;
  1323. }
  1324. // Methods used by CtNewWrappedMethod
  1325. Hashtable getHiddenMethods() {
  1326. if (hiddenMethods == null)
  1327. hiddenMethods = new Hashtable();
  1328. return hiddenMethods;
  1329. }
  1330. int getUniqueNumber() { return uniqueNumberSeed++; }
  1331. public String makeUniqueName(String prefix) {
  1332. HashMap table = new HashMap();
  1333. makeMemberList(table);
  1334. Set keys = table.keySet();
  1335. String[] methods = new String[keys.size()];
  1336. keys.toArray(methods);
  1337. if (notFindInArray(prefix, methods))
  1338. return prefix;
  1339. int i = 100;
  1340. String name;
  1341. do {
  1342. if (i > 999)
  1343. throw new RuntimeException("too many unique name");
  1344. name = prefix + i++;
  1345. } while (!notFindInArray(name, methods));
  1346. return name;
  1347. }
  1348. private static boolean notFindInArray(String prefix, String[] values) {
  1349. int len = values.length;
  1350. for (int i = 0; i < len; i++)
  1351. if (values[i].startsWith(prefix))
  1352. return false;
  1353. return true;
  1354. }
  1355. private void makeMemberList(HashMap table) {
  1356. int mod = getModifiers();
  1357. if (Modifier.isAbstract(mod) || Modifier.isInterface(mod))
  1358. try {
  1359. CtClass[] ifs = getInterfaces();
  1360. int size = ifs.length;
  1361. for (int i = 0; i < size; i++) {
  1362. CtClass ic =ifs[i];
  1363. if (ic != null && ic instanceof CtClassType)
  1364. ((CtClassType)ic).makeMemberList(table);
  1365. }
  1366. }
  1367. catch (NotFoundException e) {}
  1368. try {
  1369. CtClass s = getSuperclass();
  1370. if (s != null && s instanceof CtClassType)
  1371. ((CtClassType)s).makeMemberList(table);
  1372. }
  1373. catch (NotFoundException e) {}
  1374. List list = getClassFile2().getMethods();
  1375. int n = list.size();
  1376. for (int i = 0; i < n; i++) {
  1377. MethodInfo minfo = (MethodInfo)list.get(i);
  1378. table.put(minfo.getName(), this);
  1379. }
  1380. list = getClassFile2().getFields();
  1381. n = list.size();
  1382. for (int i = 0; i < n; i++) {
  1383. FieldInfo finfo = (FieldInfo)list.get(i);
  1384. table.put(finfo.getName(), this);
  1385. }
  1386. }
  1387. }
  1388. class FieldInitLink {
  1389. FieldInitLink next;
  1390. CtField field;
  1391. CtField.Initializer init;
  1392. FieldInitLink(CtField f, CtField.Initializer i) {
  1393. next = null;
  1394. field = f;
  1395. init = i;
  1396. }
  1397. }