/*
* Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package kdp.classparser;
import java.util.*;
/**
* A class that is used to parse the strings encountered in
* a Java class file into their "correct" representation.
* i.e. in a class file the parameters to the main method
* are encoded as
* "[Ljava/lang/String;"
* and should be displayed as
* "java.lang.String[]"
*
* @author Aaron Dietrich
* @version $Id: StringParser.java,v 1.1.1.1 2000/07/07 13:34:23 jrv Exp $
*
* Revision History
* $Log: StringParser.java,v $
* 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 StringParser
{
/**
* Parses the String s into a string that contains
* a list of parameters and a return value. The String
* s must be a properly formatted method signature
* as read in from a Java class file.
*
* @param s properly formatted method signature as read in
* from a Java class file.
* @return String string containing a list of method parameters and
* the return value.
*/
public static String parseSignature (String s)
{
//build the return string in retVal
String retVal = new String ("");
//the method parameters are extracted into this string
String methodParams;
//the method return value is extracted into this string
String methodReturnVal;
//used to determine what parameter we are on so a
// ", " can be put in the string if necessary to
//separate parameters
int timesThrough = 0;
//index is the index of the character denoting the
//end of the parameter list
int index = s.lastIndexOf (')');
//extract out the list of method parameters from
//the method signature
methodParams = new String (s.substring (1, index));
//build the parameter list
retVal = retVal + "Params: ";
if (methodParams.length () == 0)
//there are no parameters
retVal = retVal + "None";
else
{//loop until there are no parameters left to decode
while (methodParams.length () != 0)
{
//grab the first parameter out of the list
String firstParam = getFirstParam (methodParams);
//if this is not the first parameter we examined put
//a ", " in the new list to separate the parameters
if (timesThrough > 0)
retVal = retVal + ", ";
//convert the class file representation of the first
//parameter into the "correct" readable format
retVal = retVal + parseDataType (firstParam);
//get the length of the method parameter string
int length = methodParams.length ();
//get the length of the first parameter
int firstParamLength = firstParam.length ();
//remove the first parameter from the method parameter
//string
methodParams = methodParams.substring (firstParamLength, length);
++timesThrough;
}
}
//get the length of the input string
int length = s.length ();
//grab the return value by taking a substring out of
//the input from the end of the parameter list to the end
methodReturnVal = new String (s.substring (index + 1, length));
//build the final string
retVal = retVal + "\n\t\t\tReturn: " + getReturnValue (methodReturnVal);
return retVal;
}
/**
* Convert the passed in encoded string into it's full form
*
* @param s an encoded method return value
*
* @return String the full form of s
*/
public static String getReturnValue (String s)
{
int lastIndex = s.lastIndexOf (")");
String returnValue = s.substring (lastIndex + 1);
return parseDataType (returnValue);
}
/**
* Copies the first parameter from the input string
* and returns it. It does not alter the input string.
*
* @param s the list of parameters to a method
*
* @return String the first parameter of the method
*/
private static String getFirstParam (String s)
{
//build the first parameter in this String
String retVal = new String ("");
//examine the first character to determine the parameter
//type
switch (s.charAt (0))
{
case 'V' : retVal = "V"; break; //void
case 'B' : retVal = "B"; break; //byte
case 'C' : retVal = "C"; break; //char
case 'D' : retVal = "D"; break; //double
case 'F' : retVal = "F"; break; //float
case 'I' : retVal = "I"; break; //integer
case 'J' : retVal = "J"; break; //long
//a class... the class name is terminated by a ";"
case 'L' : int index = s.indexOf (';');
retVal = s.substring (0, index + 1);
break;
case 'S' : retVal = "S"; break; //short
case 'Z' : retVal = "Z"; break; //boolean
//an array... recursively call without the "["
//but put the "[" back on after the parameter
//has been extracted so that it can be pattern matched
//later for the whole parameter signature
case '[' : retVal = "[" + getFirstParam (s.substring (1));
break;
//something weird... just use the input string
default : retVal = s; break;
}
return retVal;
}
/**
* Parses an input string representing a Java
* primitive ID or class name, or array as
* extracted from a Java class file. It returns
* the "correct" readable representation of the
* string.
*
* @param s input string as read from a Java class file.
*
* @return String the resulting string
*/
public static String parseDataType (String s)
{
//build the result in here by branching based on
//the first character of the input string
//and placing the appropriate word form of the
//datatype or class name in the result string
String retVal = new String ("");
switch (s.charAt (0))
{
case 'V' : retVal = "void"; break;
case 'B' : retVal = "byte"; break;
case 'C' : retVal = "char"; break;
case 'D' : retVal = "double"; break;
case 'F' : retVal = "float"; break;
case 'I' : retVal = "int"; break;
case 'J' : retVal = "long"; break;
case 'L' : retVal = parseClassNameRemoveFirst (s); break;
case 'S' : retVal = "short"; break;
case 'Z' : retVal = "boolean"; break;
case '[' : retVal = parseDataType (s.substring (1, s.length ())) + "[]"; break;
default : retVal = s; break;
}
return retVal;
}
/**
* Extracts the parameters from the passed in method signature and
* puts them in a linked list of strings.
*
* @param s Encoded method signature
*
* @return LinkedList the parameters of a method
* in a linked list of strings
*/
public static LinkedList getParametersAsLL (String s)
{
LinkedList paramList = new LinkedList ();
//the method parameters are extracted into this string
String methodParams;
//index is the index of the character denoting the
//end of the parameter list
int index = s.lastIndexOf (')');
//extract out the list of method parameters from
//the method signature
methodParams = new String (s.substring (1, index));
if (methodParams.length () == 0)
return null;
else
{//loop until there are no parameters left to decode
while (methodParams.length () != 0)
{
//grab the first parameter out of the list
String firstParam = getFirstParam (methodParams);
paramList.add (parseDataType (firstParam));
//get the length of the method parameter string
int length = methodParams.length ();
//get the length of the first parameter
int firstParamLength = firstParam.length ();
//remove the first parameter from the method parameter string
methodParams = methodParams.substring (firstParamLength, length);
}
}
return paramList;
}
/**
* A simpler version of class name parsing.
* Just replaces "/" with ".".
*
* @param s the input string
*
* @return String the parsed output string
*/
public static String parseClassName (String s)
{
String retVal = new String (s);
retVal = retVal.replace ('/', '.');
return retVal;
}
/**
* Another local method that converts a class name to
* it's "correct" form. It replaces "/" with "." and
* removes ";" and removes the first character, often
* an "L".
*/
private static String parseClassNameRemoveFirst (String s)
{
String retVal = new String (s);
retVal = retVal.substring (1);
retVal = retVal.replace ('/', '.');
retVal = retVal.replace (';', ' ');
retVal = retVal.trim ();
return retVal;
}
}
|