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 }