package com.de22.javabytecode; import java.io.IOException; import com.common.util.*; import com.de22.javabytecode.constant.*; /** * Copyright Wynne Crisman 1999,2006
*/ public class Method extends Component { private short accessFlags = 0; //The modifiers and visibility for the method.// private short nameIndex = 0; //The index within the constant collection of the name constant for this method.// private short descriptorIndex = 0; //The index within the constant collection of the descriptor for this method.// private IList attributes = new LiteList(10, 30); //The attributes associated with this method.// /** * Gets the return type in class file format (ie: [I for int[] and Ljava.lang.Object; for java.lang.Object). * @param descriptor The descriptor in class file format. * @return The return type in class file format. */ public static String getReturnType(String descriptor) { return descriptor.substring(descriptor.lastIndexOf(')') + 1); }//getReturnType()// /** * Gets the method parameters in class file format (ie: [I for int[] and Ljava.lang.Object; for java.lang.Object). * @param descriptor The descriptor in class file format. * @return The collection of parameters in order and in class file format. */ public static String[] getParamterTypes(String descriptor) { int descriptorIndex = 1; int parameterIndex = 0; String[] result = null; int startIndex = 1; //First count the parameters.// while(descriptor.charAt(descriptorIndex) != ')') { if(descriptor.charAt(descriptorIndex) == 'L') { descriptorIndex = descriptor.indexOf(';', descriptorIndex); parameterIndex++; }//if// else if(descriptor.charAt(descriptorIndex) != '[') { parameterIndex++; }//else if// descriptorIndex++; }//while// result = new String[parameterIndex]; parameterIndex = 0; descriptorIndex = 1; //Next load the parameter class names.// while(descriptor.charAt(descriptorIndex) != ')') { if(descriptor.charAt(descriptorIndex) == 'L') { descriptorIndex = descriptor.indexOf(';', descriptorIndex); result[parameterIndex++] = descriptor.substring(startIndex, descriptorIndex + 1); startIndex = descriptorIndex + 1; }//if// else if(descriptor.charAt(descriptorIndex) != '[') { result[parameterIndex++] = descriptor.substring(startIndex, descriptorIndex + 1); startIndex = descriptorIndex + 1; }//else if// descriptorIndex++; }//while// return result; }//getParamterTypes()// /** * Method constructor. */ protected Method(Type type) { super(type); }//Method()// /** * Adds an attribute to the method. * An attribute describes some property of the method. * @param attribute The attribute to add to the method. The attribute's name will automatically be added to the constant pool. * @return The index of the attribute in the attribute pool. */ public short addAttribute(CodeAttribute attribute) { short nameIndex = getType().addConstant(new ConstantUtf8(getType(), attribute.getDefaultName()), false); attribute.setNameIndex(nameIndex); attributes.add(attribute); return (short) (attributes.getSize() - 1); }//addAttribute()// /** * Gets the attribute referenced by the index. *
Warning: This is a one based index, but the method to get the count will return the actual number of values.
* @param index The one based index of the attribute to retrieve. * @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index. */ public CodeAttribute getAttribute(short index) { int constant = index - 1; return (CodeAttribute) attributes.get(constant); }//getAttribute()// /** * Removes the attribute referenced by the index. *Warning: This is a one based index, but the method to get the count will return the actual number of values.
* @param index The one based index of the attribute to remove. * @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index. */ public CodeAttribute removeAttribute(short index) { int constant = index - 1; return (CodeAttribute) attributes.remove(constant); }//getAttribute()// /** * Gets the count of attributes associated with the type. * @return The number of attributes for this type. */ public int getAttributeCount() { return attributes.getSize(); }//getAttributeCount()// /** * Gets the method's access flags. * @return The method's access flags. * @see #ACC_PUBLIC * @see #ACC_PRIVATE * @see #ACC_PROTECTED * @see #ACC_STATIC * @see #ACC_ABSTRACT * @see #ACC_SYNCHRONIZED * @see #ACC_NATIVE * @see #ACC_FINAL */ public short getAccessFlags() { return accessFlags; }//getAccessFlags()// /** * Gets the index of constant in the classes constant pool for the method descriptor. * @return The method descriptor's constant pool index. */ public short getDescriptorIndex() { return descriptorIndex; }//getDescriptorIndex()// /** * Gets the index of constant in the classes constant pool for the method name. * @return The methods name's constant pool index. */ public short getNameIndex() { return nameIndex; }//getNameIndex()// /** * Gets the size in number of bytes of the component and all subcomponents. * @return The number of bytes required to represent the component and all subcomponents. */ public int getSize() { return 0; }//getSize()// /** * Reads this object from the given stream. * @param in The input stream to read this object from. */ public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException { short length; accessFlags = in.readShort(); nameIndex = in.readShort(); descriptorIndex = in.readShort(); length = in.readShort(); attributes = length > 0 ? new LiteList((int) length, 10) : LiteList.EMPTY_LIST; while(length-- > 0) { addAttribute(CodeAttribute.readAttribute(getType(), in)); }//while// }//readExternal()// /** * Reads a method from the given stream. * @param type The type object that the method will belong to. * @param in The input stream to read the method from. */ protected static Method readMethod(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException { Method method = new Method(type); method.readExternal(in); return method; }//readMethod()// /** * Sets the method's access flags. * @param accessFlags The method's access flags. * @see #ACC_PUBLIC * @see #ACC_PRIVATE * @see #ACC_PROTECTED * @see #ACC_STATIC * @see #ACC_ABSTRACT * @see #ACC_SYNCHRONIZED * @see #ACC_NATIVE * @see #ACC_FINAL */ public void setAccessFlags(short accessFlags) { this.accessFlags = accessFlags; }//setAccessFlags()// /** * Sets the index of constant in the classes constant pool for the method descriptor. * @param descriptorIndex The method descriptor's constant pool index. */ public void setDescriptorIndex(short descriptorIndex) { this.descriptorIndex = descriptorIndex; }//setDescriptorIndex()// /** * Sets the index of constant in the classes constant pool for the method name. * @param nameIndex The methods name's constant pool index. */ public void setNameIndex(short nameIndex) { this.nameIndex = nameIndex; }//setNameIndex()// /** * @see Component.toString(StringBuffer, int) */ public void toString(StringBuffer buffer, int tabCount) { IIterator iterator = null; appendTabs(buffer, tabCount); buffer.append("Method (accessFlags="); buffer.append(accessFlags); buffer.append(" nameIndex="); buffer.append(nameIndex); buffer.append(" descriptorIndex="); buffer.append(descriptorIndex); buffer.append(" Name='"); buffer.append(getType().getConstant(nameIndex)); buffer.append("' Signature='"); buffer.append(getType().getConstant(descriptorIndex)); buffer.append("')"); if(attributes.getSize() > 0) { buffer.append(' '); buffer.append('{'); appendEndOfLine(buffer); iterator = attributes.iterator(); while(iterator.hasNext()) { CodeAttribute attribute = (CodeAttribute) iterator.next(); attribute.toString(buffer, tabCount + 1); }//while// appendTabs(buffer, tabCount); buffer.append('}'); }//if// appendEndOfLine(buffer); }//toString()// /** * Writes this object to the given stream. * @param out The output stream to write this object to. */ public void writeExternal(java.io.ObjectOutput out) throws IOException { short length = (short) (attributes != null ? attributes.getSize() : 0); out.writeShort(accessFlags); out.writeShort(nameIndex); out.writeShort(descriptorIndex); out.writeShort(length); for(int index = 0; index < length; index++) { ((CodeAttribute) attributes.get(index)).writeExternal(out); }//for// }//writeExternal()// }//Method//