/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, &lt;type&gt; 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, &lt;type&gt; 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