aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/CtMethod.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/CtMethod.java')
-rw-r--r--src/main/javassist/CtMethod.java579
1 files changed, 579 insertions, 0 deletions
diff --git a/src/main/javassist/CtMethod.java b/src/main/javassist/CtMethod.java
new file mode 100644
index 00000000..dbe1931c
--- /dev/null
+++ b/src/main/javassist/CtMethod.java
@@ -0,0 +1,579 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * 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. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * 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.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist;
+
+import javassist.bytecode.*;
+import javassist.expr.ExprEditor;
+
+/* Some methods do nothing except calling the super's method.
+ * They might seem redundant but they are necessary so that javadoc
+ * includes the description of those methods in the page of this class.
+ */
+
+/**
+ * An instance of <code>CtMethod</code> represents a method.
+ *
+ * @see CtClass#getDeclaredMethods()
+ * @see CtNewMethod
+ */
+public final class CtMethod extends CtBehavior {
+ protected CtMethod next;
+ protected int cachedHashCode;
+
+ CtMethod(MethodInfo minfo, CtClass declaring) {
+ super(declaring, minfo);
+ next = null;
+ cachedHashCode = 0;
+ }
+
+ /**
+ * Creates a public abstract method. The created method must be
+ * added to a class with <code>CtClass.addMethod()</code>.
+ *
+ * @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 <code>CtMethod</code> object.
+ * The created method must be
+ * added to a class with <code>CtClass.addMethod()</code>.
+ *
+ * <p>All occurrences of class names in the created method
+ * are replaced with names specified by
+ * <code>map</code> if <code>map</code> is not <code>null</code>.
+ *
+ * <p>For example, suppose that a method <code>at()</code> is as
+ * follows:
+ *
+ * <ul><pre>public X at(int i) {
+ * return (X)super.elementAt(i);
+ * }</pre></ul>
+ *
+ * <p>(<code>X</code> is a class name.) If <code>map</code> substitutes
+ * <code>String</code> for <code>X</code>, then the created method is:
+ *
+ * <ul><pre>public String at(int i) {
+ * return (String)super.elementAt(i);
+ * }</pre></ul>
+ *
+ * <p>By default, all the occurrences of the names of the class
+ * declaring <code>at()</code> 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 <code>map</code> is null or not.
+ * To prevent this replacement, call <code>ClassMap.fix()</code>.
+ *
+ * <p><b>Note:</b> if the <code>.class</code> notation (for example,
+ * <code>String.class</code>) 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 <code>Class.forName()</code> 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 <code>null</code>.
+ *
+ * @see CtClass#addMethod(CtMethod)
+ * @see ClassMap#fix(String)
+ */
+ public CtMethod(CtMethod src, CtClass declaring, ClassMap map)
+ throws CannotCompileException
+ {
+ this(null, declaring);
+ MethodInfo srcInfo = src.methodInfo;
+ CtClass srcClass = src.getDeclaringClass();
+ ConstPool cp = declaring.getClassFile2().getConstPool();
+ if (map == null)
+ map = new ClassMap();
+
+ map.put(srcClass.getName(), declaring.getName());
+ try {
+ CtClass srcSuper = srcClass.getSuperclass();
+ if (srcSuper != null) {
+ String srcSuperName = srcSuper.getName();
+ if (!srcSuperName.equals(CtClass.javaLangObject))
+ map.put(srcSuperName,
+ declaring.getSuperclass().getName());
+ }
+
+ methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
+ }
+ catch (NotFoundException e) {
+ throw new CannotCompileException(e);
+ }
+ catch (BadBytecode e) {
+ throw new CannotCompileException(e);
+ }
+ }
+
+ static CtMethod append(CtMethod list, CtMethod tail) {
+ tail.next = null;
+ if (list == null)
+ return tail;
+ else {
+ CtMethod lst = list;
+ while (lst.next != null)
+ lst = lst.next;
+
+ lst.next = tail;
+ return list;
+ }
+ }
+
+ static int count(CtMethod m) {
+ int n = 0;
+ while (m != null) {
+ ++n;
+ m = m.next;
+ }
+
+ return n;
+ }
+
+ /**
+ * 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.
+ */
+ public int hashCode() {
+ /* This method is overridden in ExistingMethod for optimization.
+ */
+ if (cachedHashCode == 0) {
+ String signature
+ = methodInfo.getName() + ':' + methodInfo.getDescriptor();
+
+ // System.identityHashCode() returns 0 only for null.
+ cachedHashCode = System.identityHashCode(signature.intern());
+ }
+
+ return cachedHashCode;
+ }
+
+ /**
+ * Indicates whether <code>obj</code> has the same name and the
+ * same signature as this method.
+ */
+ public boolean equals(Object obj) {
+ return obj != null && obj instanceof CtMethod
+ && obj.hashCode() == hashCode();
+ }
+
+ /**
+ * Returns the MethodInfo representing the method in the class file.
+ */
+ public MethodInfo getMethodInfo() {
+ return super.getMethodInfo();
+ }
+
+ /**
+ * Obtains the modifiers of the method.
+ *
+ * @return modifiers encoded with
+ * <code>javassist.Modifier</code>.
+ * @see Modifier
+ */
+ public int getModifiers() {
+ return super.getModifiers();
+ }
+
+ /**
+ * Sets the encoded modifiers of the method.
+ *
+ * @see Modifier
+ */
+ public void setModifiers(int mod) {
+ super.setModifiers(mod);
+ }
+
+ /**
+ * Obtains the name of this method.
+ */
+ public String getName() {
+ return methodInfo.getName();
+ }
+
+ /**
+ * Changes the name of this method.
+ */
+ public void setName(String newname) {
+ declaringClass.checkModify();
+ methodInfo.setName(newname);
+ }
+
+ /**
+ * Returns the class that declares this method.
+ */
+ public CtClass getDeclaringClass() {
+ return super.getDeclaringClass();
+ }
+
+ /**
+ * Obtains parameter types of this method.
+ */
+ public CtClass[] getParameterTypes() throws NotFoundException {
+ return super.getParameterTypes();
+ }
+
+ /**
+ * Obtains the type of the returned value.
+ */
+ public CtClass getReturnType() throws NotFoundException {
+ return getReturnType0();
+ }
+
+ /**
+ * Returns the character string representing the parameter types
+ * and the return type. If two methods have the same parameter types
+ * and the return type, <code>getSignature()</code> returns the
+ * same string.
+ */
+ public String getSignature() {
+ return super.getSignature();
+ }
+
+ /**
+ * Obtains exceptions that this method may throw.
+ */
+ public CtClass[] getExceptionTypes() throws NotFoundException {
+ return super.getExceptionTypes();
+ }
+
+ /**
+ * Sets exceptions that this method may throw.
+ *
+ * @param types exception types (or null)
+ */
+ public void setExceptionTypes(CtClass[] types) throws NotFoundException {
+ super.setExceptionTypes(types);
+ }
+
+ /**
+ * Sets a method body.
+ *
+ * @param src the source code representing the method body.
+ * It must be a single statement or block.
+ */
+ public void setBody(String src) throws CannotCompileException {
+ super.setBody(src);
+ }
+
+ /**
+ * Copies a method body from another method.
+ * If this method is abstract, the abstract modifier is removed
+ * after the method body is copied.
+ *
+ * <p>All occurrences of the class names in the copied method body
+ * are replaced with the names specified by
+ * <code>map</code> if <code>map</code> is not <code>null</code>.
+ *
+ * @param src the method that the body is copied from.
+ * @param map the hashtable associating original class names
+ * with substituted names.
+ * It can be <code>null</code>.
+ */
+ 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 <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);
+ }
+
+ /**
+ * Obtains an attribute with the given name.
+ * If that attribute is not found in the class file, this
+ * method returns null.
+ *
+ * @param name attribute name
+ */
+ public byte[] getAttribute(String name) {
+ return super.getAttribute(name);
+ }
+
+ /**
+ * Adds an attribute. The attribute is saved in the class file.
+ *
+ * @param name attribute name
+ * @param data attribute value
+ */
+ public void setAttribute(String name, byte[] data) {
+ super.setAttribute(name, data);
+ }
+
+ /**
+ * Declares to use <code>$cflow</code> for this method.
+ * If <code>$cflow</code> is used, the class files modified
+ * with Javassist requires a support class
+ * <code>javassist.runtime.Cflow</code> at runtime
+ * (other Javassist classes are not required at runtime).
+ *
+ * <p>Every <code>$cflow</code> variable is given a unique name.
+ * For example, if the given name is <code>"Point.paint"</code>,
+ * then the variable is indicated by <code>$cflow(Point.paint)</code>.
+ *
+ * @param name <code>$cflow</code> name. It can include
+ * alphabets, numbers, <code>_</code>,
+ * <code>$</code>, and <code>.</code> (dot).
+ *
+ * @see javassist.runtime.Cflow
+ */
+ public void useCflow(String name) throws CannotCompileException {
+ super.useCflow(name);
+ }
+
+ /**
+ * Modifies the method body.
+ *
+ * @param converter specifies how to modify.
+ */
+ public void instrument(CodeConverter converter)
+ throws CannotCompileException
+ {
+ super.instrument(converter);
+ }
+
+ /**
+ * Modifies the method body.
+ *
+ * @param editor specifies how to modify.
+ */
+ public void instrument(ExprEditor editor)
+ throws CannotCompileException
+ {
+ super.instrument(editor);
+ }
+
+ /**
+ * Inserts bytecode at the beginning of the method body.
+ *
+ * @param src the source code representing the inserted bytecode.
+ * It must be a single statement or block.
+ */
+ public void insertBefore(String src) throws CannotCompileException {
+ super.insertBefore(src);
+ }
+
+ /**
+ * Inserts bytecode at the end of the method body.
+ * The bytecode is inserted just before every return insturction.
+ * It is not executed when an exception is thrown.
+ *
+ * @param src the source code representing the inserted bytecode.
+ * It must be a single statement or block.
+ */
+ public void insertAfter(String src)
+ throws CannotCompileException
+ {
+ super.insertAfter(src);
+ }
+
+ /**
+ * Inserts bytecode at the end of the method body.
+ * The bytecode is inserted just before every return insturction.
+ *
+ * @param src the source code representing the inserted bytecode.
+ * It must be a single statement or block.
+ * @param asFinally true if the inserted bytecode is executed
+ * not only when the transfer normally returns
+ * but also when an exception is thrown.
+ */
+ public void insertAfter(String src, boolean asFinally)
+ throws CannotCompileException
+ {
+ super.insertAfter(src, asFinally);
+ }
+
+ /**
+ * Adds a catch clause that handles an exception thrown in the
+ * method body.
+ * The catch clause must end with a return or throw statement.
+ *
+ * @param src the source code representing the catch clause.
+ * It must be a single statement or block.
+ * @param exceptionType the type of the exception handled by the
+ * catch clause.
+ * @param exceptionName the name of the variable containing the
+ * caught exception.
+ */
+ public void addCatch(String src, CtClass exceptionType,
+ String exceptionName)
+ throws CannotCompileException
+ {
+ super.addCatch(src, exceptionType, exceptionName);
+ }
+
+ // inner classes
+
+ /**
+ * Instances of this class represent a constant parameter.
+ * They are used to specify the parameter given to the methods
+ * created by <code>CtNewMethod.wrapped()</code>.
+ *
+ * @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 an <code>String</code> constant.
+ *
+ * @param s the constant value.
+ */
+ public static ConstParameter string(String s) {
+ return new StringConstParameter(s);
+ }
+
+ ConstParameter() {}
+
+ int compile(Bytecode code) throws CannotCompileException {
+ return 0;
+ }
+
+ String descriptor() {
+ return defaultDescriptor();
+ }
+
+ static String defaultDescriptor() {
+ return "([Ljava/lang/Object;)Ljava/lang/Object;";
+ }
+
+ String constDescriptor() {
+ return defaultConstDescriptor();
+ }
+
+ /**
+ * Returns the descriptor for constructors.
+ */
+ static String defaultConstDescriptor() {
+ return "([Ljava/lang/Object;)V";
+ }
+ }
+
+ static class IntConstParameter extends ConstParameter {
+ int param;
+
+ IntConstParameter(int i) {
+ param = i;
+ }
+
+ int compile(Bytecode code) throws CannotCompileException {
+ code.addIconst(param);
+ return 1;
+ }
+
+ String descriptor() {
+ return "([Ljava/lang/Object;I)Ljava/lang/Object;";
+ }
+
+ String constDescriptor() {
+ return "([Ljava/lang/Object;I)V";
+ }
+ }
+
+ static class StringConstParameter extends ConstParameter {
+ String param;
+
+ StringConstParameter(String s) {
+ param = s;
+ }
+
+ int compile(Bytecode code) throws CannotCompileException {
+ code.addLdc(param);
+ return 1;
+ }
+
+ String descriptor() {
+ return "([Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;";
+ }
+
+ String constDescriptor() {
+ return "([Ljava/lang/Object;Ljava/lang/String;)V";
+ }
+ }
+}