001 package edu.rice.cs.cunit.classFile.attributes; 002 003 import edu.rice.cs.cunit.classFile.code.instructions.LineNumberTable; 004 import edu.rice.cs.cunit.classFile.constantPool.AUTFPoolInfo; 005 import edu.rice.cs.cunit.classFile.constantPool.ConstantPool; 006 import edu.rice.cs.cunit.util.Types; 007 008 import java.io.ByteArrayOutputStream; 009 import java.io.IOException; 010 import java.util.ArrayList; 011 import java.util.List; 012 013 /** 014 * Represents an abstract annotations attribute in a class file that can contain annotations for multiple entities, 015 * like for method parameters or local variables. 016 * 017 * @author Mathias Ricken 018 */ 019 public abstract class AMultipleAnnotationsAttributeInfo extends AAnnotationsAttributeInfo { 020 /** 021 * Creates a new abstract multiple annotations attribute. 022 * @param name name of attribute 023 * @param data data array 024 * @param cp constant pool 025 */ 026 public AMultipleAnnotationsAttributeInfo(AUTFPoolInfo name, byte data[], ConstantPool cp) { 027 super(name, data, cp); 028 } 029 030 /** 031 * Return the number of entities. 032 * 033 * @return number of entities 034 * 035 * @throws ClassFormatError 036 */ 037 public short getEntityCount() throws ClassFormatError { 038 return _data[0]; 039 } 040 041 /** 042 * Return the list of entity annotations arrays. 043 * 044 * @return list of arrays of entity annotations. 045 * 046 * @throws ClassFormatError 047 */ 048 public List<Annotation[]> getEntityAnnotations() throws ClassFormatError { 049 ArrayList<Annotation[]> entityAnnots = new ArrayList<Annotation[]>(); 050 int index = 1; 051 for(int entity=0; entity<getEntityCount(); ++entity) { 052 int count = Types.ushortFromBytes(_data, index); 053 assert(count <= 0xffff); 054 index += 2; 055 Annotation[] ann = new Annotation[count]; 056 for(short i = 0; i < count; ++i) { 057 ann[i] = new Annotation(_constantPool,_data,index); 058 index += ann[i].getSize(); 059 } 060 entityAnnots.add(ann); 061 } 062 return entityAnnots; 063 } 064 065 /** 066 * Set the entity annotations list. 067 * 068 * @param entityAnnots list of arrays of entity anotations 069 * 070 * @throws ClassFormatError 071 */ 072 public void setEntityAnnotations(List<Annotation[]> entityAnnots) throws IOException { 073 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 074 baos.write((byte)entityAnnots.size()); 075 for(Annotation[] ann: entityAnnots) { 076 baos.write(Types.bytesFromShort((short)ann.length)); 077 for(int i = 0; i < ann.length; ++i) { 078 ann[i].writeToByteArrayOutputStream(_constantPool,baos); 079 } 080 } 081 setData(baos.toByteArray()); 082 } 083 084 /** 085 * Return a human-readable version of this attribute. 086 * 087 * @return string 088 */ 089 public String toString() { 090 StringBuilder x = new StringBuilder(); 091 x.append(_name); 092 x.append(" <"); 093 x.append(getEntityCount()); 094 x.append(" "); 095 x.append(getEntityName()); 096 x.append("(s) { "); 097 boolean first = true; 098 for(Annotation[] entityAnnot : getEntityAnnotations()) { 099 if (first) { 100 first = false; 101 } 102 else { 103 x.append(", "); 104 } 105 boolean firstAnn = true; 106 for(Annotation ann : entityAnnot) { 107 if (firstAnn) { 108 firstAnn = false; 109 } 110 else { 111 x.append(", "); 112 } 113 x.append(ann.toString()); 114 } 115 x.append(" }"); 116 } 117 x.append(" } >"); 118 return x.toString(); 119 } 120 121 /** 122 * Return the name of the entity, e.g. "parameter" or "local variable". 123 * @return name of tne entity 124 */ 125 public abstract String getEntityName(); 126 127 /** 128 * Adjust program counter values contained in this attribute, starting at startPC, by adding deltaPC to them. 129 * 130 * @param startPC program counter to start at 131 * @param deltaPC change in program counter values 132 */ 133 public void adjustPC(int startPC, int deltaPC) { 134 // nothing to do 135 } 136 137 /** 138 * Translate the program counter values contained in this attribute from an old line number table to a new one. 139 * 140 * @param index critical point (insertion or deletion point) 141 * @param deltaIndex delta value to add to all old line numbers greater than the critical point 142 * @param oldLnt old line number table 143 * @param newLnt new line number table 144 */ 145 public void translatePC(int index, int deltaIndex, LineNumberTable oldLnt, LineNumberTable newLnt) { 146 // nothing to do 147 } 148 149 /** 150 * Creates and returns a copy of this object. 151 */ 152 public Object clone() throws CloneNotSupportedException { 153 return super.clone(); 154 } 155 }