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