1 11 package org.eclipse.jdt.internal.compiler.classfmt; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.ast.Annotation; 15 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; 16 import org.eclipse.jdt.internal.compiler.env.*; 17 import org.eclipse.jdt.internal.compiler.impl.*; 18 import org.eclipse.jdt.internal.compiler.lookup.TagBits; 19 20 public class AnnotationInfo extends ClassFileStruct implements IBinaryAnnotation { 21 22 private char[] typename; 23 27 private ElementValuePairInfo[] pairs; 28 29 long standardAnnotationTagBits = 0; 30 int readOffset = 0; 31 32 static Object [] EmptyValueArray = new Object [0]; 33 34 AnnotationInfo(byte[] classFileBytes, int[] contantPoolOffsets, int offset) { 35 super(classFileBytes, contantPoolOffsets, offset); 36 } 37 42 AnnotationInfo(byte[] classFileBytes, int[] contantPoolOffsets, int offset, boolean runtimeVisible, boolean populate) { 43 this(classFileBytes, contantPoolOffsets, offset); 44 if (populate) 45 decodeAnnotation(); 46 else 47 this.readOffset = scanAnnotation(0, runtimeVisible, true); 48 } 49 private void decodeAnnotation() { 50 this.readOffset = 0; 51 int utf8Offset = this.constantPoolOffsets[u2At(0)] - structOffset; 52 this.typename = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 53 int numberOfPairs = u2At(2); 54 this.readOffset += 4; 56 this.pairs = numberOfPairs == 0 ? ElementValuePairInfo.NoMembers : new ElementValuePairInfo[numberOfPairs]; 57 for (int i = 0; i < numberOfPairs; i++) { 58 utf8Offset = this.constantPoolOffsets[u2At(this.readOffset)] - structOffset; 60 char[] membername = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 61 this.readOffset += 2; 62 Object value = decodeDefaultValue(); 63 this.pairs[i] = new ElementValuePairInfo(membername, value); 64 } 65 } 66 Object decodeDefaultValue() { 67 Object value = null; 68 int tag = u1At(this.readOffset); 70 this.readOffset++; 71 int constValueOffset = -1; 72 switch (tag) { 73 case 'Z': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 75 value = BooleanConstant.fromValue(i4At(constValueOffset + 1) == 1); 76 this.readOffset += 2; 77 break; 78 case 'I': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 80 value = IntConstant.fromValue(i4At(constValueOffset + 1)); 81 this.readOffset += 2; 82 break; 83 case 'C': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 85 value = CharConstant.fromValue((char) i4At(constValueOffset + 1)); 86 this.readOffset += 2; 87 break; 88 case 'B': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 90 value = ByteConstant.fromValue((byte) i4At(constValueOffset + 1)); 91 this.readOffset += 2; 92 break; 93 case 'S': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 95 value = ShortConstant.fromValue((short) i4At(constValueOffset + 1)); 96 this.readOffset += 2; 97 break; 98 case 'D': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 100 value = DoubleConstant.fromValue(doubleAt(constValueOffset + 1)); 101 this.readOffset += 2; 102 break; 103 case 'F': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 105 value = FloatConstant.fromValue(floatAt(constValueOffset + 1)); 106 this.readOffset += 2; 107 break; 108 case 'J': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 110 value = LongConstant.fromValue(i8At(constValueOffset + 1)); 111 this.readOffset += 2; 112 break; 113 case 's': constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 115 value = StringConstant.fromValue(String.valueOf(utf8At(constValueOffset + 3, u2At(constValueOffset + 1)))); 116 this.readOffset += 2; 117 break; 118 case 'e': 119 constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 120 char[] typeName = utf8At(constValueOffset + 3, u2At(constValueOffset + 1)); 121 this.readOffset += 2; 122 constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 123 char[] constName = utf8At(constValueOffset + 3, u2At(constValueOffset + 1)); 124 this.readOffset += 2; 125 value = new EnumConstantSignature(typeName, constName); 126 break; 127 case 'c': 128 constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset; 129 char[] className = utf8At(constValueOffset + 3, u2At(constValueOffset + 1)); 130 value = new ClassSignature(className); 131 this.readOffset += 2; 132 break; 133 case '@': 134 value = new AnnotationInfo(this.reference, this.constantPoolOffsets, this.readOffset + this.structOffset, false, true); 135 this.readOffset += ((AnnotationInfo) value).readOffset; 136 break; 137 case '[': 138 int numberOfValues = u2At(this.readOffset); 139 this.readOffset += 2; 140 if (numberOfValues == 0) { 141 value = EmptyValueArray; 142 } else { 143 Object [] arrayElements = new Object [numberOfValues]; 144 value = arrayElements; 145 for (int i = 0; i < numberOfValues; i++) 146 arrayElements[i] = decodeDefaultValue(); 147 } 148 break; 149 default: 150 throw new IllegalStateException ("Unrecognized tag " + (char) tag); } 152 return value; 153 } 154 public IBinaryElementValuePair[] getElementValuePairs() { 155 if (this.pairs == null) 156 initialize(); 157 return this.pairs; 158 } 159 public char[] getTypeName() { 160 return this.typename; 161 } 162 void initialize() { 163 if (this.pairs == null) 164 decodeAnnotation(); 165 } 166 private int readRetentionPolicy(int offset) { 167 int currentOffset = offset; 168 int tag = u1At(currentOffset); 169 currentOffset++; 170 switch (tag) { 171 case 'e': 172 int utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - structOffset; 173 char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 174 currentOffset += 2; 175 if (typeName.length == 38 && CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_RETENTIONPOLICY)) { 176 utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - structOffset; 177 char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 178 this.standardAnnotationTagBits |= Annotation.getRetentionPolicy(constName); 179 } 180 currentOffset += 2; 181 break; 182 case 'B': 183 case 'C': 184 case 'D': 185 case 'F': 186 case 'I': 187 case 'J': 188 case 'S': 189 case 'Z': 190 case 's': 191 case 'c': 192 currentOffset += 2; 193 break; 194 case '@': 195 currentOffset = scanAnnotation(currentOffset, false, false); 198 break; 199 case '[': 200 int numberOfValues = u2At(currentOffset); 201 currentOffset += 2; 202 for (int i = 0; i < numberOfValues; i++) 203 currentOffset = scanElementValue(currentOffset); 204 break; 205 default: 206 throw new IllegalStateException (); 207 } 208 return currentOffset; 209 } 210 private int readTargetValue(int offset) { 211 int currentOffset = offset; 212 int tag = u1At(currentOffset); 213 currentOffset++; 214 switch (tag) { 215 case 'e': 216 int utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - structOffset; 217 char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 218 currentOffset += 2; 219 if (typeName.length == 34 && CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_ELEMENTTYPE)) { 220 utf8Offset = this.constantPoolOffsets[u2At(currentOffset)] - structOffset; 221 char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 222 this.standardAnnotationTagBits |= Annotation.getTargetElementType(constName); 223 } 224 currentOffset += 2; 225 break; 226 case 'B': 227 case 'C': 228 case 'D': 229 case 'F': 230 case 'I': 231 case 'J': 232 case 'S': 233 case 'Z': 234 case 's': 235 case 'c': 236 currentOffset += 2; 237 break; 238 case '@': 239 currentOffset = scanAnnotation(currentOffset, false, false); 242 break; 243 case '[': 244 int numberOfValues = u2At(currentOffset); 245 currentOffset += 2; 246 if (numberOfValues == 0) { 247 this.standardAnnotationTagBits |= TagBits.AnnotationTarget; 248 } else { 249 for (int i = 0; i < numberOfValues; i++) 250 currentOffset = readTargetValue(currentOffset); 251 } 252 break; 253 default: 254 throw new IllegalStateException (); 255 } 256 return currentOffset; 257 } 258 274 private int scanAnnotation(int offset, boolean expectRuntimeVisibleAnno, boolean toplevel) { 275 int currentOffset = offset; 276 int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset; 277 char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 278 if (toplevel) 279 this.typename = typeName; 280 int numberOfPairs = u2At(offset + 2); 281 currentOffset += 4; 283 if (expectRuntimeVisibleAnno && toplevel) { 284 switch (typeName.length) { 285 case 22: 286 if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_DEPRECATED)) { 287 this.standardAnnotationTagBits |= TagBits.AnnotationDeprecated; 288 return currentOffset; 289 } 290 break; 291 case 29: 292 if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_TARGET)) { 293 currentOffset += 2; 294 return readTargetValue(currentOffset); 295 } 296 break; 297 case 33: 298 if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_DOCUMENTED)) { 299 this.standardAnnotationTagBits |= TagBits.AnnotationDocumented; 300 return currentOffset; 301 } 302 break; 303 case 32: 304 if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_RETENTION)) { 305 currentOffset += 2; 306 return readRetentionPolicy(currentOffset); 307 } 308 if (CharOperation.equals(typeName, ConstantPool.JAVA_LANG_ANNOTATION_INHERITED)) { 309 this.standardAnnotationTagBits |= TagBits.AnnotationInherited; 310 return currentOffset; 311 } 312 break; 313 } 314 } 315 for (int i = 0; i < numberOfPairs; i++) { 316 currentOffset += 2; 318 currentOffset = scanElementValue(currentOffset); 319 } 320 return currentOffset; 321 } 322 327 private int scanElementValue(int offset) { 328 int currentOffset = offset; 329 int tag = u1At(currentOffset); 330 currentOffset++; 331 switch (tag) { 332 case 'B': 333 case 'C': 334 case 'D': 335 case 'F': 336 case 'I': 337 case 'J': 338 case 'S': 339 case 'Z': 340 case 's': 341 case 'c': 342 currentOffset += 2; 343 break; 344 case 'e': 345 currentOffset += 4; 346 break; 347 case '@': 348 currentOffset = scanAnnotation(currentOffset, false, false); 351 break; 352 case '[': 353 int numberOfValues = u2At(currentOffset); 354 currentOffset += 2; 355 for (int i = 0; i < numberOfValues; i++) 356 currentOffset = scanElementValue(currentOffset); 357 break; 358 default: 359 throw new IllegalStateException (); 360 } 361 return currentOffset; 362 } 363 public String toString() { 364 StringBuffer buffer = new StringBuffer (); 365 buffer.append('@'); 366 buffer.append(this.typename); 367 if (this.pairs != null) { 368 buffer.append('('); 369 buffer.append("\n\t"); for (int i = 0, len = this.pairs.length; i < len; i++) { 371 if (i > 0) 372 buffer.append(",\n\t"); buffer.append(this.pairs[i]); 374 } 375 buffer.append(')'); 376 } 377 return buffer.toString(); 378 } 379 } 380 | Popular Tags |