package com.de22.javabytecode; import com.de22.javabytecode.attribute.*; import com.de22.javabytecode.constant.*; /** * Copyright Wynne Crisman 1999,2006

* Defines an attribute in any of the attribute collections. * See the JVM specification 4.7. * Subclasses of this type will provided additional functionality. */ public abstract class CodeAttribute extends Component { /** The index of the attribute's name in the constant collection. */ private short nameIndex = -1; /** * CodeAttribute constructor. */ public CodeAttribute(Type type) { super(type); }//CodeAttribute()// /** * Gets the attribute's default name as it is stored in the class bytes. * @return The default name identifying the attribute's type. */ public abstract String getDefaultName(); /** * Gets the index of the attribute's name in the type's constant pool. * @return The index of the attribute name. */ public short getNameIndex() { return nameIndex; }//getNameIndex()// /* (non-Javadoc) * @see com.de22.javabytecode.ITypeComponent#getSize() */ public abstract int getSize(); /** * Reads an attribute from the given stream. * @param type The type object that the attribute will belong to. * @param in The input stream to read the attribute from. */ protected static CodeAttribute readAttribute(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException { CodeAttribute attribute = null; short nameIndex = in.readShort(); Constant constant = type.getConstant(nameIndex); ConstantUtf8 constantUtf8 = constant instanceof ConstantUtf8 ? (ConstantUtf8) constant : constant instanceof ConstantString ? (ConstantUtf8) type.getConstant(((ConstantString) constant).getStringIndex()) : null; //This should never occur, but seems to for some compiled java code (probably due to a bad compiler). We will simply replace the missing string with an empty string.// if(constantUtf8 == null) { // System.out.println("Null constant found (index = " + nameIndex + ") while reading an unidentified attribute."); attribute = new Unidentified(type, ""); attribute.nameIndex = nameIndex; attribute.readExternal(in); }//if// else { String name = constantUtf8.getValue(); if(name.equalsIgnoreCase("SourceFile")) { attribute = new SourceFile(type); }//if// else if(name.equalsIgnoreCase("Code")) { attribute = new Code(type); }//else if// else if(name.equalsIgnoreCase("Exceptions")) { attribute = new ExceptionIndexes(type); }//else if// else if(name.equalsIgnoreCase("LineNumberTable")) { attribute = new LineNumberTable(type); }//else if// else if(name.equalsIgnoreCase("LocalVariableTable")) { attribute = new LocalVariableTable(type); }//else if// else if(name.equalsIgnoreCase("InnerClasses")) { attribute = new InnerClasses(type); }//else if// else if(name.equalsIgnoreCase("ConstantValue")) { attribute = new ConstantValue(type); }//else if// else if(name.equalsIgnoreCase("Synthetic")) { attribute = new Synthetic(type); }//else if// else { attribute = new Unidentified(type, name); }//else// attribute.nameIndex = nameIndex; attribute.readExternal(in); }//else// return attribute; }//readAttribute()// /** * 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 java.io.IOException, ClassNotFoundException { if(this.nameIndex == -1) { //There is usually no need to read the name index since it is read in the readAttribute(Type, ObjectInput) method.// nameIndex = in.readShort(); }//if// //Note: We leave it to the attribute to read the length of the attribute because some will require this info and most will ignore it.// }//readExternal()// /** * Sets the index of the attribute's name in the type's constant pool. * @param nameIndex The index of the attribute name. */ public void setNameIndex(short nameIndex) { this.nameIndex = nameIndex; }//setNameIndex()// /** * 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 java.io.IOException { short nameIndex = getType().getConstantIndex(new ConstantUtf8(getType(), getDefaultName())); //Write the constant index referenceing the attribute name.// out.writeShort(nameIndex); //Write size in bytes of the attribute.// out.writeInt(getSize()); }//writeExternal()// }//CodeAttribute//