You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CtField.java 37KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2003 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 javassist.bytecode.*;
  17. import javassist.compiler.Javac;
  18. import javassist.compiler.CompileError;
  19. import javassist.compiler.ast.ASTree;
  20. /**
  21. * An instance of CtField represents a field.
  22. *
  23. * @see CtClass#getDeclaredFields()
  24. */
  25. public class CtField extends CtMember {
  26. protected FieldInfo fieldInfo;
  27. CtField next;
  28. /**
  29. * Creates a <code>CtField</code> object.
  30. * The created field must be added to a class
  31. * with <code>CtClass.addField()</code>.
  32. * An initial value of the field is specified
  33. * by a <code>CtField.Initializer</code> object.
  34. *
  35. * <p>If getter and setter methods are needed,
  36. * call <code>CtNewMethod.getter()</code> and
  37. * <code>CtNewMethod.setter()</code>.
  38. *
  39. * @param type field type
  40. * @param name field name
  41. * @param declaring the class to which the field will be added.
  42. *
  43. * @see CtClass#addField(CtField)
  44. * @see CtNewMethod#getter(String,CtField)
  45. * @see CtNewMethod#setter(String,CtField)
  46. * @see CtField.Initializer
  47. */
  48. public CtField(CtClass type, String name, CtClass declaring)
  49. throws CannotCompileException
  50. {
  51. this(Descriptor.of(type), name, declaring);
  52. }
  53. /**
  54. * Creates a copy of the given field.
  55. * The created field must be added to a class
  56. * with <code>CtClass.addField()</code>.
  57. * An initial value of the field is specified
  58. * by a <code>CtField.Initializer</code> object.
  59. *
  60. * <p>If getter and setter methods are needed,
  61. * call <code>CtNewMethod.getter()</code> and
  62. * <code>CtNewMethod.setter()</code>.
  63. *
  64. * @param src the original field
  65. * @param declaring the class to which the field will be added.
  66. * @see CtNewMethod#getter(String,CtField)
  67. * @see CtNewMethod#setter(String,CtField)
  68. * @see CtField.Initializer
  69. */
  70. public CtField(CtField src, CtClass declaring)
  71. throws CannotCompileException
  72. {
  73. this(src.fieldInfo.getDescriptor(), src.fieldInfo.getName(),
  74. declaring);
  75. }
  76. private CtField(String typeDesc, String name, CtClass clazz)
  77. throws CannotCompileException
  78. {
  79. super(clazz);
  80. next = null;
  81. ClassFile cf = clazz.getClassFile2();
  82. if (cf == null)
  83. throw new CannotCompileException("bad declaring class: "
  84. + clazz.getName());
  85. fieldInfo = new FieldInfo(cf.getConstPool(), name, typeDesc);
  86. }
  87. CtField(FieldInfo fi, CtClass clazz) {
  88. super(clazz);
  89. fieldInfo = fi;
  90. next = null;
  91. }
  92. /* Javac.CtFieldWithInit overrides.
  93. */
  94. protected ASTree getInitAST() { return null; }
  95. /* Called by CtClassType.addField().
  96. */
  97. Initializer getInit() {
  98. ASTree tree = getInitAST();
  99. if (tree == null)
  100. return null;
  101. else
  102. return Initializer.byExpr(tree);
  103. }
  104. /**
  105. * Compiles the given source code and creates a field.
  106. * Examples of the source code are:
  107. *
  108. * <ul><pre>
  109. * "public String name;"
  110. * "public int k = 3;"</pre></ul>
  111. *
  112. * <p>Note that the source code ends with <code>';'</code>
  113. * (semicolon).
  114. *
  115. * @param src the source text.
  116. * @param declaring the class to which the created field is added.
  117. */
  118. public static CtField make(String src, CtClass declaring)
  119. throws CannotCompileException
  120. {
  121. Javac compiler = new Javac(declaring);
  122. try {
  123. CtMember obj = compiler.compile(src);
  124. if (obj instanceof CtField)
  125. return (CtField)obj; // an instance of Javac.CtFieldWithInit
  126. }
  127. catch (CompileError e) {
  128. throw new CannotCompileException(e);
  129. }
  130. throw new CannotCompileException("not a field");
  131. }
  132. static CtField append(CtField list, CtField tail) {
  133. tail.next = null;
  134. if (list == null)
  135. return tail;
  136. else {
  137. CtField lst = list;
  138. while (lst.next != null)
  139. lst = lst.next;
  140. lst.next = tail;
  141. return list;
  142. }
  143. }
  144. static int count(CtField f) {
  145. int n = 0;
  146. while (f != null) {
  147. ++n;
  148. f = f.next;
  149. }
  150. return n;
  151. }
  152. /**
  153. * Returns the FieldInfo representing the field in the class file.
  154. */
  155. public FieldInfo getFieldInfo() {
  156. declaringClass.checkModify();
  157. return fieldInfo;
  158. }
  159. /**
  160. * Undocumented method. Do not use; internal-use only.
  161. */
  162. public FieldInfo getFieldInfo2() { return fieldInfo; }
  163. /**
  164. * Returns the class declaring the field.
  165. */
  166. public CtClass getDeclaringClass() {
  167. // this is redundant but for javadoc.
  168. return super.getDeclaringClass();
  169. }
  170. /**
  171. * Returns the name of the field.
  172. */
  173. public String getName() {
  174. return fieldInfo.getName();
  175. }
  176. /**
  177. * Changes the name of the field.
  178. */
  179. public void setName(String newName) {
  180. declaringClass.checkModify();
  181. fieldInfo.setName(newName);
  182. }
  183. /**
  184. * Returns the encoded modifiers of the field.
  185. *
  186. * @see Modifier
  187. */
  188. public int getModifiers() {
  189. return AccessFlag.toModifier(fieldInfo.getAccessFlags());
  190. }
  191. /**
  192. * Sets the encoded modifiers of the field.
  193. *
  194. * @see Modifier
  195. */
  196. public void setModifiers(int mod) {
  197. declaringClass.checkModify();
  198. fieldInfo.setAccessFlags(AccessFlag.of(mod));
  199. }
  200. /**
  201. * Returns the type of the field.
  202. */
  203. public CtClass getType() throws NotFoundException {
  204. return Descriptor.toCtClass(fieldInfo.getDescriptor(),
  205. declaringClass.getClassPool());
  206. }
  207. /**
  208. * Sets the type of the field.
  209. */
  210. public void setType(CtClass clazz) {
  211. declaringClass.checkModify();
  212. fieldInfo.setDescriptor(Descriptor.of(clazz));
  213. }
  214. /**
  215. * Obtains an attribute with the given name.
  216. * If that attribute is not found in the class file, this
  217. * method returns null.
  218. *
  219. * @param name attribute name
  220. */
  221. public byte[] getAttribute(String name) {
  222. AttributeInfo ai = fieldInfo.getAttribute(name);
  223. if (ai == null)
  224. return null;
  225. else
  226. return ai.get();
  227. }
  228. /**
  229. * Adds an attribute. The attribute is saved in the class file.
  230. *
  231. * @param name attribute name
  232. * @param data attribute value
  233. */
  234. public void setAttribute(String name, byte[] data) {
  235. declaringClass.checkModify();
  236. fieldInfo.addAttribute(new AttributeInfo(fieldInfo.getConstPool(),
  237. name, data));
  238. }
  239. // inner classes
  240. /**
  241. * Instances of this class specify how to initialize a field.
  242. * <code>Initializer</code> is passed to
  243. * <code>CtClass.addField()</code> with a <code>CtField</code>.
  244. *
  245. * <p>This class cannot be instantiated with the <code>new</code> operator.
  246. * Factory methods such as <code>byParameter()</code> and
  247. * <code>byNew</code>
  248. * must be used for the instantiation. They create a new instance with
  249. * the given parameters and return it.
  250. *
  251. * @see CtClass#addField(CtField,CtField.Initializer)
  252. */
  253. public static abstract class Initializer {
  254. /**
  255. * Makes an initializer that assigns a constant integer value.
  256. * The field must be integer type.
  257. */
  258. public static Initializer constant(int i) {
  259. return new IntInitializer(i);
  260. }
  261. /**
  262. * Makes an initializer that assigns a constant long value.
  263. * The field must be long type.
  264. */
  265. public static Initializer constant(long l) {
  266. return new LongInitializer(l);
  267. }
  268. /**
  269. * Makes an initializer that assigns a constant double value.
  270. * The field must be double type.
  271. */
  272. public static Initializer constant(double d) {
  273. return new DoubleInitializer(d);
  274. }
  275. /**
  276. * Makes an initializer that assigns a constant string value.
  277. * The field must be <code>java.lang.String</code> type.
  278. */
  279. public static Initializer constant(String s) {
  280. return new StringInitializer(s);
  281. }
  282. /**
  283. * Makes an initializer using a constructor parameter.
  284. *
  285. * <p>The initial value is the
  286. * N-th parameter given to the constructor of the object including
  287. * the field. If the constructor takes less than N parameters,
  288. * the field is not initialized.
  289. * If the field is static, it is never initialized.
  290. *
  291. * @param nth the n-th (&gt;= 0) parameter is used as
  292. * the initial value.
  293. * If nth is 0, then the first parameter is
  294. * used.
  295. */
  296. public static Initializer byParameter(int nth) {
  297. ParamInitializer i = new ParamInitializer();
  298. i.nthParam = nth;
  299. return i;
  300. }
  301. /**
  302. * Makes an initializer creating a new object.
  303. *
  304. * <p>This initializer creates a new object and uses it as the initial
  305. * value of the field. The constructor of the created object receives
  306. * the parameter:
  307. *
  308. * <ul><code>Object obj</code> - the object including the field.<br>
  309. * </ul>
  310. *
  311. * <p>If the initialized field is static, then the constructor does
  312. * not receive any parameters.
  313. *
  314. * @param objectType the class instantiated for the initial value.
  315. */
  316. public static Initializer byNew(CtClass objectType) {
  317. NewInitializer i = new NewInitializer();
  318. i.objectType = objectType;
  319. i.stringParams = null;
  320. i.withConstructorParams = false;
  321. return i;
  322. }
  323. /**
  324. * Makes an initializer creating a new object.
  325. *
  326. * <p>This initializer creates a new object and uses it as the initial
  327. * value of the field. The constructor of the created object receives
  328. * the parameters:
  329. *
  330. * <ul><code>Object obj</code> - the object including the field.<br>
  331. * <code>String[] strs</code> - the character strings specified
  332. * by <code>stringParams</code><br>
  333. * </ul>
  334. *
  335. * <p>If the initialized field is static, then the constructor
  336. * receives only <code>strs</code>.
  337. *
  338. * @param objectType the class instantiated for the initial value.
  339. * @param stringParams the array of strings passed to the
  340. * constructor.
  341. */
  342. public static Initializer byNew(CtClass objectType,
  343. String[] stringParams) {
  344. NewInitializer i = new NewInitializer();
  345. i.objectType = objectType;
  346. i.stringParams = stringParams;
  347. i.withConstructorParams = false;
  348. return i;
  349. }
  350. /**
  351. * Makes an initializer creating a new object.
  352. *
  353. * <p>This initializer creates a new object and uses it as the initial
  354. * value of the field. The constructor of the created object receives
  355. * the parameters:
  356. *
  357. * <ul><code>Object obj</code> - the object including the field.<br>
  358. * <code>Object[] args</code> - the parameters passed to the
  359. * constructor of the object including the
  360. * filed.
  361. * </ul>
  362. *
  363. * <p>If the initialized field is static, then the constructor does
  364. * not receive any parameters.
  365. *
  366. * @param objectType the class instantiated for the initial value.
  367. *
  368. * @see javassist.CtField.Initializer#byNewArray(CtClass,int)
  369. * @see javassist.CtField.Initializer#byNewArray(CtClass,int[])
  370. */
  371. public static Initializer byNewWithParams(CtClass objectType) {
  372. NewInitializer i = new NewInitializer();
  373. i.objectType = objectType;
  374. i.stringParams = null;
  375. i.withConstructorParams = true;
  376. return i;
  377. }
  378. /**
  379. * Makes an initializer creating a new object.
  380. *
  381. * <p>This initializer creates a new object and uses it as the initial
  382. * value of the field. The constructor of the created object receives
  383. * the parameters:
  384. *
  385. * <ul><code>Object obj</code> - the object including the field.<br>
  386. * <code>String[] strs</code> - the character strings specified
  387. * by <code>stringParams</code><br>
  388. * <code>Object[] args</code> - the parameters passed to the
  389. * constructor of the object including the
  390. * filed.
  391. * </ul>
  392. *
  393. * <p>If the initialized field is static, then the constructor receives
  394. * only <code>strs</code>.
  395. *
  396. * @param objectType the class instantiated for the initial value.
  397. * @param stringParams the array of strings passed to the
  398. * constructor.
  399. */
  400. public static Initializer byNewWithParams(CtClass objectType,
  401. String[] stringParams) {
  402. NewInitializer i = new NewInitializer();
  403. i.objectType = objectType;
  404. i.stringParams = stringParams;
  405. i.withConstructorParams = true;
  406. return i;
  407. }
  408. /**
  409. * Makes an initializer calling a static method.
  410. *
  411. * <p>This initializer calls a static method and uses the returned
  412. * value as the initial value of the field.
  413. * The called method receives the parameters:
  414. *
  415. * <ul><code>Object obj</code> - the object including the field.<br>
  416. * </ul>
  417. *
  418. * <p>If the initialized field is static, then the method does
  419. * not receive any parameters.
  420. *
  421. * <p>The type of the returned value must be the same as the field
  422. * type.
  423. *
  424. * @param methodClass the class that the static method is
  425. * declared in.
  426. * @param methodName the name of the satic method.
  427. */
  428. public static Initializer byCall(CtClass methodClass,
  429. String methodName) {
  430. MethodInitializer i = new MethodInitializer();
  431. i.objectType = methodClass;
  432. i.methodName = methodName;
  433. i.stringParams = null;
  434. i.withConstructorParams = false;
  435. return i;
  436. }
  437. /**
  438. * Makes an initializer calling a static method.
  439. *
  440. * <p>This initializer calls a static method and uses the returned
  441. * value as the initial value of the field. The called method
  442. * receives the parameters:
  443. *
  444. * <ul><code>Object obj</code> - the object including the field.<br>
  445. * <code>String[] strs</code> - the character strings specified
  446. * by <code>stringParams</code><br>
  447. * </ul>
  448. *
  449. * <p>If the initialized field is static, then the method
  450. * receive only <code>strs</code>.
  451. *
  452. * <p>The type of the returned value must be the same as the field
  453. * type.
  454. *
  455. * @param methodClass the class that the static method is
  456. * declared in.
  457. * @param methodName the name of the satic method.
  458. * @param stringParams the array of strings passed to the
  459. * static method.
  460. */
  461. public static Initializer byCall(CtClass methodClass,
  462. String methodName,
  463. String[] stringParams) {
  464. MethodInitializer i = new MethodInitializer();
  465. i.objectType = methodClass;
  466. i.methodName = methodName;
  467. i.stringParams = stringParams;
  468. i.withConstructorParams = false;
  469. return i;
  470. }
  471. /**
  472. * Makes an initializer calling a static method.
  473. *
  474. * <p>This initializer calls a static method and uses the returned
  475. * value as the initial value of the field. The called method
  476. * receives the parameters:
  477. *
  478. * <ul><code>Object obj</code> - the object including the field.<br>
  479. * <code>Object[] args</code> - the parameters passed to the
  480. * constructor of the object including the
  481. * filed.
  482. * </ul>
  483. *
  484. * <p>If the initialized field is static, then the method does
  485. * not receive any parameters.
  486. *
  487. * <p>The type of the returned value must be the same as the field
  488. * type.
  489. *
  490. * @param methodClass the class that the static method is
  491. * declared in.
  492. * @param methodName the name of the satic method.
  493. */
  494. public static Initializer byCallWithParams(CtClass methodClass,
  495. String methodName) {
  496. MethodInitializer i = new MethodInitializer();
  497. i.objectType = methodClass;
  498. i.methodName = methodName;
  499. i.stringParams = null;
  500. i.withConstructorParams = true;
  501. return i;
  502. }
  503. /**
  504. * Makes an initializer calling a static method.
  505. *
  506. * <p>This initializer calls a static method and uses the returned
  507. * value as the initial value of the field. The called method
  508. * receives the parameters:
  509. *
  510. * <ul><code>Object obj</code> - the object including the field.<br>
  511. * <code>String[] strs</code> - the character strings specified
  512. * by <code>stringParams</code><br>
  513. * <code>Object[] args</code> - the parameters passed to the
  514. * constructor of the object including the
  515. * filed.
  516. * </ul>
  517. *
  518. * <p>If the initialized field is static, then the method
  519. * receive only <code>strs</code>.
  520. *
  521. * <p>The type of the returned value must be the same as the field
  522. * type.
  523. *
  524. * @param methodClass the class that the static method is
  525. * declared in.
  526. * @param methodName the name of the satic method.
  527. * @param stringParams the array of strings passed to the
  528. * static method.
  529. */
  530. public static Initializer byCallWithParams(CtClass methodClass,
  531. String methodName, String[] stringParams) {
  532. MethodInitializer i = new MethodInitializer();
  533. i.objectType = methodClass;
  534. i.methodName = methodName;
  535. i.stringParams = stringParams;
  536. i.withConstructorParams = true;
  537. return i;
  538. }
  539. /**
  540. * Makes an initializer creating a new array.
  541. *
  542. * @param type the type of the array.
  543. * @param size the size of the array.
  544. * @throws NotFoundException if the type of the array components
  545. * is not found.
  546. */
  547. public static Initializer byNewArray(CtClass type, int size)
  548. throws NotFoundException
  549. {
  550. return new ArrayInitializer(type.getComponentType(), size);
  551. }
  552. /**
  553. * Makes an initializer creating a new multi-dimensional array.
  554. *
  555. * @param type the type of the array.
  556. * @param sizes an <code>int</code> array of the size in every
  557. * dimension.
  558. * The first element is the size in the first
  559. * dimension. The second is in the second, etc.
  560. */
  561. public static Initializer byNewArray(CtClass type, int[] sizes) {
  562. return new MultiArrayInitializer(type, sizes);
  563. }
  564. /**
  565. * Makes an initializer.
  566. *
  567. * @param source initializer expression.
  568. */
  569. public static Initializer byExpr(String source) {
  570. return new CodeInitializer(source);
  571. }
  572. static Initializer byExpr(ASTree source) {
  573. return new PtreeInitializer(source);
  574. }
  575. // Check whether this initializer is valid for the field type.
  576. // If it is invaild, this method throws an exception.
  577. void check(CtClass type) throws CannotCompileException {}
  578. // produce codes for initialization
  579. abstract int compile(CtClass type, String name, Bytecode code,
  580. CtClass[] parameters, Javac drv)
  581. throws CannotCompileException;
  582. // produce codes for initialization
  583. abstract int compileIfStatic(CtClass type, String name,
  584. Bytecode code, Javac drv) throws CannotCompileException;
  585. }
  586. static abstract class CodeInitializer0 extends Initializer {
  587. abstract void compileExpr(Javac drv) throws CompileError;
  588. int compile(CtClass type, String name, Bytecode code,
  589. CtClass[] parameters, Javac drv)
  590. throws CannotCompileException
  591. {
  592. try {
  593. code.addAload(0);
  594. compileExpr(drv);
  595. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  596. return code.getMaxStack();
  597. }
  598. catch (CompileError e) {
  599. throw new CannotCompileException(e);
  600. }
  601. }
  602. int compileIfStatic(CtClass type, String name, Bytecode code,
  603. Javac drv) throws CannotCompileException
  604. {
  605. try {
  606. compileExpr(drv);
  607. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  608. return code.getMaxStack();
  609. }
  610. catch (CompileError e) {
  611. throw new CannotCompileException(e);
  612. }
  613. }
  614. }
  615. static class CodeInitializer extends CodeInitializer0 {
  616. private String expression;
  617. CodeInitializer(String expr) { expression = expr; }
  618. void compileExpr(Javac drv) throws CompileError {
  619. drv.compileExpr(expression);
  620. }
  621. }
  622. static class PtreeInitializer extends CodeInitializer0 {
  623. private ASTree expression;
  624. PtreeInitializer(ASTree expr) { expression = expr; }
  625. void compileExpr(Javac drv) throws CompileError {
  626. drv.compileExpr(expression);
  627. }
  628. }
  629. /**
  630. * A field initialized with a parameter passed to the constructor
  631. * of the class containing that field.
  632. */
  633. static class ParamInitializer extends Initializer {
  634. int nthParam;
  635. ParamInitializer() {}
  636. int compile(CtClass type, String name, Bytecode code,
  637. CtClass[] parameters, Javac drv)
  638. throws CannotCompileException
  639. {
  640. if (parameters != null && nthParam < parameters.length) {
  641. code.addAload(0);
  642. int nth = nthParamToLocal(nthParam, parameters, false);
  643. int s = code.addLoad(nth, type) + 1;
  644. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  645. return s; // stack size
  646. }
  647. else
  648. return 0; // do not initialize
  649. }
  650. /**
  651. * Computes the index of the local variable that the n-th parameter
  652. * is assigned to.
  653. *
  654. * @param nth n-th parameter
  655. * @param params list of parameter types
  656. * @param isStatic true if the method is static.
  657. */
  658. static int nthParamToLocal(int nth, CtClass[] params,
  659. boolean isStatic) {
  660. CtClass longType = CtClass.longType;
  661. CtClass doubleType = CtClass.doubleType;
  662. int k;
  663. if (isStatic)
  664. k = 0;
  665. else
  666. k = 1; // 0 is THIS.
  667. for (int i = 0; i < nth; ++i) {
  668. CtClass type = params[i];
  669. if (type == longType || type == doubleType)
  670. k += 2;
  671. else
  672. ++k;
  673. }
  674. return k;
  675. }
  676. int compileIfStatic(CtClass type, String name, Bytecode code,
  677. Javac drv) throws CannotCompileException
  678. {
  679. return 0;
  680. }
  681. }
  682. /**
  683. * A field initialized with an object created by the new operator.
  684. */
  685. static class NewInitializer extends Initializer {
  686. CtClass objectType;
  687. String[] stringParams;
  688. boolean withConstructorParams;
  689. NewInitializer() {}
  690. /**
  691. * Produces codes in which a new object is created and assigned to
  692. * the field as the initial value.
  693. */
  694. int compile(CtClass type, String name, Bytecode code,
  695. CtClass[] parameters, Javac drv)
  696. throws CannotCompileException
  697. {
  698. int stacksize;
  699. code.addAload(0);
  700. code.addNew(objectType);
  701. code.add(Bytecode.DUP);
  702. code.addAload(0);
  703. if (stringParams == null)
  704. stacksize = 4;
  705. else
  706. stacksize = compileStringParameter(code) + 4;
  707. if (withConstructorParams)
  708. stacksize += CtNewWrappedMethod.compileParameterList(code,
  709. parameters, 1);
  710. code.addInvokespecial(objectType, "<init>", getDescriptor());
  711. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  712. return stacksize;
  713. }
  714. private String getDescriptor() {
  715. final String desc3
  716. = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)V";
  717. if (stringParams == null)
  718. if (withConstructorParams)
  719. return "(Ljava/lang/Object;[Ljava/lang/Object;)V";
  720. else
  721. return "(Ljava/lang/Object;)V";
  722. else
  723. if (withConstructorParams)
  724. return desc3;
  725. else
  726. return "(Ljava/lang/Object;[Ljava/lang/String;)V";
  727. }
  728. /**
  729. * Produces codes for a static field.
  730. */
  731. int compileIfStatic(CtClass type, String name, Bytecode code,
  732. Javac drv) throws CannotCompileException
  733. {
  734. String desc;
  735. code.addNew(objectType);
  736. code.add(Bytecode.DUP);
  737. int stacksize = 2;
  738. if (stringParams == null)
  739. desc = "()V";
  740. else {
  741. desc = "([Ljava/lang/String;)V";
  742. stacksize += compileStringParameter(code);
  743. }
  744. code.addInvokespecial(objectType, "<init>", desc);
  745. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  746. return stacksize;
  747. }
  748. protected final int compileStringParameter(Bytecode code)
  749. throws CannotCompileException
  750. {
  751. int nparam = stringParams.length;
  752. code.addIconst(nparam);
  753. code.addAnewarray("java.lang.String");
  754. for (int j = 0; j < nparam; ++j) {
  755. code.add(Bytecode.DUP); // dup
  756. code.addIconst(j); // iconst_<j>
  757. code.addLdc(stringParams[j]); // ldc ...
  758. code.add(Bytecode.AASTORE); // aastore
  759. }
  760. return 4;
  761. }
  762. }
  763. /**
  764. * A field initialized with the result of a static method call.
  765. */
  766. static class MethodInitializer extends NewInitializer {
  767. String methodName;
  768. // the method class is specified by objectType.
  769. MethodInitializer() {}
  770. /**
  771. * Produces codes in which a new object is created and assigned to
  772. * the field as the initial value.
  773. */
  774. int compile(CtClass type, String name, Bytecode code,
  775. CtClass[] parameters, Javac drv)
  776. throws CannotCompileException
  777. {
  778. int stacksize;
  779. code.addAload(0);
  780. code.addAload(0);
  781. if (stringParams == null)
  782. stacksize = 2;
  783. else
  784. stacksize = compileStringParameter(code) + 2;
  785. if (withConstructorParams)
  786. stacksize += CtNewWrappedMethod.compileParameterList(code,
  787. parameters, 1);
  788. String typeDesc = Descriptor.of(type);
  789. String mDesc = getDescriptor() + typeDesc;
  790. code.addInvokestatic(objectType, methodName, mDesc);
  791. code.addPutfield(Bytecode.THIS, name, typeDesc);
  792. return stacksize;
  793. }
  794. private String getDescriptor() {
  795. final String desc3
  796. = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)";
  797. if (stringParams == null)
  798. if (withConstructorParams)
  799. return "(Ljava/lang/Object;[Ljava/lang/Object;)";
  800. else
  801. return "(Ljava/lang/Object;)";
  802. else
  803. if (withConstructorParams)
  804. return desc3;
  805. else
  806. return "(Ljava/lang/Object;[Ljava/lang/String;)";
  807. }
  808. /**
  809. * Produces codes for a static field.
  810. */
  811. int compileIfStatic(CtClass type, String name, Bytecode code,
  812. Javac drv) throws CannotCompileException
  813. {
  814. String desc;
  815. int stacksize = 1;
  816. if (stringParams == null)
  817. desc = "()";
  818. else {
  819. desc = "([Ljava/lang/String;)";
  820. stacksize += compileStringParameter(code);
  821. }
  822. String typeDesc = Descriptor.of(type);
  823. code.addInvokestatic(objectType, methodName, desc + typeDesc);
  824. code.addPutstatic(Bytecode.THIS, name, typeDesc);
  825. return stacksize;
  826. }
  827. }
  828. static class IntInitializer extends Initializer {
  829. int value;
  830. IntInitializer(int v) { value = v; }
  831. void check(CtClass type) throws CannotCompileException {
  832. if (type != CtClass.intType)
  833. throw new CannotCompileException("type mismatch");
  834. }
  835. int compile(CtClass type, String name, Bytecode code,
  836. CtClass[] parameters, Javac drv)
  837. throws CannotCompileException
  838. {
  839. code.addAload(0);
  840. code.addIconst(value);
  841. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  842. return 2; // stack size
  843. }
  844. int compileIfStatic(CtClass type, String name, Bytecode code,
  845. Javac drv) throws CannotCompileException
  846. {
  847. code.addIconst(value);
  848. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  849. return 1; // stack size
  850. }
  851. }
  852. static class LongInitializer extends Initializer {
  853. long value;
  854. LongInitializer(long v) { value = v; }
  855. void check(CtClass type) throws CannotCompileException {
  856. if (type != CtClass.longType)
  857. throw new CannotCompileException("type mismatch");
  858. }
  859. int compile(CtClass type, String name, Bytecode code,
  860. CtClass[] parameters, Javac drv)
  861. throws CannotCompileException
  862. {
  863. code.addAload(0);
  864. code.addLdc2w(value);
  865. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  866. return 3; // stack size
  867. }
  868. int compileIfStatic(CtClass type, String name, Bytecode code,
  869. Javac drv) throws CannotCompileException
  870. {
  871. code.addLdc2w(value);
  872. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  873. return 2; // stack size
  874. }
  875. }
  876. static class DoubleInitializer extends Initializer {
  877. double value;
  878. DoubleInitializer(double v) { value = v; }
  879. void check(CtClass type) throws CannotCompileException {
  880. if (type != CtClass.doubleType)
  881. throw new CannotCompileException("type mismatch");
  882. }
  883. int compile(CtClass type, String name, Bytecode code,
  884. CtClass[] parameters, Javac drv)
  885. throws CannotCompileException
  886. {
  887. code.addAload(0);
  888. code.addLdc2w(value);
  889. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  890. return 3; // stack size
  891. }
  892. int compileIfStatic(CtClass type, String name, Bytecode code,
  893. Javac drv) throws CannotCompileException
  894. {
  895. code.addLdc2w(value);
  896. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  897. return 2; // stack size
  898. }
  899. }
  900. static class StringInitializer extends Initializer {
  901. String value;
  902. StringInitializer(String v) { value = v; }
  903. void check(CtClass type) throws CannotCompileException {
  904. if (!type.getName().equals("java.lang.String"))
  905. throw new CannotCompileException("type mismatch");
  906. }
  907. int compile(CtClass type, String name, Bytecode code,
  908. CtClass[] parameters, Javac drv)
  909. throws CannotCompileException
  910. {
  911. code.addAload(0);
  912. code.addLdc(value);
  913. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  914. return 2; // stack size
  915. }
  916. int compileIfStatic(CtClass type, String name, Bytecode code,
  917. Javac drv) throws CannotCompileException
  918. {
  919. code.addLdc(value);
  920. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  921. return 1; // stack size
  922. }
  923. }
  924. static class ArrayInitializer extends Initializer {
  925. CtClass type;
  926. int size;
  927. ArrayInitializer(CtClass t, int s) { type = t; size = s; }
  928. private void addNewarray(Bytecode code) {
  929. if (type.isPrimitive())
  930. code.addNewarray(((CtPrimitiveType)type).getArrayType(),
  931. size);
  932. else
  933. code.addAnewarray(type, size);
  934. }
  935. int compile(CtClass type, String name, Bytecode code,
  936. CtClass[] parameters, Javac drv)
  937. throws CannotCompileException
  938. {
  939. code.addAload(0);
  940. addNewarray(code);
  941. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  942. return 2; // stack size
  943. }
  944. int compileIfStatic(CtClass type, String name, Bytecode code,
  945. Javac drv) throws CannotCompileException
  946. {
  947. addNewarray(code);
  948. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  949. return 1; // stack size
  950. }
  951. }
  952. static class MultiArrayInitializer extends Initializer {
  953. CtClass type;
  954. int[] dim;
  955. MultiArrayInitializer(CtClass t, int[] d) { type = t; dim = d; }
  956. void check(CtClass type) throws CannotCompileException {
  957. if (!type.isArray())
  958. throw new CannotCompileException("type mismatch");
  959. }
  960. int compile(CtClass type, String name, Bytecode code,
  961. CtClass[] parameters, Javac drv)
  962. throws CannotCompileException
  963. {
  964. code.addAload(0);
  965. int s = code.addMultiNewarray(type, dim);
  966. code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
  967. return s + 1; // stack size
  968. }
  969. int compileIfStatic(CtClass type, String name, Bytecode code,
  970. Javac drv) throws CannotCompileException
  971. {
  972. int s = code.addMultiNewarray(type, dim);
  973. code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
  974. return s; // stack size
  975. }
  976. }
  977. }