All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.javassist.CtMethod Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * 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.bytecode.AccessFlag;
import com.feilong.lib.javassist.bytecode.BadBytecode;
import com.feilong.lib.javassist.bytecode.Bytecode;
import com.feilong.lib.javassist.bytecode.CodeAttribute;
import com.feilong.lib.javassist.bytecode.CodeIterator;
import com.feilong.lib.javassist.bytecode.ConstPool;
import com.feilong.lib.javassist.bytecode.Descriptor;
import com.feilong.lib.javassist.bytecode.MethodInfo;
import com.feilong.lib.javassist.bytecode.Opcode;

/**
 * An instance of CtMethod represents a method.
 *
 * 

* See the super class CtBehavior since * a number of useful methods are in CtBehavior. * A number of useful factory methods are in CtNewMethod. * * @see CtClass#getDeclaredMethods() * @see CtNewMethod */ public final class CtMethod extends CtBehavior{ protected String cachedStringRep; /** * @see #make(MethodInfo minfo, CtClass declaring) */ CtMethod(MethodInfo minfo, CtClass declaring){ super(declaring, minfo); cachedStringRep = null; } /** * Creates a public abstract method. The created method must be * added to a class with CtClass.addMethod(). * * @param declaring * the class to which the created method is added. * @param returnType * the type of the returned value * @param mname * the method name * @param parameters * a list of the parameter types * * @see CtClass#addMethod(CtMethod) */ public CtMethod(CtClass returnType, String mname, CtClass[] parameters, CtClass declaring){ this(null, declaring); ConstPool cp = declaring.getClassFile2().getConstPool(); String desc = Descriptor.ofMethod(returnType, parameters); methodInfo = new MethodInfo(cp, mname, desc); setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT); } /** * Creates a copy of a CtMethod object. * The created method must be * added to a class with CtClass.addMethod(). * *

* All occurrences of class names in the created method * are replaced with names specified by * map if map is not null. * *

* For example, suppose that a method at() is as * follows: * *

     * 
     * public X at(int i){
     *     return (X) super.elementAt(i);
     * }
     * 
* *

* (X is a class name.) If map substitutes * String for X, then the created method is: * *

     * 
     * public String at(int i){
     *     return (String) super.elementAt(i);
     * }
     * 
* *

* By default, all the occurrences of the names of the class * declaring at() and the superclass are replaced * with the name of the class and the superclass that the * created method is added to. * This is done whichever map is null or not. * To prevent this replacement, call ClassMap.fix() * or put() to explicitly specify replacement. * *

* Note: if the .class notation (for example, * String.class) is included in an expression, the * Javac compiler may produce a helper method. * Since this constructor never * copies this helper method, the programmers have the responsiblity of * copying it. Otherwise, use Class.forName() in the * expression. * * @param src * the source method. * @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 null. * * @see CtClass#addMethod(CtMethod) * @see ClassMap#fix(String) */ public CtMethod(CtMethod src, CtClass declaring, ClassMap map) throws CannotCompileException{ this(null, declaring); copy(src, false, map); } /** * Compiles the given source code and creates a method. * This method simply delegates to make() in * CtNewMethod. See it for more details. * CtNewMethod has a number of useful factory methods. * * @param src * the source text. * @param declaring * the class to which the created method is added. * @see CtNewMethod#make(String, CtClass) */ public static CtMethod make(String src,CtClass declaring) throws CannotCompileException{ return CtNewMethod.make(src, declaring); } /** * Creates a method from a MethodInfo object. * * @param declaring * the class declaring the method. * @throws CannotCompileException * if the the MethodInfo * object and the declaring class have different * ConstPool objects * @since 3.6 */ public static CtMethod make(MethodInfo minfo,CtClass declaring) throws CannotCompileException{ if (declaring.getClassFile2().getConstPool() != minfo.getConstPool()){ throw new CannotCompileException("bad declaring class"); } return new CtMethod(minfo, declaring); } /** * Returns a hash code value for the method. * If two methods have the same name and signature, then * the hash codes for the two methods are equal. */ @Override public int hashCode(){ return getStringRep().hashCode(); } /** * This method is invoked when setName() or replaceClassName() * in CtClass is called. */ @Override void nameReplaced(){ cachedStringRep = null; } /* * This method is also called by CtClassType.getMethods0(). */ final String getStringRep(){ if (cachedStringRep == null){ cachedStringRep = methodInfo.getName() + Descriptor.getParamDescriptor(methodInfo.getDescriptor()); } return cachedStringRep; } /** * Indicates whether obj has the same name and the * same signature as this method. */ @Override public boolean equals(Object obj){ return obj != null && obj instanceof CtMethod && ((CtMethod) obj).getStringRep().equals(getStringRep()); } /** * Returns the method name followed by parameter types * such as javassist.CtMethod.setBody(String). * * @since 3.5 */ @Override public String getLongName(){ return getDeclaringClass().getName() + "." + getName() + Descriptor.toString(getSignature()); } /** * Obtains the name of this method. */ @Override public String getName(){ return methodInfo.getName(); } /** * Changes the name of this method. */ public void setName(String newname){ declaringClass.checkModify(); methodInfo.setName(newname); } /** * Obtains the type of the returned value. */ public CtClass getReturnType() throws NotFoundException{ return getReturnType0(); } /** * Returns true if the method body is empty, that is, {}. * It also returns true if the method is an abstract method. */ @Override public boolean isEmpty(){ CodeAttribute ca = getMethodInfo2().getCodeAttribute(); if (ca == null){ return (getModifiers() & Modifier.ABSTRACT) != 0; } CodeIterator it = ca.iterator(); try{ return it.hasNext() && it.byteAt(it.next()) == Opcode.RETURN && !it.hasNext(); }catch (BadBytecode e){} return false; } /** * Copies a method body from another method. * If this method is abstract, the abstract modifier is removed * after the method body is copied. * *

* All occurrences of the class names in the copied method body * are replaced with the names specified by * map if map is not null. * * @param src * the method that the body is copied from. * @param map * the hashtable associating original class names * with substituted names. * It can be null. */ public void setBody(CtMethod src,ClassMap map) throws CannotCompileException{ setBody0(src.declaringClass, src.methodInfo, declaringClass, methodInfo, map); } /** * 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 null). * * @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. } // inner classes /** * Instances of this class represent a constant parameter. * They are used to specify the parameter given to the methods * created by CtNewMethod.wrapped(). * * @see CtMethod#setWrappedBody(CtMethod,CtMethod.ConstParameter) * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass) * @see CtNewConstructor#make(CtClass[],CtClass[],int,CtMethod,CtMethod.ConstParameter,CtClass) */ public static class ConstParameter{ /** * Makes an integer constant. * * @param i * the constant value. */ public static ConstParameter integer(int i){ return new IntConstParameter(i); } /** * Makes a long integer constant. * * @param i * the constant value. */ public static ConstParameter integer(long i){ return new LongConstParameter(i); } /** * Makes an String constant. * * @param s * the constant value. */ public static ConstParameter string(String s){ return new StringConstParameter(s); } ConstParameter(){ } /** * @return the size of the stack consumption. */ int compile(Bytecode code) throws CannotCompileException{ return 0; } String descriptor(){ return defaultDescriptor(); } /** * @see CtNewWrappedMethod */ static String defaultDescriptor(){ return "([Ljava/lang/Object;)Ljava/lang/Object;"; } /** * Returns the descriptor for constructors. * * @see CtNewWrappedConstructor */ String constDescriptor(){ return defaultConstDescriptor(); } /** * Returns the default descriptor for constructors. */ static String defaultConstDescriptor(){ return "([Ljava/lang/Object;)V"; } } static class IntConstParameter extends ConstParameter{ int param; IntConstParameter(int i){ param = i; } @Override int compile(Bytecode code) throws CannotCompileException{ code.addIconst(param); return 1; } @Override String descriptor(){ return "([Ljava/lang/Object;I)Ljava/lang/Object;"; } @Override String constDescriptor(){ return "([Ljava/lang/Object;I)V"; } } static class LongConstParameter extends ConstParameter{ long param; LongConstParameter(long l){ param = l; } @Override int compile(Bytecode code) throws CannotCompileException{ code.addLconst(param); return 2; } @Override String descriptor(){ return "([Ljava/lang/Object;J)Ljava/lang/Object;"; } @Override String constDescriptor(){ return "([Ljava/lang/Object;J)V"; } } static class StringConstParameter extends ConstParameter{ String param; StringConstParameter(String s){ param = s; } @Override int compile(Bytecode code) throws CannotCompileException{ code.addLdc(param); return 1; } @Override String descriptor(){ return "([Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;"; } @Override String constDescriptor(){ return "([Ljava/lang/Object;Ljava/lang/String;)V"; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy