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