1 16 17 package org.cojen.classfile.attribute; 18 19 import java.util.ArrayList ; 20 import java.util.List ; 21 import java.io.DataInput ; 22 import java.io.DataOutput ; 23 import java.io.IOException ; 24 import org.cojen.classfile.Attribute; 25 import org.cojen.classfile.AttributeFactory; 26 import org.cojen.classfile.CodeBuffer; 27 import org.cojen.classfile.ConstantPool; 28 import org.cojen.classfile.ExceptionHandler; 29 import org.cojen.classfile.LocalVariable; 30 import org.cojen.classfile.Location; 31 32 42 public class CodeAttr extends Attribute { 43 44 private CodeBuffer mCodeBuffer; 45 private List mAttributes = new ArrayList (2); 46 47 private LineNumberTableAttr mLineNumberTable; 48 private LocalVariableTableAttr mLocalVariableTable; 49 50 private LineNumberTableAttr mOldLineNumberTable; 51 private LocalVariableTableAttr mOldLocalVariableTable; 52 53 public CodeAttr(ConstantPool cp) { 54 super(cp, CODE); 55 } 56 57 public CodeAttr(ConstantPool cp, String name) { 58 super(cp, name); 59 } 60 61 public CodeAttr(ConstantPool cp, String name, int length, 62 DataInput din, AttributeFactory attrFactory) 63 throws IOException 64 { 65 super(cp, name); 66 67 final int maxStackDepth = din.readUnsignedShort(); 68 final int maxLocals = din.readUnsignedShort(); 69 70 final byte[] byteCodes = new byte[din.readInt()]; 71 din.readFully(byteCodes); 72 73 int exceptionHandlerCount = din.readUnsignedShort(); 74 final ExceptionHandler[] handlers = 75 new ExceptionHandler[exceptionHandlerCount]; 76 77 for (int i=0; i<exceptionHandlerCount; i++) { 78 handlers[i] = ExceptionHandler.readFrom(cp, din); 79 } 80 81 mCodeBuffer = new CodeBuffer() { 82 public int getMaxStackDepth() { 83 return maxStackDepth; 84 } 85 86 public int getMaxLocals() { 87 return maxLocals; 88 } 89 90 public byte[] getByteCodes() { 91 return (byte[])byteCodes.clone(); 92 } 93 94 public ExceptionHandler[] getExceptionHandlers() { 95 return (ExceptionHandler[])handlers.clone(); 96 } 97 }; 98 99 int attributeCount = din.readUnsignedShort(); 100 for (int i=0; i<attributeCount; i++) { 101 addAttribute(Attribute.readFrom(cp, din, attrFactory)); 102 } 103 } 104 105 108 public CodeBuffer getCodeBuffer() { 109 return mCodeBuffer; 110 } 111 112 116 public void setCodeBuffer(CodeBuffer code) { 117 mCodeBuffer = code; 118 mOldLineNumberTable = mLineNumberTable; 119 mOldLocalVariableTable = mLocalVariableTable; 120 mAttributes.remove(mLineNumberTable); 121 mAttributes.remove(mLocalVariableTable); 122 mLineNumberTable = null; 123 mLocalVariableTable = null; 124 } 125 126 132 public int getLineNumber(Location start) { 133 LineNumberTableAttr table = mOldLineNumberTable; 134 if (table == null) { 135 table = mLineNumberTable; 136 } 137 138 if (table == null || start.getLocation() < 0) { 139 return -1; 140 } else { 141 return table.getLineNumber(start); 142 } 143 } 144 145 149 public void mapLineNumber(Location start, int line_number) { 150 if (mLineNumberTable == null) { 151 addAttribute(new LineNumberTableAttr(getConstantPool())); 152 } 153 mLineNumberTable.addEntry(start, line_number); 154 } 155 156 162 public void localVariableUse(LocalVariable localVar) { 163 if (mLocalVariableTable == null) { 164 addAttribute(new LocalVariableTableAttr(getConstantPool())); 165 } 166 mLocalVariableTable.addEntry(localVar); 167 } 168 169 public void addAttribute(Attribute attr) { 170 if (attr instanceof LineNumberTableAttr) { 171 if (mLineNumberTable != null) { 172 mAttributes.remove(mLineNumberTable); 173 } 174 mLineNumberTable = (LineNumberTableAttr)attr; 175 } else if (attr instanceof LocalVariableTableAttr) { 176 if (mLocalVariableTable != null) { 177 mAttributes.remove(mLocalVariableTable); 178 } 179 mLocalVariableTable = (LocalVariableTableAttr)attr; 180 } 181 182 mAttributes.add(attr); 183 } 184 185 public Attribute[] getAttributes() { 186 Attribute[] attrs = new Attribute[mAttributes.size()]; 187 return (Attribute[])mAttributes.toArray(attrs); 188 } 189 190 193 public int getLength() { 194 int length = 12; 195 196 if (mCodeBuffer != null) { 197 length += mCodeBuffer.getByteCodes().length; 198 ExceptionHandler[] handlers = mCodeBuffer.getExceptionHandlers(); 199 if (handlers != null) { 200 length += 8 * handlers.length; 201 } 202 } 203 204 int size = mAttributes.size(); 205 for (int i=0; i<size; i++) { 206 length += ((Attribute)mAttributes.get(i)).getLength(); 207 length += 6; } 209 210 return length; 211 } 212 213 public void writeDataTo(DataOutput dout) throws IOException { 214 if (mCodeBuffer == null) { 215 throw new IllegalStateException ("CodeAttr has no CodeBuffer set"); 216 } 217 218 ExceptionHandler[] handlers = mCodeBuffer.getExceptionHandlers(); 219 220 dout.writeShort(mCodeBuffer.getMaxStackDepth()); 221 dout.writeShort(mCodeBuffer.getMaxLocals()); 222 223 byte[] byteCodes = mCodeBuffer.getByteCodes(); 224 dout.writeInt(byteCodes.length); 225 dout.write(byteCodes); 226 227 if (handlers != null) { 228 int exceptionHandlerCount = handlers.length; 229 dout.writeShort(exceptionHandlerCount); 230 231 for (int i=0; i<exceptionHandlerCount; i++) { 232 handlers[i].writeTo(dout); 233 } 234 } else { 235 dout.writeShort(0); 236 } 237 238 int size = mAttributes.size(); 239 dout.writeShort(size); 240 for (int i=0; i<size; i++) { 241 Attribute attr = (Attribute)mAttributes.get(i); 242 attr.writeTo(dout); 243 } 244 245 mOldLineNumberTable = null; 246 mOldLocalVariableTable = null; 247 } 248 } 249 | Popular Tags |