/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package javassist;
import javassist.bytecode.*;
import javassist.compiler.
Javac;
import javassist.compiler.
CompileError;
import javassist.
CtMethod.
ConstParameter;
/**
* A collection of static methods for creating a <code>CtConstructor</code>.
* An instance of this class does not make any sense.
*
* <p>A class initializer (static constructor) cannot be created by the
* methods in this class. Call <code>makeClassInitializer()</code> in
* <code>CtClass</code> and append code snippet to the body of the class
* initializer obtained by <code>makeClassInitializer()</code>.
*
* @see CtClass#addConstructor(CtConstructor)
* @see CtClass#makeClassInitializer()
*/
public class
CtNewConstructor {
/**
* Specifies that no parameters are passed to a super-class'
* constructor. That is, the default constructor is invoked.
*/
public static final int
PASS_NONE = 0; // call super()
/**
* Specifies that parameters are converted into an array of
* <code>Object</code> and passed to a super-class'
* constructor.
*/
public static final int
PASS_ARRAY = 1; // an array of parameters
/**
* Specifies that parameters are passed <i>as is</i>
* to a super-class' constructor. The signature of that
* constructor must be the same as that of the created constructor.
*/
public static final int
PASS_PARAMS = 2;
/**
* Compiles the given source code and creates a constructor.
* The source code must include not only the constructor body
* but the whole declaration.
*
* @param src the source text.
* @param declaring the class to which the created constructor is added.
*/
public static
CtConstructor make(
String src,
CtClass declaring)
throws
CannotCompileException
{
Javac compiler = new
Javac(
declaring);
try {
CtMember obj =
compiler.
compile(
src);
if (
obj instanceof
CtConstructor) {
// a stack map table has been already created.
return (
CtConstructor)
obj;
}
}
catch (
CompileError e) {
throw new
CannotCompileException(
e);
}
throw new
CannotCompileException("not a constructor");
}
/**
* Creates a public constructor.
*
* @param parameters a list of the parameter types.
* @param exceptions a list of the exception types.
* @param body the source text of the constructor body.
* It must be a block surrounded by <code>{}</code>.
* If it is <code>null</code>, the substituted
* constructor body does nothing except calling
* <code>super()</code>.
* @param declaring the class to which the created method is added.
*/
public static
CtConstructor make(
CtClass[]
parameters,
CtClass[]
exceptions,
String body,
CtClass declaring)
throws
CannotCompileException
{
try {
CtConstructor cc = new
CtConstructor(
parameters,
declaring);
cc.
setExceptionTypes(
exceptions);
cc.
setBody(
body);
return
cc;
}
catch (
NotFoundException e) {
throw new
CannotCompileException(
e);
}
}
/**
* Creats a copy of a constructor.
*
* @param c the copied constructor.
* @param declaring the class to which the created method is added.
* @param map the hashtable associating original class names
* with substituted names.
* It can be <code>null</code>.
*
* @see CtConstructor#CtConstructor(CtConstructor,CtClass,ClassMap)
*/
public static
CtConstructor copy(
CtConstructor c,
CtClass declaring,
ClassMap map) throws
CannotCompileException {
return new
CtConstructor(
c,
declaring,
map);
}
/**
* Creates a default (public) constructor.
*
* <p>The created constructor takes no parameter. It calls
* <code>super()</code>.
*/
public static
CtConstructor defaultConstructor(
CtClass declaring)
throws
CannotCompileException
{
CtConstructor cons = new
CtConstructor((
CtClass[])null,
declaring);
ConstPool cp =
declaring.
getClassFile2().
getConstPool();
Bytecode code = new
Bytecode(
cp, 1, 1);
code.
addAload(0);
try {
code.
addInvokespecial(
declaring.
getSuperclass(),
"<init>", "()V");
}
catch (
NotFoundException e) {
throw new
CannotCompileException(
e);
}
code.
add(
Bytecode.
RETURN);
// no need to construct a stack map table.
cons.
getMethodInfo2().
setCodeAttribute(
code.
toCodeAttribute());
return
cons;
}
/**
* Creates a public constructor that only calls a constructor
* in the super class. The created constructor receives parameters
* specified by <code>parameters</code> but calls the super's
* constructor without those parameters (that is, it calls the default
* constructor).
*
* <p>The parameters passed to the created constructor should be
* used for field initialization. <code>CtField.Initializer</code>
* objects implicitly insert initialization code in constructor
* bodies.
*
* @param parameters parameter types
* @param exceptions exception types
* @param declaring the class to which the created constructor
* is added.
* @see CtField.Initializer#byParameter(int)
*/
public static
CtConstructor skeleton(
CtClass[]
parameters,
CtClass[]
exceptions,
CtClass declaring)
throws
CannotCompileException
{
return
make(
parameters,
exceptions,
PASS_NONE,
null, null,
declaring);
}
/**
* Creates a public constructor that only calls a constructor
* in the super class. The created constructor receives parameters
* specified by <code>parameters</code> and calls the super's
* constructor with those parameters.
*
* @param parameters parameter types
* @param exceptions exception types
* @param declaring the class to which the created constructor
* is added.
*/
public static
CtConstructor make(
CtClass[]
parameters,
CtClass[]
exceptions,
CtClass declaring)
throws
CannotCompileException
{
return
make(
parameters,
exceptions,
PASS_PARAMS,
null, null,
declaring);
}
/**
* Creates a public constructor.
*
* <p>If <code>howto</code> is <code>PASS_PARAMS</code>,
* the created constructor calls the super's constructor with the
* same signature. The superclass must contain
* a constructor taking the same set of parameters as the created one.
*
* <p>If <code>howto</code> is <code>PASS_NONE</code>,
* the created constructor calls the super's default constructor.
* The superclass must contain a constructor taking no parameters.
*
* <p>If <code>howto</code> is <code>PASS_ARRAY</code>,
* the created constructor calls the super's constructor
* with the given parameters in the form of an array of
* <code>Object</code>. The signature of the super's constructor
* must be:
*
* <ul><code>constructor(Object[] params, <type> cvalue)
* </code></ul>
*
* <p>Here, <code>cvalue</code> is the constant value specified
* by <code>cparam</code>.
*
* <p>If <code>cparam</code> is <code>null</code>, the signature
* must be:
*
* <ul><code>constructor(Object[] params)</code></ul>
*
* <p>If <code>body</code> is not null, a copy of that method is
* embedded in the body of the created constructor.
* The embedded method is executed after
* the super's constructor is called and the values of fields are
* initialized. Note that <code>body</code> must not
* be a constructor but a method.
*
* <p>Since the embedded method is wrapped
* in parameter-conversion code
* as in <code>CtNewMethod.wrapped()</code>,
* the constructor parameters are
* passed in the form of an array of <code>Object</code>.
* The method specified by <code>body</code> must have the
* signature shown below:
*
* <ul><code>Object method(Object[] params, <type> cvalue)
* </code></ul>
*
* <p>If <code>cparam</code> is <code>null</code>, the signature
* must be:
*
* <ul><code>Object method(Object[] params)</code></ul>
*
* <p>Although the type of the returned value is <code>Object</code>,
* the value must be always <code>null</code>.
*
* <p><i>Example:</i>
*
* <ul><pre>ClassPool pool = ... ;
* CtClass xclass = pool.makeClass("X");
* CtMethod method = pool.getMethod("Sample", "m");
* xclass.setSuperclass(pool.get("Y"));
* CtClass[] argTypes = { CtClass.intType };
* ConstParameter cparam = ConstParameter.string("test");
* CtConstructor c = CtNewConstructor.make(argTypes, null,
* PASS_PARAMS, method, cparam, xclass);
* xclass.addConstructor(c);</pre></ul>
*
* <p>where the class <code>Sample</code> is as follows:
*
* <ul><pre>public class Sample {
* public Object m(Object[] args, String msg) {
* System.out.println(msg);
* return null;
* }
* }</pre></ul>
*
* <p>This program produces the following class:
*
* <ul><pre>public class X extends Y {
* public X(int p0) {
* super(p0);
* String msg = "test";
* Object[] args = new Object[] { p0 };
* // begin of copied body
* System.out.println(msg);
* Object result = null;
* // end
* }
* }</pre></ul>
*
* @param parameters a list of the parameter types
* @param exceptions a list of the exceptions
* @param howto how to pass parameters to the super-class'
* constructor (<code>PASS_NONE</code>,
* <code>PASS_ARRAY</code>,
* or <code>PASS_PARAMS</code>)
* @param body appended body (may be <code>null</code>).
* It must be not a constructor but a method.
* @param cparam constant parameter (may be <code>null</code>.)
* @param declaring the class to which the created constructor
* is added.
*
* @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
*/
public static
CtConstructor make(
CtClass[]
parameters,
CtClass[]
exceptions, int
howto,
CtMethod body,
ConstParameter cparam,
CtClass declaring)
throws
CannotCompileException
{
return
CtNewWrappedConstructor.
wrapped(
parameters,
exceptions,
howto,
body,
cparam,
declaring);
}
}