/** * Creates a wrapped method. The wrapped method receives parameters in the form of an array of * <code>Object</code>. * * <p>The body of the created method is a copy of the body of a method specified by <code>body * </code>. However, it is wrapped in parameter-conversion code. * * <p>The method specified by <code>body</code> must have this singature: * * <ul> * <code>Object method(Object[] params, <type> cvalue) * </code> * </ul> * * <p>The type of the <code>cvalue</code> depends on <code>constParam</code>. If <code>constParam * </code> is <code>null</code>, the signature must be: * * <ul> * <code>Object method(Object[] params)</code> * </ul> * * <p>The method body copied from <code>body</code> is wrapped in parameter-conversion code, which * converts parameters specified by <code>parameterTypes</code> into an array of <code>Object * </code>. The returned value is also converted from the <code>Object</code> type to the type * specified by <code>returnType</code>. Thus, the resulting method body is as follows: * * <ul> * <pre>Object[] params = new Object[] { p0, p1, ... }; * <<i>type</i>> cvalue = <<i>constant-value</i>>; * <i>... copied method body ...</i> * Object result = <<i>returned value</i>> * return (<i><returnType></i>)result; * </pre> * </ul> * * <p>The variables <code>p0</code>, <code>p2</code>, ... represent formal parameters of the * created method. The value of <code>cvalue</code> is specified by <code>constParam</code>. * * <p>If the type of a parameter or a returned value is a primitive type, then the value is * converted into a wrapper object such as <code>java.lang.Integer</code>. If the type of the * returned value is <code>void</code>, the returned value is discarded. * * <p><i>Example:</i> * * <ul> * <pre>ClassPool pool = ... ; * CtClass vec = pool.makeClass("intVector"); * vec.setSuperclass(pool.get("java.util.Vector")); * CtMethod addMethod = pool.getMethod("Sample", "add0"); * * CtClass[] argTypes = { CtClass.intType }; * CtMethod m = CtNewMethod.wrapped(CtClass.voidType, "add", argTypes, * null, addMethod, null, vec); * vec.addMethod(m);</pre> * </ul> * * <p>where the class <code>Sample</code> is as follows: * * <ul> * <pre>public class Sample extends java.util.Vector { * public Object add0(Object[] args) { * super.addElement(args[0]); * return null; * } * }</pre> * </ul> * * <p>This program produces a class <code>intVector</code>: * * <ul> * <pre>public class intVector extends java.util.Vector { * public void add(int p0) { * Object[] args = new Object[] { p0 }; * // begin of copied body * super.addElement(args[0]); * Object result = null; * // end * } * }</pre> * </ul> * * <p>Note that the type of the parameter to <code>add()</code> depends only on the value of * <code>argTypes</code> passed to <code>CtNewMethod.wrapped()</code>. Thus, it is easy to modify * this program to produce a <code>StringVector</code> class, which is a vector containing only * <code>String</code> objects, and other vector classes. * * @param returnType the type of the returned value. * @param mname the method name. * @param parameterTypes a list of the parameter types. * @param exceptionTypes a list of the exception types. * @param body the method body (must not be a static method). * @param constParam the constant parameter (maybe <code>null</code>). * @param declaring the class to which the created method is added. */ public static CtMethod wrapped( CtClass returnType, String mname, CtClass[] parameterTypes, CtClass[] exceptionTypes, CtMethod body, ConstParameter constParam, CtClass declaring) throws CannotCompileException { return CtNewWrappedMethod.wrapped( returnType, mname, parameterTypes, exceptionTypes, body, constParam, declaring); }
/** * Replace a method body with a new method body wrapping the given method. * * @param mbody the wrapped method * @param constParam the constant parameter given to the wrapped method (maybe <code>null</code>). * @see * CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass) */ public void setWrappedBody(CtMethod mbody, ConstParameter constParam) throws CannotCompileException { declaringClass.checkModify(); CtClass clazz = getDeclaringClass(); CtClass[] params; CtClass retType; try { params = getParameterTypes(); retType = getReturnType(); } catch (NotFoundException e) { throw new CannotCompileException(e); } Bytecode code = CtNewWrappedMethod.makeBody( clazz, clazz.getClassFile2(), mbody, params, retType, constParam); CodeAttribute cattr = code.toCodeAttribute(); methodInfo.setCodeAttribute(cattr); methodInfo.setAccessFlags(methodInfo.getAccessFlags() & ~AccessFlag.ABSTRACT); // rebuilding a stack map table is not needed. }