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, <type> 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, <type> 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