/Users/lyon/j4p/src/javassist/CtNewConstructor.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.CtMethod.ConstParameter;
22
23 /**
24 * A collection of static methods for creating a <code>CtConstructor</code>.
25 * An instance of this class does not make any sense.
26 *
27 * @see CtClass#addConstructor(CtConstructor)
28 */
29 public class CtNewConstructor {
30 /**
31 * Specifies that no parameters are passed to a super-class'
32 * constructor. That is, the default constructor is invoked.
33 */
34 public static final int PASS_NONE = 0; // call super()
35
36 /**
37 * Specifies that parameters are converted into an array of
38 * <code>Object</code> and passed to a super-class'
39 * constructor.
40 */
41 public static final int PASS_ARRAY = 1; // an array of parameters
42
43 /**
44 * Specifies that parameters are passed <i>as is</i>
45 * to a super-class' constructor. The signature of that
46 * constructor must be the same as that of the created constructor.
47 */
48 public static final int PASS_PARAMS = 2;
49
50 /**
51 * Compiles the given source code and creates a constructor.
52 * The source code must include not only the constructor body
53 * but the whole declaration.
54 *
55 * @param src the source text.
56 * @param declaring the class to which the created constructor is added.
57 */
58 public static CtConstructor make(String src, CtClass declaring)
59 throws CannotCompileException {
60 Javac compiler = new Javac(declaring);
61 try {
62 CtMember obj = compiler.compile(src);
63 if (obj instanceof CtConstructor)
64 return (CtConstructor) obj;
65 } catch (CompileError e) {
66 throw new CannotCompileException(e);
67 }
68
69 throw new CannotCompileException("not a constructor");
70 }
71
72 /**
73 * Creates a public constructor.
74 *
75 * @param returnType the type of the returned value.
76 * @param mname the method name.
77 * @param parameters a list of the parameter types.
78 * @param exceptions a list of the exception types.
79 * @param body the source text of the constructor body.
80 * It must be a block surrounded by <code>{}</code>.
81 * If it is <code>null</code>, the substituted
82 * constructor body does nothing except calling
83 * <code>super()</code>.
84 * @param declaring the class to which the created method is added.
85 */
86 public static CtConstructor make(CtClass[] parameters,
87 CtClass[] exceptions,
88 String body, CtClass declaring)
89 throws CannotCompileException {
90 try {
91 CtConstructor cc = new CtConstructor(parameters, declaring);
92 cc.setExceptionTypes(exceptions);
93 cc.setBody(body);
94 return cc;
95 } catch (NotFoundException e) {
96 throw new CannotCompileException(e);
97 }
98 }
99
100 /**
101 * Creats a copy of a constructor.
102 *
103 * @param c the copied constructor.
104 * @param declaring the class to which the created method is added.
105 * @param map the hashtable associating original class names
106 * with substituted names.
107 * It can be <code>null</code>.
108 *
109 * @see CtConstructor#CtConstructor(CtConstructor,CtClass,ClassMap)
110 */
111 public static CtConstructor copy(CtConstructor c, CtClass declaring,
112 ClassMap map) throws CannotCompileException {
113 return new CtConstructor(c, declaring, map);
114 }
115
116 /**
117 * Creates a default (public) constructor.
118 *
119 * <p>The created constructor takes no parameter. It calls
120 * <code>super()</code>.
121 */
122 public static CtConstructor defaultConstructor(CtClass declaring)
123 throws CannotCompileException {
124 CtConstructor cons = new CtConstructor((CtClass[]) null, declaring);
125
126 ConstPool cp = declaring.getClassFile2().getConstPool();
127 Bytecode code = new Bytecode(cp, 1, 1);
128 code.addAload(0);
129 try {
130 code.addInvokespecial(declaring.getSuperclass(),
131 "<init>", "()V");
132 } catch (NotFoundException e) {
133 throw new CannotCompileException(e);
134 }
135
136 code.add(Bytecode.RETURN);
137
138 cons.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
139 return cons;
140 }
141
142 /**
143 * Creates a public constructor that only calls a constructor
144 * in the super class. The created constructor receives parameters
145 * specified by <code>parameters</code> but calls the super's
146 * constructor without those parameters (that is, it calls the default
147 * constructor).
148 *
149 * <p>The parameters passed to the created constructor should be
150 * used for field initialization. <code>CtField.Initializer</code>
151 * objects implicitly insert initialization code in constructor
152 * bodies.
153 *
154 * @param parameters parameter types
155 * @param exceptions exception types
156 * @param declaring the class to which the created constructor
157 * is added.
158 * @see CtField.Initializer#byParameter(int)
159 */
160 public static CtConstructor skeleton(CtClass[] parameters,
161 CtClass[] exceptions, CtClass declaring)
162 throws CannotCompileException {
163 return make(parameters, exceptions, PASS_NONE,
164 null, null, declaring);
165 }
166
167 /**
168 * Creates a public constructor that only calls a constructor
169 * in the super class. The created constructor receives parameters
170 * specified by <code>parameters</code> and calls the super's
171 * constructor with those parameters.
172 *
173 * @param parameters parameter types
174 * @param exceptions exception types
175 * @param declaring the class to which the created constructor
176 * is added.
177 */
178 public static CtConstructor make(CtClass[] parameters,
179 CtClass[] exceptions, CtClass declaring)
180 throws CannotCompileException {
181 return make(parameters, exceptions, PASS_PARAMS,
182 null, null, declaring);
183 }
184
185 /**
186 * Creates a public constructor.
187 *
188 * <p>If <code>howto</code> is <code>PASS_PARAMS</code>,
189 * the created constructor calls the super's constructor with the
190 * same signature. The superclass must contain
191 * a constructor taking the same set of parameters as the created one.
192 *
193 * <p>If <code>howto</code> is <code>PASS_NONE</code>,
194 * the created constructor calls the super's default constructor.
195 * The superclass must contain a constructor taking no parameters.
196 *
197 * <p>If <code>howto</code> is <code>PASS_ARRAY</code>,
198 * the created constructor calls the super's constructor
199 * with the given parameters in the form of an array of
200 * <code>Object</code>. The signature of the super's constructor
201 * must be:
202 *
203 * <ul><code>constructor(Object[] params, <type> cvalue)
204 * </code></ul>
205 *
206 * <p>Here, <code>cvalue</code> is the constant value specified
207 * by <code>cparam</code>.
208 *
209 * <p>If <code>cparam</code> is <code>null</code>, the signature
210 * must be:
211 *
212 * <ul><code>constructor(Object[] params)</code></ul>
213 *
214 * <p>If <code>body</code> is not null, a copy of that method is
215 * embedded in the body of the created constructor.
216 * The embedded method is executed after
217 * the super's constructor is called and the values of fields are
218 * initialized. Note that <code>body</code> must not
219 * be a constructor but a method.
220 *
221 * <p>Since the embedded method is wrapped
222 * in parameter-conversion code
223 * as in <code>CtNewMethod.wrapped()</code>,
224 * the constructor parameters are
225 * passed in the form of an array of <code>Object</code>.
226 * The method specified by <code>body</code> must have the
227 * signature shown below:
228 *
229 * <ul><code>Object method(Object[] params, <type> cvalue)
230 * </code></ul>
231 *
232 * <p>If <code>cparam</code> is <code>null</code>, the signature
233 * must be:
234 *
235 * <ul><code>Object method(Object[] params)</code></ul>
236 *
237 * <p>Although the type of the returned value is <code>Object</code>,
238 * the value must be always <code>null</code>.
239 *
240 * <p><i>Example:</i>
241 *
242 * <ul><pre>ClassPool pool = ... ;
243 * CtClass xclass = pool.makeClass("X");
244 * CtMethod method = pool.getMethod("Sample", "m");
245 * xclass.setSuperclass(pool.get("Y"));
246 * CtClass[] argTypes = { CtClass.intType };
247 * ConstParameter cparam = ConstParameter.string("test");
248 * CtConstructor c = CtNewConstructor.make(argTypes, null,
249 * PASS_PARAMS, method, cparam, xclass);
250 * xclass.addConstructor(c);</pre></ul>
251 *
252 * <p>where the class <code>Sample</code> is as follows:
253 *
254 * <ul><pre>public class Sample {
255 * public Object m(Object[] args, String msg) {
256 * System.out.println(msg);
257 * return null;
258 * }
259 * }</pre></ul>
260 *
261 * <p>This program produces the following class:
262 *
263 * <ul><pre>public class X extends Y {
264 * public X(int p0) {
265 * super(p0);
266 * String msg = "test";
267 * Object[] args = new Object[] { p0 };
268 * // begin of copied body
269 * System.out.println(msg);
270 * Object result = null;
271 * // end
272 * }
273 * }</pre></ul>
274 *
275 * @param parameters a list of the parameter types
276 * @param exceptions a list of the exceptions
277 * @param howto how to pass parameters to the super-class'
278 * constructor (<code>PASS_NONE</code>,
279 * <code>PASS_ARRAY</code>,
280 * or <code>PASS_PARAMS</code>)
281 * @param body appended body (may be <code>null</code>).
282 * It must be not a constructor but a method.
283 * @param cparam constant parameter (may be <code>null</code>.)
284 * @param declaring the class to which the created constructor
285 * is added.
286 *
287 * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
288 */
289 public static CtConstructor make(CtClass[] parameters,
290 CtClass[] exceptions, int howto,
291 CtMethod body, ConstParameter cparam,
292 CtClass declaring)
293 throws CannotCompileException {
294 return CtNewWrappedConstructor.wrapped(parameters, exceptions,
295 howto, body, cparam, declaring);
296 }
297 }
298