• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */
15 
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  * <p>A class initializer (static constructor) cannot be created by the
28  * methods in this class.  Call <code>makeClassInitializer()</code> in
29  * <code>CtClass</code> and append code snippet to the body of the class
30  * initializer obtained by <code>makeClassInitializer()</code>.
31  *
32  * @see CtClass#addConstructor(CtConstructor)
33  * @see CtClass#makeClassInitializer()
34  */
35 public class CtNewConstructor {
36     /**
37      * Specifies that no parameters are passed to a super-class'
38      * constructor.  That is, the default constructor is invoked.
39      */
40     public static final int PASS_NONE = 0;      // call super()
41 
42     /**
43      * Specifies that parameters are converted into an array of
44      * <code>Object</code> and passed to a super-class'
45      * constructor.
46      */
47     public static final int PASS_ARRAY = 1;     // an array of parameters
48 
49     /**
50      * Specifies that parameters are passed <i>as is</i>
51      * to a super-class' constructor.  The signature of that
52      * constructor must be the same as that of the created constructor.
53      */
54     public static final int PASS_PARAMS = 2;
55 
56     /**
57      * Compiles the given source code and creates a constructor.
58      * The source code must include not only the constructor body
59      * but the whole declaration.
60      *
61      * @param src               the source text.
62      * @param declaring    the class to which the created constructor is added.
63      */
make(String src, CtClass declaring)64     public static CtConstructor make(String src, CtClass declaring)
65         throws CannotCompileException
66     {
67         Javac compiler = new Javac(declaring);
68         try {
69             CtMember obj = compiler.compile(src);
70             if (obj instanceof CtConstructor) {
71                 // a stack map table has been already created.
72                 return (CtConstructor)obj;
73             }
74         }
75         catch (CompileError e) {
76             throw new CannotCompileException(e);
77         }
78 
79         throw new CannotCompileException("not a constructor");
80     }
81 
82     /**
83      * Creates a public constructor.
84      *
85      * @param parameters        a list of the parameter types.
86      * @param exceptions        a list of the exception types.
87      * @param body              the source text of the constructor body.
88      *                  It must be a block surrounded by <code>{}</code>.
89      *                  If it is <code>null</code>, the substituted
90      *                  constructor body does nothing except calling
91      *                  <code>super()</code>.
92      * @param declaring    the class to which the created method is added.
93      */
make(CtClass[] parameters, CtClass[] exceptions, String body, CtClass declaring)94     public static CtConstructor make(CtClass[] parameters,
95                                      CtClass[] exceptions,
96                                      String body, CtClass declaring)
97         throws CannotCompileException
98     {
99         try {
100             CtConstructor cc = new CtConstructor(parameters, declaring);
101             cc.setExceptionTypes(exceptions);
102             cc.setBody(body);
103             return cc;
104         }
105         catch (NotFoundException e) {
106             throw new CannotCompileException(e);
107         }
108     }
109 
110     /**
111      * Creates a copy of a constructor.
112      * This is a convenience method for calling
113      * {@link CtConstructor#CtConstructor(CtConstructor, CtClass, ClassMap) this constructor}.
114      * See the description of the constructor for particular behavior of the copying.
115      *
116      * @param c         the copied constructor.
117      * @param declaring    the class to which the created method is added.
118      * @param map       the hash table associating original class names
119      *                  with substituted names.
120      *                  It can be <code>null</code>.
121      *
122      * @see CtConstructor#CtConstructor(CtConstructor,CtClass,ClassMap)
123      */
copy(CtConstructor c, CtClass declaring, ClassMap map)124     public static CtConstructor copy(CtConstructor c, CtClass declaring,
125                                 ClassMap map) throws CannotCompileException {
126         return new CtConstructor(c, declaring, map);
127     }
128 
129     /**
130      * Creates a default (public) constructor.
131      *
132      * <p>The created constructor takes no parameter.  It calls
133      * <code>super()</code>.
134      */
defaultConstructor(CtClass declaring)135     public static CtConstructor defaultConstructor(CtClass declaring)
136         throws CannotCompileException
137     {
138         CtConstructor cons = new CtConstructor((CtClass[])null, declaring);
139 
140         ConstPool cp = declaring.getClassFile2().getConstPool();
141         Bytecode code = new Bytecode(cp, 1, 1);
142         code.addAload(0);
143         try {
144             code.addInvokespecial(declaring.getSuperclass(),
145                                   "<init>", "()V");
146         }
147         catch (NotFoundException e) {
148             throw new CannotCompileException(e);
149         }
150 
151         code.add(Bytecode.RETURN);
152 
153         // no need to construct a stack map table.
154         cons.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
155         return cons;
156     }
157 
158     /**
159      * Creates a public constructor that only calls a constructor
160      * in the super class.  The created constructor receives parameters
161      * specified by <code>parameters</code> but calls the super's
162      * constructor without those parameters (that is, it calls the default
163      * constructor).
164      *
165      * <p>The parameters passed to the created constructor should be
166      * used for field initialization.  <code>CtField.Initializer</code>
167      * objects implicitly insert initialization code in constructor
168      * bodies.
169      *
170      * @param parameters        parameter types
171      * @param exceptions        exception types
172      * @param declaring         the class to which the created constructor
173      *                          is added.
174      * @see CtField.Initializer#byParameter(int)
175      */
skeleton(CtClass[] parameters, CtClass[] exceptions, CtClass declaring)176     public static CtConstructor skeleton(CtClass[] parameters,
177                         CtClass[] exceptions, CtClass declaring)
178         throws CannotCompileException
179     {
180         return make(parameters, exceptions, PASS_NONE,
181                     null, null, declaring);
182     }
183 
184     /**
185      * Creates a public constructor that only calls a constructor
186      * in the super class.  The created constructor receives parameters
187      * specified by <code>parameters</code> and calls the super's
188      * constructor with those parameters.
189      *
190      * @param parameters        parameter types
191      * @param exceptions        exception types
192      * @param declaring         the class to which the created constructor
193      *                          is added.
194      */
make(CtClass[] parameters, CtClass[] exceptions, CtClass declaring)195     public static CtConstructor make(CtClass[] parameters,
196                                      CtClass[] exceptions, CtClass declaring)
197         throws CannotCompileException
198     {
199         return make(parameters, exceptions, PASS_PARAMS,
200                     null, null, declaring);
201     }
202 
203     /**
204      * Creates a public constructor.
205      *
206      * <p>If <code>howto</code> is <code>PASS_PARAMS</code>,
207      * the created constructor calls the super's constructor with the
208      * same signature.  The superclass must contain
209      * a constructor taking the same set of parameters as the created one.
210      *
211      * <p>If <code>howto</code> is <code>PASS_NONE</code>,
212      * the created constructor calls the super's default constructor.
213      * The superclass must contain a constructor taking no parameters.
214      *
215      * <p>If <code>howto</code> is <code>PASS_ARRAY</code>,
216      * the created constructor calls the super's constructor
217      * with the given parameters in the form of an array of
218      * <code>Object</code>.  The signature of the super's constructor
219      * must be:
220      *
221      * <ul><code>constructor(Object[] params, &lt;type&gt; cvalue)
222      * </code></ul>
223      *
224      * <p>Here, <code>cvalue</code> is the constant value specified
225      * by <code>cparam</code>.
226      *
227      * <p>If <code>cparam</code> is <code>null</code>, the signature
228      * must be:
229      *
230      * <ul><code>constructor(Object[] params)</code></ul>
231      *
232      * <p>If <code>body</code> is not null, a copy of that method is
233      * embedded in the body of the created constructor.
234      * The embedded method is executed after
235      * the super's constructor is called and the values of fields are
236      * initialized.  Note that <code>body</code> must not
237      * be a constructor but a method.
238      *
239      * <p>Since the embedded method is wrapped
240      * in parameter-conversion code
241      * as in <code>CtNewMethod.wrapped()</code>,
242      * the constructor parameters are
243      * passed in the form of an array of <code>Object</code>.
244      * The method specified by <code>body</code> must have the
245      * signature shown below:
246      *
247      * <ul><code>Object method(Object[] params, &lt;type&gt; cvalue)
248      * </code></ul>
249      *
250      * <p>If <code>cparam</code> is <code>null</code>, the signature
251      * must be:
252      *
253      * <ul><code>Object method(Object[] params)</code></ul>
254      *
255      * <p>Although the type of the returned value is <code>Object</code>,
256      * the value must be always <code>null</code>.
257      *
258      * <p><i>Example:</i>
259      *
260      * <ul><pre>ClassPool pool = ... ;
261      * CtClass xclass = pool.makeClass("X");
262      * CtMethod method = pool.getMethod("Sample", "m");
263      * xclass.setSuperclass(pool.get("Y"));
264      * CtClass[] argTypes = { CtClass.intType };
265      * ConstParameter cparam = ConstParameter.string("test");
266      * CtConstructor c = CtNewConstructor.make(argTypes, null,
267      *                                  PASS_PARAMS, method, cparam, xclass);
268      * xclass.addConstructor(c);</pre></ul>
269      *
270      * <p>where the class <code>Sample</code> is as follows:
271      *
272      * <ul><pre>public class Sample {
273      *     public Object m(Object[] args, String msg) {
274      *         System.out.println(msg);
275      *         return null;
276      *     }
277      * }</pre></ul>
278      *
279      * <p>This program produces the following class:
280      *
281      * <ul><pre>public class X extends Y {
282      *     public X(int p0) {
283      *         super(p0);
284      *         String msg = "test";
285      *         Object[] args = new Object[] { p0 };
286      *         // begin of copied body
287      *         System.out.println(msg);
288      *         Object result = null;
289      *         // end
290      *     }
291      * }</pre></ul>
292      *
293      * @param parameters        a list of the parameter types
294      * @param exceptions        a list of the exceptions
295      * @param howto             how to pass parameters to the super-class'
296      *                          constructor (<code>PASS_NONE</code>,
297      *                          <code>PASS_ARRAY</code>,
298      *                          or <code>PASS_PARAMS</code>)
299      * @param body              appended body (may be <code>null</code>).
300      *                          It must be not a constructor but a method.
301      * @param cparam            constant parameter (may be <code>null</code>.)
302      * @param declaring         the class to which the created constructor
303      *                          is added.
304      *
305      * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
306      */
make(CtClass[] parameters, CtClass[] exceptions, int howto, CtMethod body, ConstParameter cparam, CtClass declaring)307     public static CtConstructor make(CtClass[] parameters,
308                                      CtClass[] exceptions, int howto,
309                                      CtMethod body, ConstParameter cparam,
310                                      CtClass declaring)
311         throws CannotCompileException
312     {
313         return CtNewWrappedConstructor.wrapped(parameters, exceptions,
314                                         howto, body, cparam, declaring);
315     }
316 }
317