/* |
|
* reserved comment block |
|
* DO NOT REMOVE OR ALTER! |
|
*/ |
|
/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
* (the "License"); you may not use this file except in compliance with |
|
* the License. You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
package com.sun.org.apache.bcel.internal.classfile; |
|
import java.io.DataInput; |
|
import java.io.IOException; |
|
import com.sun.org.apache.bcel.internal.Const; |
|
import com.sun.org.apache.bcel.internal.generic.Type; |
|
import com.sun.org.apache.bcel.internal.util.BCELComparator; |
|
/** |
|
* This class represents the method info structure, i.e., the representation for |
|
* a method in the class. See JVM specification for details. A method has access |
|
* flags, a name, a signature and a number of attributes. |
|
* |
|
* @version $Id: Method.java 1749603 2016-06-21 20:50:19Z ggregory $ |
|
*/ |
|
public final class Method extends FieldOrMethod { |
|
private static BCELComparator bcelComparator = new BCELComparator() { |
|
@Override |
|
public boolean equals(final Object o1, final Object o2) { |
|
final Method THIS = (Method) o1; |
|
final Method THAT = (Method) o2; |
|
return THIS.getName().equals(THAT.getName()) |
|
&& THIS.getSignature().equals(THAT.getSignature()); |
|
} |
|
@Override |
|
public int hashCode(final Object o) { |
|
final Method THIS = (Method) o; |
|
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); |
|
} |
|
}; |
|
// annotations defined on the parameters of a method |
|
private ParameterAnnotationEntry[] parameterAnnotationEntries; |
|
/** |
|
* Empty constructor, all attributes have to be defined via `setXXX' |
|
* methods. Use at your own risk. |
|
*/ |
|
public Method() { |
|
} |
|
/** |
|
* Initialize from another object. Note that both objects use the same |
|
* references (shallow copy). Use clone() for a physical copy. |
|
*/ |
|
public Method(final Method c) { |
|
super(c); |
|
} |
|
/** |
|
* Construct object from file stream. |
|
* |
|
* @param file Input stream |
|
* @throws IOException |
|
* @throws ClassFormatException |
|
*/ |
|
Method(final DataInput file, final ConstantPool constant_pool) throws IOException, |
|
ClassFormatException { |
|
super(file, constant_pool); |
|
} |
|
/** |
|
* @param access_flags Access rights of method |
|
* @param name_index Points to field name in constant pool |
|
* @param signature_index Points to encoded signature |
|
* @param attributes Collection of attributes |
|
* @param constant_pool Array of constants |
|
*/ |
|
public Method(final int access_flags, final int name_index, final int signature_index, final Attribute[] attributes, |
|
final ConstantPool constant_pool) { |
|
super(access_flags, name_index, signature_index, attributes, constant_pool); |
|
} |
|
/** |
|
* Called by objects that are traversing the nodes of the tree implicitely |
|
* defined by the contents of a Java class. I.e., the hierarchy of methods, |
|
* fields, attributes, etc. spawns a tree of objects. |
|
* |
|
* @param v Visitor object |
|
*/ |
|
@Override |
|
public void accept(final Visitor v) { |
|
v.visitMethod(this); |
|
} |
|
/** |
|
* @return Code attribute of method, if any |
|
*/ |
|
public final Code getCode() { |
|
for (final Attribute attribute : super.getAttributes()) { |
|
if (attribute instanceof Code) { |
|
return (Code) attribute; |
|
} |
|
} |
|
return null; |
|
} |
|
/** |
|
* @return ExceptionTable attribute of method, if any, i.e., list all |
|
* exceptions the method may throw not exception handlers! |
|
*/ |
|
public final ExceptionTable getExceptionTable() { |
|
for (final Attribute attribute : super.getAttributes()) { |
|
if (attribute instanceof ExceptionTable) { |
|
return (ExceptionTable) attribute; |
|
} |
|
} |
|
return null; |
|
} |
|
/** |
|
* @return LocalVariableTable of code attribute if any, i.e. the call is |
|
* forwarded to the Code atribute. |
|
*/ |
|
public final LocalVariableTable getLocalVariableTable() { |
|
final Code code = getCode(); |
|
if (code == null) { |
|
return null; |
|
} |
|
return code.getLocalVariableTable(); |
|
} |
|
/** |
|
* @return LineNumberTable of code attribute if any, i.e. the call is |
|
* forwarded to the Code atribute. |
|
*/ |
|
public final LineNumberTable getLineNumberTable() { |
|
final Code code = getCode(); |
|
if (code == null) { |
|
return null; |
|
} |
|
return code.getLineNumberTable(); |
|
} |
|
/** |
|
* Return string representation close to declaration format, e.g. |
|
* 'public static void main(String[] args) throws IOException' |
|
* |
|
* @return String representation of the method. |
|
*/ |
|
@Override |
|
public final String toString() { |
|
final String access = Utility.accessToString(super.getAccessFlags()); |
|
// Get name and signature from constant pool |
|
ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(super.getSignatureIndex(), Const.CONSTANT_Utf8); |
|
String signature = c.getBytes(); |
|
c = (ConstantUtf8) super.getConstantPool().getConstant(super.getNameIndex(), Const.CONSTANT_Utf8); |
|
final String name = c.getBytes(); |
|
signature = Utility.methodSignatureToString(signature, name, access, true, |
|
getLocalVariableTable()); |
|
final StringBuilder buf = new StringBuilder(signature); |
|
for (final Attribute attribute : super.getAttributes()) { |
|
if (!((attribute instanceof Code) || (attribute instanceof ExceptionTable))) { |
|
buf.append(" [").append(attribute).append("]"); |
|
} |
|
} |
|
final ExceptionTable e = getExceptionTable(); |
|
if (e != null) { |
|
final String str = e.toString(); |
|
if (!str.isEmpty()) { |
|
buf.append("\n\t\tthrows ").append(str); |
|
} |
|
} |
|
return buf.toString(); |
|
} |
|
/** |
|
* @return deep copy of this method |
|
*/ |
|
public final Method copy(final ConstantPool _constant_pool) { |
|
return (Method) copy_(_constant_pool); |
|
} |
|
/** |
|
* @return return type of method |
|
*/ |
|
public Type getReturnType() { |
|
return Type.getReturnType(getSignature()); |
|
} |
|
/** |
|
* @return array of method argument types |
|
*/ |
|
public Type[] getArgumentTypes() { |
|
return Type.getArgumentTypes(getSignature()); |
|
} |
|
/** |
|
* @return Comparison strategy object |
|
*/ |
|
public static BCELComparator getComparator() { |
|
return bcelComparator; |
|
} |
|
/** |
|
* @param comparator Comparison strategy object |
|
*/ |
|
public static void setComparator(final BCELComparator comparator) { |
|
bcelComparator = comparator; |
|
} |
|
/** |
|
* Return value as defined by given BCELComparator strategy. By default two |
|
* method objects are said to be equal when their names and signatures are |
|
* equal. |
|
* |
|
* @see java.lang.Object#equals(java.lang.Object) |
|
*/ |
|
@Override |
|
public boolean equals(final Object obj) { |
|
return bcelComparator.equals(this, obj); |
|
} |
|
/** |
|
* Return value as defined by given BCELComparator strategy. By default |
|
* return the hashcode of the method's name XOR signature. |
|
* |
|
* @see java.lang.Object#hashCode() |
|
*/ |
|
@Override |
|
public int hashCode() { |
|
return bcelComparator.hashCode(this); |
|
} |
|
/** |
|
* @return Annotations on the parameters of a method |
|
* @since 6.0 |
|
*/ |
|
public ParameterAnnotationEntry[] getParameterAnnotationEntries() { |
|
if (parameterAnnotationEntries == null) { |
|
parameterAnnotationEntries = ParameterAnnotationEntry.createParameterAnnotationEntries(getAttributes()); |
|
} |
|
return parameterAnnotationEntries; |
|
} |
|
} |