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

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