com.feilong.lib.javassist.CtNewConstructor Maven / Gradle / Ivy
Show all versions of feilong Show documentation
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- 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,
* or the Apache License Version 2.0.
*
* 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 com.feilong.lib.javassist;
import com.feilong.lib.javassist.CtMethod.ConstParameter;
import com.feilong.lib.javassist.bytecode.Bytecode;
import com.feilong.lib.javassist.bytecode.ConstPool;
import com.feilong.lib.javassist.bytecode.Opcode;
import com.feilong.lib.javassist.compiler.CompileError;
import com.feilong.lib.javassist.compiler.Javac;
/**
* A collection of static methods for creating a CtConstructor
.
* An instance of this class does not make any sense.
*
*
* A class initializer (static constructor) cannot be created by the
* methods in this class. Call makeClassInitializer()
in
* CtClass
and append code snippet to the body of the class
* initializer obtained by makeClassInitializer()
.
*
* @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
* Object
and passed to a super-class'
* constructor.
*/
public static final int PASS_ARRAY = 1; // an array of parameters
/**
* Specifies that parameters are passed as is
* 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 {}
.
* If it is null
, the substituted
* constructor body does nothing except calling
* super()
.
* @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);
}
}
/**
* Creates a copy of a constructor.
* This is a convenience method for calling
* {@link CtConstructor#CtConstructor(CtConstructor, CtClass, ClassMap) this constructor}.
* See the description of the constructor for particular behavior of the copying.
*
* @param c
* the copied constructor.
* @param declaring
* the class to which the created method is added.
* @param map
* the hash table associating original class names
* with substituted names.
* It can be null
.
*
* @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.
*
*
* The created constructor takes no parameter. It calls
* super()
.
*/
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(), "", "()V");
}catch (NotFoundException e){
throw new CannotCompileException(e);
}
code.add(Opcode.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 parameters
but calls the super's
* constructor without those parameters (that is, it calls the default
* constructor).
*
*
* The parameters passed to the created constructor should be
* used for field initialization. CtField.Initializer
* 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 parameters
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.
*
*
* If howto
is PASS_PARAMS
,
* 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.
*
*
* If howto
is PASS_NONE
,
* the created constructor calls the super's default constructor.
* The superclass must contain a constructor taking no parameters.
*
*
* If howto
is PASS_ARRAY
,
* the created constructor calls the super's constructor
* with the given parameters in the form of an array of
* Object
. The signature of the super's constructor
* must be:
*
*
* constructor(Object[] params, <type> cvalue)
*
*
*
* Here, cvalue
is the constant value specified
* by cparam
.
*
*
* If cparam
is null
, the signature
* must be:
*
*
* constructor(Object[] params)
*
*
*
* If body
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 body
must not
* be a constructor but a method.
*
*
* Since the embedded method is wrapped
* in parameter-conversion code
* as in CtNewMethod.wrapped()
,
* the constructor parameters are
* passed in the form of an array of Object
.
* The method specified by body
must have the
* signature shown below:
*
*
* Object method(Object[] params, <type> cvalue)
*
*
*
* If cparam
is null
, the signature
* must be:
*
*
* Object method(Object[] params)
*
*
*
* Although the type of the returned value is Object
,
* the value must be always null
.
*
*
* Example:
*
*
* 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);
*
*
*
* where the class Sample
is as follows:
*
*
* public class Sample{
*
* public Object m(Object[] args,String msg){
* System.out.println(msg);
* return null;
* }
* }
*
*
*
* This program produces the following class:
*
*
* 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
* }
* }
*
*
* @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 (PASS_NONE
,
* PASS_ARRAY
,
* or PASS_PARAMS
)
* @param body
* appended body (may be null
).
* It must be not a constructor but a method.
* @param cparam
* constant parameter (may be null
.)
* @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);
}
}