169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * An instance of <code>CtMethod</code> represents a method.
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>See the super class <code>CtBehavior</code> since
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a number of useful methods are in <code>CtBehavior</code>.
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A number of useful factory methods are in <code>CtNewMethod</code>.
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see CtClass#getDeclaredMethods()
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see CtNewMethod
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic final class CtMethod extends CtBehavior {
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected String cachedStringRep;
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #make(MethodInfo minfo, CtClass declaring)
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    CtMethod(MethodInfo minfo, CtClass declaring) {
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(declaring, minfo);
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cachedStringRep = null;
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Creates a public abstract method.  The created method must be
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * added to a class with <code>CtClass.addMethod()</code>.
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param declaring         the class to which the created method is added.
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param returnType        the type of the returned value
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param mname             the method name
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param parameters        a list of the parameter types
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtClass#addMethod(CtMethod)
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtMethod(CtClass returnType, String mname,
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    CtClass[] parameters, CtClass declaring) {
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this(null, declaring);
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = declaring.getClassFile2().getConstPool();
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc = Descriptor.ofMethod(returnType, parameters);
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo = new MethodInfo(cp, mname, desc);
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT);
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Creates a copy of a <code>CtMethod</code> object.
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The created method must be
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * added to a class with <code>CtClass.addMethod()</code>.
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>All occurrences of class names in the created method
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * are replaced with names specified by
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>map</code> if <code>map</code> is not <code>null</code>.
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>For example, suppose that a method <code>at()</code> is as
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * follows:
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <ul><pre>public X at(int i) {
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *     return (X)super.elementAt(i);
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * }</pre></ul>
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>(<code>X</code> is a class name.)  If <code>map</code> substitutes
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>String</code> for <code>X</code>, then the created method is:
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <ul><pre>public String at(int i) {
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *     return (String)super.elementAt(i);
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * }</pre></ul>
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>By default, all the occurrences of the names of the class
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * declaring <code>at()</code> and the superclass are replaced
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * with the name of the class and the superclass that the
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * created method is added to.
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This is done whichever <code>map</code> is null or not.
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * To prevent this replacement, call <code>ClassMap.fix()</code>
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * or <code>put()</code> to explicitly specify replacement.
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p><b>Note:</b> if the <code>.class</code> notation (for example,
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>String.class</code>) is included in an expression, the
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Javac compiler may produce a helper method.
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Since this constructor never
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * copies this helper method, the programmers have the responsiblity of
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * copying it.  Otherwise, use <code>Class.forName()</code> in the
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * expression.
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the source method.
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param declaring    the class to which the created method is added.
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param map       the hashtable associating original class names
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  with substituted names.
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It can be <code>null</code>.
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtClass#addMethod(CtMethod)
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see ClassMap#fix(String)
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtMethod(CtMethod src, CtClass declaring, ClassMap map)
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this(null, declaring);
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        copy(src, false, map);
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Compiles the given source code and creates a method.
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method simply delegates to <code>make()</code> in
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>CtNewMethod</code>.  See it for more details.
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>CtNewMethod</code> has a number of useful factory methods.
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src               the source text.
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param declaring    the class to which the created method is added.
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtNewMethod#make(String, CtClass)
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static CtMethod make(String src, CtClass declaring)
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return CtNewMethod.make(src, declaring);
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Creates a method from a <code>MethodInfo</code> object.
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param declaring     the class declaring the method.
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws CannotCompileException       if the the <code>MethodInfo</code>
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *          object and the declaring class have different
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *          <code>ConstPool</code> objects
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.6
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static CtMethod make(MethodInfo minfo, CtClass declaring)
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (declaring.getClassFile2().getConstPool() != minfo.getConstPool())
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("bad declaring class");
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new CtMethod(minfo, declaring);
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns a hash code value for the method.
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If two methods have the same name and signature, then
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the hash codes for the two methods are equal.
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int hashCode() {
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getStringRep().hashCode();
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method is invoked when setName() or replaceClassName()
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in CtClass is called.
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void nameReplaced() {
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cachedStringRep = null;
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* This method is also called by CtClassType.getMethods0().
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    final String getStringRep() {
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (cachedStringRep == null)
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cachedStringRep = methodInfo.getName()
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                + Descriptor.getParamDescriptor(methodInfo.getDescriptor());
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return cachedStringRep;
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Indicates whether <code>obj</code> has the same name and the
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * same signature as this method.
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean equals(Object obj) {
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return obj != null && obj instanceof CtMethod
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal               && ((CtMethod)obj).getStringRep().equals(getStringRep());
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the method name followed by parameter types
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * such as <code>javassist.CtMethod.setBody(String)</code>.
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.5
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getLongName() {
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getDeclaringClass().getName() + "."
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal               + getName() + Descriptor.toString(getSignature());
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the name of this method.
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getName() {
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return methodInfo.getName();
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Changes the name of this method.
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setName(String newname) {
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo.setName(newname);
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the type of the returned value.
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass getReturnType() throws NotFoundException {
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getReturnType0();
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if the method body is empty, that is, <code>{}</code>.
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It also returns true if the method is an abstract method.
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isEmpty() {
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = getMethodInfo2().getCodeAttribute();
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ca == null)         // abstract or native
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return (getModifiers() & Modifier.ABSTRACT) != 0;
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator it = ca.iterator();
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return it.hasNext() && it.byteAt(it.next()) == Opcode.RETURN
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                && !it.hasNext();
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {}
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return false;
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Copies a method body from another method.
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If this method is abstract, the abstract modifier is removed
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * after the method body is copied.
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>All occurrences of the class names in the copied method body
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * are replaced with the names specified by
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>map</code> if <code>map</code> is not <code>null</code>.
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src       the method that the body is copied from.
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param map       the hashtable associating original class names
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  with substituted names.
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It can be <code>null</code>.
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setBody(CtMethod src, ClassMap map)
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setBody0(src.declaringClass, src.methodInfo,
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 declaringClass, methodInfo, map);
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Replace a method body with a new method body wrapping the
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * given method.
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param mbody             the wrapped method
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param constParam        the constant parameter given to
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          the wrapped method
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          (maybe <code>null</code>).
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setWrappedBody(CtMethod mbody, ConstParameter constParam)
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        declaringClass.checkModify();
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass clazz = getDeclaringClass();
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass[] params;
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass retType;
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            params = getParameterTypes();
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            retType = getReturnType();
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Bytecode code = CtNewWrappedMethod.makeBody(clazz,
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                    clazz.getClassFile2(),
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                    mbody,
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                    params, retType,
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                    constParam);
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute cattr = code.toCodeAttribute();
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo.setCodeAttribute(cattr);
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methodInfo.setAccessFlags(methodInfo.getAccessFlags()
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  & ~AccessFlag.ABSTRACT);
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // rebuilding a stack map table is not needed.
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // inner classes
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Instances of this class represent a constant parameter.
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * They are used to specify the parameter given to the methods
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * created by <code>CtNewMethod.wrapped()</code>.
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtMethod#setWrappedBody(CtMethod,CtMethod.ConstParameter)
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see CtNewConstructor#make(CtClass[],CtClass[],int,CtMethod,CtMethod.ConstParameter,CtClass)
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class ConstParameter {
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Makes an integer constant.
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param i             the constant value.
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public static ConstParameter integer(int i) {
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new IntConstParameter(i);
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Makes a long integer constant.
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param i             the constant value.
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public static ConstParameter integer(long i) {
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new LongConstParameter(i);
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Makes an <code>String</code> constant.
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param s             the constant value.
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public static ConstParameter string(String s) {
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new StringConstParameter(s);
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstParameter() {}
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return      the size of the stack consumption.
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int compile(Bytecode code) throws CannotCompileException {
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 0;
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String descriptor() {
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return defaultDescriptor();
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @see CtNewWrappedMethod
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        static String defaultDescriptor() {
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;)Ljava/lang/Object;";
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the descriptor for constructors.
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @see CtNewWrappedConstructor
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String constDescriptor() {
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return defaultConstDescriptor();
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the default descriptor for constructors.
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        static String defaultConstDescriptor() {
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;)V";
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class IntConstParameter extends ConstParameter {
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int param;
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        IntConstParameter(int i) {
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            param = i;
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int compile(Bytecode code) throws CannotCompileException {
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addIconst(param);
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 1;
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String descriptor() {
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;I)Ljava/lang/Object;";
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String constDescriptor() {
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;I)V";
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class LongConstParameter extends ConstParameter {
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        long param;
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LongConstParameter(long l) {
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            param = l;
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int compile(Bytecode code) throws CannotCompileException {
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addLconst(param);
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 2;
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String descriptor() {
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;J)Ljava/lang/Object;";
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String constDescriptor() {
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;J)V";
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class StringConstParameter extends ConstParameter {
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String param;
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        StringConstParameter(String s) {
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            param = s;
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int compile(Bytecode code) throws CannotCompileException {
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addLdc(param);
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 1;
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String descriptor() {
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;";
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String constDescriptor() {
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "([Ljava/lang/Object;Ljava/lang/String;)V";
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
436