/*
* Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package kdp.classparser;
import kdp.classparser.attributes.*;
import kdp.classparser.constantpoolclasses.*;
import kdp.Log;
import java.io.*;
import java.util.*;
/**
* Encapsulates a Method of a Java class file.
*
* @author Aaron Dietrich
* @version $Id: MethodInfo.java,v 1.2 2000/08/14 19:49:11 zmm3876 Exp $
*
* Revision History
* $Log: MethodInfo.java,v $
* Revision 1.2 2000/08/14 19:49:11 zmm3876
* *** empty log message ***
*
* Revision 1.1 2000/08/09 16:11:50 zmm3876
* *** empty log message ***
*
* Revision 1.1.1.1 2000/07/07 13:34:23 jrv
* Initial import of kdp code
*
* Revision 1.1.1.1 2000/05/31 19:14:47 ritsun
* Initial import of kvmdt to CVS
*
* Revision 1.1 2000/04/25 00:36:43 ritsun
* Initial revision
*
*/
public class MethodInfo
{
/** access flag if this method is public */
private static final int ACC_PUBLIC = 0x0001;
/** access flag if this method is private */
private static final int ACC_PRIVATE = 0x0002;
/** access flag if this method is protected */
private static final int ACC_PROTECTED = 0x0004;
/** access flag if this method is static */
private static final int ACC_STATIC = 0x0008;
/** access flag if this method is final */
private static final int ACC_FINAL = 0x0010;
/** access flag if this method is synchronized */
private static final int ACC_SYNCHRONIZED = 0x0020;
/** access flag if this method is native */
private static final int ACC_NATIVE = 0x0100;
/** access flag if this method is abstract */
private static final int ACC_ABSTRACT = 0x0400;
/** access flag if this method is strict */
private static final int ACC_STRICT = 0x0800;
/** access flags of this method */
private int accessFlags;
/** index into constant pool containing name of method */
private int nameIndex;
/** index into constant pool table containing method signature */
private int descriptorIndex;
/** number of attributes this method has */
private int attributesCount;
/** number of arguments this method has */
private int argCount;
/** array of attributes for this method */
private AttributeInfo attributes[];
/** reference to class file's constant pool */
private ConstantPoolInfo[] constantPool;
/**
* Constructor.
*
* @param iStream input stream to read from
* @param constantPool constant pool of this class
*
* @exception IOException just pass IOExceptions up
*/
public MethodInfo (DataInputStream iStream,
final ConstantPoolInfo[] constantPool) throws IOException
{
accessFlags = iStream.readUnsignedShort ();
nameIndex = iStream.readUnsignedShort ();
descriptorIndex = iStream.readUnsignedShort ();
attributesCount = iStream.readUnsignedShort ();
//allocate space for and read in all the attributes
attributes = new AttributeInfo[attributesCount];
for (int lcv = 0; lcv < attributesCount; ++lcv)
attributes[lcv] = new AttributeInfo (iStream, constantPool);
this.constantPool = constantPool;
}
/**
* Gets the source file line numbers and code array indices of all
* lines in this method that a breakpoint can be set at.
*
* @return int[][] Array of breakable lines in source file
* and corresponding code array indices.
* int[source_file_line_#s][code_array_indices]
*/
public int[][] getBreakableLineNumbers ()
{
//get this method's code array
CodeAttribute code = getCodeAttribute ();
if (code == null) {
// jpc
Log.LOGN(2, "code is null!");
return null;
}
//get the code array's line number table
LineNumberTableAttribute lines = code.getLineNumberTable ();
if (lines == null) {
// jpc
Log.LOGN(2, "lines is null!");
return null;
}
return (lines.getLineNumbersAndIndicesAsArray ());
}
/**
* Retrieves the Code attribute for this method.
*
* @return CodeAttribute this methods code attribute or null
* if it does not have one
*/
public CodeAttribute getCodeAttribute ()
{
int attrIndex = 0;
boolean found = false;
//loop through the attributes until the Code attribute is found or
//there are no attributes left
while ((!found) && (attrIndex < attributesCount))
{
if (attributes[attrIndex].getType () == AttributeInfo.ATTR_CODE)
found = true;
else
++attrIndex;
}
if (found)
{//found the Code attribute so return it
AttributeInfo attrInfo = attributes[attrIndex];
CodeAttribute code = (CodeAttribute) attrInfo.getInfo ();
return code;
}
else
return null; //didn't find it... just return null
}
/**
* Determine if this method contains the specified source file line number.
*
* @param lineNumber source file line number
*
* @return boolean true if this method contains that
* line number, false otherwise
*/
public boolean containsLine (int lineNumber)
{
//get the code attribute
CodeAttribute code = getCodeAttribute ();
//look up if this line number is in the code attribute's LineNumberTable
if (code != null)
return (code.containsLine (lineNumber));
else
return false;
}
/**
* Retrieves the starting index in the code array that equates to the
* specified line number in the source file.
*
* @param lineNumber source file number
*
* @return int the index in this method's code array
* that equates to the specified source
* file line number.
*/
public int getCodeIndex (int lineNumber)
{
boolean found = false;
int index = 0;
//get the code attribute
CodeAttribute code = getCodeAttribute ();
if (code == null)
return -1;
//get the LineNumberTable for this method
LineNumberTableAttribute lines = code.getLineNumberTable ();
if (lines == null)
return -1;
//query the line number table for the code array index that
//contains the specified line number
return lines.getCodeIndexBySourceLineNumber (lineNumber);
}
/**
* Obtain the access flags as an int
*
* @return int the access flags for this method
*
*/
public int getAccessFlags()
{
return accessFlags;
}
/**
* Query the access permissions of this method.
*
* @return String return the access permissions as an easy
* to read string
*/
public String getAccess ()
{
String s = new String ("");
if ((accessFlags & ACC_PUBLIC) > 0)
s = s + "public ";
if ((accessFlags & ACC_PRIVATE) > 0)
s = s + "private ";
if ((accessFlags & ACC_PROTECTED) > 0)
s = s + "protected ";
if ((accessFlags & ACC_STATIC) > 0)
s = s + "static ";
if ((accessFlags & ACC_FINAL) > 0)
s = s + "final ";
if ((accessFlags & ACC_SYNCHRONIZED) > 0)
s = s + "synchronized ";
if ((accessFlags & ACC_NATIVE) > 0)
s = s + "native ";
if ((accessFlags & ACC_ABSTRACT) > 0)
s = s + "abstract ";
if ((accessFlags & ACC_STRICT) > 0)
s = s + "strict";
if (s.length () == 0)
s = "Not explicitly specified.";
return s;
}
/**
* Retrieve the parameter list of this method.
*
* @return LinkedList the parameters of this method
* as a linked list of string or null
* if there are no parameters
*/
public LinkedList getParameterList ()
{
ConstantUtf8Info utf8Info;
String s = new String ("");
//look up the method signature in the constant pool
utf8Info = (ConstantUtf8Info) constantPool[descriptorIndex];
//parse the parameter list
LinkedList paramList = StringParser.getParametersAsLL (utf8Info.toString ());
return paramList;
}
/**
* Query the return value of this method.
*
* @return String the return value of this method as a string
*/
public String getReturnValue ()
{
ConstantUtf8Info utf8Info;
//look up the return value in the constant pool
utf8Info = (ConstantUtf8Info) constantPool[descriptorIndex];
//convert the encoded return value into it's full form
return (StringParser.getReturnValue (utf8Info.toString ()));
}
/**
* Retrieve the name of this method.
*
* @return String the name of this method
*/
public String getName ()
{
ConstantUtf8Info utf8Info;
String methodName;
//look up the name in the constant pool
utf8Info = (ConstantUtf8Info) constantPool[nameIndex];
methodName = utf8Info.toString ();
return (methodName);
}
/**
* Retrieve the full signature as specified in the class file
* (params and return value) of this method
*
* @return String this methods signature
*/
public String getSignatureRaw ()
{
ConstantUtf8Info utf8Info;
//look up the signature in the constant pool
utf8Info = (ConstantUtf8Info) constantPool[descriptorIndex];
return (utf8Info.toString ());
}
/**
* Retrieve the full signature (params and return value) of this method
*
* @return String this methods signature
*/
public String getSignature ()
{
ConstantUtf8Info utf8Info;
//look up the signature in the constant pool
utf8Info = (ConstantUtf8Info) constantPool[descriptorIndex];
//parse the encoded form into it's full form
return (StringParser.parseSignature (utf8Info.toString ()));
}
/**
* Formats information about this method in a nice easy to read
* string.
*
* @return String nicely formatted string containing
* method information about this method
*/
public String toString ()
{
String s = new String ("");
s = s + "Method:\n\tAccess Flags=\t";
s = s + getAccess ();
s = s + "\n\tName=\t\t";
s = s + getName ();
s = s + "\n\tSignature=\t";
s = s + getSignature ();
s = s + "\n\tRaw signature=\t";
s = s + getSignatureRaw();
for (int lcv = 0; lcv < attributesCount; ++lcv)
s = s + "\n\t" + attributes[lcv].toString ();
s = s + "\n\t BreakableLines=\t";
int list[][] = getBreakableLineNumbers();
if (list == null) {
s = s + "No breakable lines\n";
} else {
for( int i = 0; i< list.length; i++) {
s = s + "\tSourceLine: " + list[i][0] + " CodeIndex: " +
list[i][1] + "\n";
}
}
return s;
}
public List getLocalVariables(){
AttributeInfo[] ai = null;
int attribCount = 0;
Attribute attribute = null;
for(int i = 0; i < attributesCount ; i++ ){
if( attributes[i].getType() == AttributeInfo.ATTR_CODE){
attribute = attributes[i].getInfo();
ai = ((CodeAttribute)attribute).getAttributes();
attribCount = ((CodeAttribute)attribute).getAttributeCount();
break;
}
}
int i = 0;
for(i = 0; i < attribCount ; i++ ){
if( ai[i].getType() == AttributeInfo.ATTR_LOCALVAR){
attribute = ai[i].getInfo();
LocalVariableTable[] localVariableTable =
((LocalVariableTableAttribute)attribute).getLocalVariableTable();
ConstantUtf8Info utf8Info;
List localVariableList = new ArrayList();
for ( i = 0; i < localVariableTable.length; ++i)
{
utf8Info = (ConstantUtf8Info)
constantPool[localVariableTable[i].nameIndex];
String name = utf8Info.toString ();
utf8Info = (ConstantUtf8Info)
constantPool[localVariableTable[i].descriptorIndex];
String type = StringParser.parseDataType (utf8Info.toString ());
localVariableList.add(
new LocalVariable( name,type, localVariableTable[i].startPC,
localVariableTable[i].length,localVariableTable[i].index));
}
return localVariableList;
}
}
// should not reach here
return null;
}
public int getArgCount() {
return (argCount);
}
}
|