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