001 package edu.rice.cs.cunit.classFile.attributes; 002 003 import edu.rice.cs.cunit.classFile.ClassFileTools; 004 import edu.rice.cs.cunit.classFile.attributes.visitors.IAttributeVisitor; 005 import edu.rice.cs.cunit.classFile.code.instructions.LineNumberTable; 006 import edu.rice.cs.cunit.classFile.constantPool.*; 007 import edu.rice.cs.cunit.classFile.constantPool.visitors.ADefaultPoolInfoVisitor; 008 import edu.rice.cs.cunit.classFile.constantPool.visitors.CheckClassVisitor; 009 import edu.rice.cs.cunit.util.Types; 010 011 import java.util.ArrayList; 012 013 /** 014 * Represents the Exceptions attribute in a class file. 015 * 016 * @author Mathias Ricken 017 */ 018 public class ExceptionsAttributeInfo extends AAttributeInfo { 019 /** 020 * Constructor. 021 * 022 * @param name attribute name 023 * @param data attribute data 024 * @param cp constant pool 025 * 026 * @throws ClassFormatError 027 */ 028 public ExceptionsAttributeInfo(AUTFPoolInfo name, byte[] data, ConstantPool cp) throws ClassFormatError { 029 super(name, data, cp); 030 } 031 032 /** 033 * Return the number of checked exceptions. 034 * 035 * @return number of exceptions 036 * 037 * @throws ClassFormatError 038 */ 039 public int getExceptionCount() throws ClassFormatError { 040 int res = Types.ushortFromBytes(_data, 0); 041 assert(res <= 0xffff); 042 return res; 043 } 044 045 /** 046 * Return the checked exceptions list. 047 * 048 * @return list of checked exceptions. May contain null! 049 * 050 * @throws ClassFormatError 051 */ 052 public ClassPoolInfo[] getExceptions() throws ClassFormatError { 053 int count = getExceptionCount(); 054 assert(count <= 0xffff); 055 ClassPoolInfo[] cpi = new ClassPoolInfo[count]; 056 for(short i = 0; i < count; ++i) { 057 cpi[i] = _constantPool.get(Types.ushortFromBytes(_data, 2 + 2 * i)).execute(new ADefaultPoolInfoVisitor<ClassPoolInfo, Object>() { 058 public ClassPoolInfo defaultCase(APoolInfo host, Object o) { 059 throw new ClassFormatError("Checked exceptions list must contain class or empty items."); 060 } 061 062 public ClassPoolInfo classCase(ClassPoolInfo host, Object o) { 063 return host; 064 } 065 066 public ClassPoolInfo emptyCase(EmptyPoolInfo host, Object o) { 067 return null; 068 } 069 }, null); 070 } 071 return cpi; 072 } 073 074 /** 075 * Set the checked exceptions list. 076 * 077 * @param cpi list of checked exceptions 078 * 079 * @throws ClassFormatError 080 */ 081 public void setExceptions(ClassPoolInfo[] cpi) { 082 byte[] newData = new byte[2 + 2 * cpi.length]; 083 Types.bytesFromShort((short)cpi.length, newData, 0); 084 for(int i = 0; i < cpi.length; ++i) { 085 if (cpi[i] != null) { 086 Types.bytesFromShort( 087 _constantPool.indexOf(cpi[i].execute(CheckClassVisitor.singleton(), null)), 088 newData, 089 2 + 2 * i); 090 } 091 else { 092 newData[2 + 2 * i] = 0; 093 newData[3 + 2 * i] = 0; 094 } 095 } 096 setData(newData); 097 } 098 099 /** 100 * Return a human-readable version of this attribute. 101 * 102 * @return string 103 */ 104 public String toString() { 105 StringBuilder x = new StringBuilder(); 106 x.append(_name + " <" + getExceptionCount() + " exceptions { "); 107 boolean first = true; 108 for(ClassPoolInfo cpi : getExceptions()) { 109 if (first) { 110 first = false; 111 } 112 else { 113 x.append(", "); 114 } 115 if (cpi != null) { 116 x.append(ClassFileTools.getClassName(cpi.getName().toString())); 117 } 118 else { 119 x.append("empty item"); 120 } 121 } 122 x.append(" } >"); 123 return x.toString(); 124 } 125 126 /** 127 * Execute a visitor on this attribute. 128 * 129 * @param visitor visitor 130 * @param param visitor-specific parameter 131 * 132 * @return visitor-specific return value 133 */ 134 public <R, D> R execute(IAttributeVisitor<R, D> visitor, D param) { 135 return visitor.exceptionsCase(this, param); 136 } 137 138 /** 139 * Adjust program counter values contained in this attribute, starting at startPC, by adding deltaPC to them. 140 * 141 * @param startPC program counter to start at 142 * @param deltaPC change in program counter values 143 */ 144 public void adjustPC(int startPC, int deltaPC) { 145 // nothing to do 146 } 147 148 /** 149 * Translate the program counter values contained in this attribute from an old line number table to a new one. 150 * 151 * @param index critical point (insertion or deletion point) 152 * @param deltaIndex delta value to add to all old line numbers greater than the critical point 153 * @param oldLnt old line number table 154 * @param newLnt new line number table 155 */ 156 public void translatePC(int index, int deltaIndex, LineNumberTable oldLnt, LineNumberTable newLnt) { 157 // nothing to do 158 } 159 160 /** 161 * Creates and returns a copy of this object. 162 */ 163 public Object clone() throws CloneNotSupportedException { 164 return super.clone(); 165 } 166 167 /** 168 * Returns the name of the attribute as it appears in the class file. 169 * 170 * @return name of the attribute. 171 */ 172 public static String getAttributeName() { 173 return "Exceptions"; 174 } 175 }