| 1 16 17 package org.cojen.classfile.attribute; 18 19 import java.io.DataInput ; 20 import java.io.DataOutput ; 21 import java.io.IOException ; 22 import java.util.Collections ; 23 import java.util.Iterator ; 24 import java.util.LinkedHashMap ; 25 import java.util.Map ; 26 import org.cojen.classfile.ConstantInfo; 27 import org.cojen.classfile.ConstantPool; 28 import org.cojen.classfile.TypeDesc; 29 import org.cojen.classfile.constant.ConstantClassInfo; 30 import org.cojen.classfile.constant.ConstantDoubleInfo; 31 import org.cojen.classfile.constant.ConstantFloatInfo; 32 import org.cojen.classfile.constant.ConstantIntegerInfo; 33 import org.cojen.classfile.constant.ConstantLongInfo; 34 import org.cojen.classfile.constant.ConstantUTFInfo; 35 36 41 public class Annotation { 42 43 44 public static final char MEMBER_TAG_BOOLEAN = 'Z'; 45 46 47 public static final char MEMBER_TAG_BYTE = 'B'; 48 49 50 public static final char MEMBER_TAG_SHORT = 'S'; 51 52 53 public static final char MEMBER_TAG_CHAR = 'C'; 54 55 56 public static final char MEMBER_TAG_INT = 'I'; 57 58 59 public static final char MEMBER_TAG_LONG = 'J'; 60 61 62 public static final char MEMBER_TAG_FLOAT = 'F'; 63 64 65 public static final char MEMBER_TAG_DOUBLE = 'D'; 66 67 68 public static final char MEMBER_TAG_STRING = 's'; 69 70 71 public static final char MEMBER_TAG_CLASS = 'c'; 72 73 74 public static final char MEMBER_TAG_ENUM = 'e'; 75 76 77 public static final char MEMBER_TAG_ARRAY = '['; 78 79 80 public static final char MEMBER_TAG_ANNOTATION = '@'; 81 82 private final ConstantPool mCp; 83 private ConstantUTFInfo mType; 84 private final Map mMemberValues; 85 86 public Annotation(ConstantPool cp) { 87 mCp = cp; 88 mMemberValues = new LinkedHashMap (2); 89 } 90 91 public Annotation(ConstantPool cp, DataInput din) throws IOException { 92 mCp = cp; 93 mType = (ConstantUTFInfo)cp.getConstant(din.readUnsignedShort()); 94 95 int memberCount = din.readUnsignedShort(); 96 mMemberValues = new LinkedHashMap (memberCount); 97 98 for (int i=0; i<memberCount; i++) { 99 String name = ((ConstantUTFInfo)cp.getConstant(din.readUnsignedShort())).getValue(); 100 mMemberValues.put(name, new MemberValue(cp, din)); 101 } 102 } 103 104 public ConstantUTFInfo getTypeConstant() { 105 return mType; 106 } 107 108 public TypeDesc getType() { 109 return TypeDesc.forDescriptor(mType.getValue()); 110 } 111 112 public void setTypeConstant(ConstantUTFInfo type) { 113 mType = type; 114 } 115 116 public void setType(TypeDesc type) { 117 setTypeConstant(mCp.addConstantUTF(type.getDescriptor())); 118 } 119 120 124 public Map getMemberValues() { 125 return Collections.unmodifiableMap(mMemberValues); 126 } 127 128 public void putMemberValue(String name, MemberValue mv) { 129 mCp.addConstantUTF(name); 130 mMemberValues.put(name, mv); 131 } 132 133 public void putMemberValue(String name, boolean value) { 134 mCp.addConstantUTF(name); 135 mMemberValues.put(name, makeMemberValue(value)); 136 } 137 138 public void putMemberValue(String name, byte value) { 139 mCp.addConstantUTF(name); 140 mMemberValues.put(name, makeMemberValue(value)); 141 } 142 143 public void putMemberValue(String name, short value) { 144 mCp.addConstantUTF(name); 145 mMemberValues.put(name, makeMemberValue(value)); 146 } 147 148 public void putMemberValue(String name, char value) { 149 mCp.addConstantUTF(name); 150 mMemberValues.put(name, makeMemberValue(value)); 151 } 152 153 public void putMemberValue(String name, int value) { 154 mCp.addConstantUTF(name); 155 mMemberValues.put(name, makeMemberValue(value)); 156 } 157 158 public void putMemberValue(String name, long value) { 159 mCp.addConstantUTF(name); 160 mMemberValues.put(name, makeMemberValue(value)); 161 } 162 163 public void putMemberValue(String name, float value) { 164 mCp.addConstantUTF(name); 165 mMemberValues.put(name, makeMemberValue(value)); 166 } 167 168 public void putMemberValue(String name, double value) { 169 mCp.addConstantUTF(name); 170 mMemberValues.put(name, makeMemberValue(value)); 171 } 172 173 public void putMemberValue(String name, String value) { 174 mCp.addConstantUTF(name); 175 mMemberValues.put(name, makeMemberValue(value)); 176 } 177 178 public void putMemberValue(String name, TypeDesc value) { 179 mCp.addConstantUTF(name); 180 mMemberValues.put(name, makeMemberValue(value)); 181 } 182 183 public void putMemberValue(String name, MemberValue[] value) { 184 mCp.addConstantUTF(name); 185 mMemberValues.put(name, makeMemberValue(value)); 186 } 187 188 public void putMemberValue(String name, TypeDesc enumType, String enumName) { 189 mCp.addConstantUTF(name); 190 mMemberValues.put(name, makeMemberValue(enumType, enumName)); 191 } 192 193 196 public void putMemberValue(String name, Annotation value) { 197 mCp.addConstantUTF(name); 198 mMemberValues.put(name, makeMemberValue(value)); 199 } 200 201 public MemberValue makeMemberValue(boolean value) { 202 return new MemberValue(MEMBER_TAG_BOOLEAN, mCp.addConstantInteger(value ? 1 : 0)); 203 } 204 205 public MemberValue makeMemberValue(byte value) { 206 return new MemberValue(MEMBER_TAG_BYTE, mCp.addConstantInteger(value)); 207 } 208 209 public MemberValue makeMemberValue(short value) { 210 return new MemberValue(MEMBER_TAG_SHORT, mCp.addConstantInteger(value)); 211 } 212 213 public MemberValue makeMemberValue(char value) { 214 return new MemberValue(MEMBER_TAG_CHAR, mCp.addConstantInteger(value)); 215 } 216 217 public MemberValue makeMemberValue(int value) { 218 return new MemberValue(MEMBER_TAG_INT, mCp.addConstantInteger(value)); 219 } 220 221 public MemberValue makeMemberValue(long value) { 222 return new MemberValue(MEMBER_TAG_LONG, mCp.addConstantLong(value)); 223 } 224 225 public MemberValue makeMemberValue(float value) { 226 return new MemberValue(MEMBER_TAG_FLOAT, mCp.addConstantFloat(value)); 227 } 228 229 public MemberValue makeMemberValue(double value) { 230 return new MemberValue(MEMBER_TAG_DOUBLE, mCp.addConstantDouble(value)); 231 } 232 233 public MemberValue makeMemberValue(String value) { 234 return new MemberValue(MEMBER_TAG_STRING, mCp.addConstantUTF(value)); 235 } 236 237 public MemberValue makeMemberValue(TypeDesc value) { 238 return new MemberValue(MEMBER_TAG_CLASS, mCp.addConstantUTF(value.getDescriptor())); 239 } 240 241 public MemberValue makeMemberValue(TypeDesc enumType, String enumName) { 242 return new MemberValue(MEMBER_TAG_ENUM, 243 new EnumConstValue(mCp.addConstantUTF(enumType.getDescriptor()), 244 mCp.addConstantUTF(enumName))); 245 } 246 247 public MemberValue makeMemberValue(MemberValue[] value) { 248 return new MemberValue(MEMBER_TAG_ARRAY, value); 249 } 250 251 254 public MemberValue makeMemberValue(Annotation value) { 255 return new MemberValue(MEMBER_TAG_ANNOTATION, value); 256 } 257 258 public Annotation makeAnnotation() { 259 return new Annotation(mCp); 260 } 261 262 public int getLength() { 263 int length = 4; 264 Iterator it = mMemberValues.values().iterator(); 265 while (it.hasNext()) { 266 length += 2 + ((MemberValue)it.next()).getLength(); 267 } 268 return length; 269 } 270 271 public void writeTo(DataOutput dout) throws IOException { 272 dout.writeShort(mType.getIndex()); 273 int memberCount = mMemberValues.size(); 274 dout.writeShort(memberCount); 275 Iterator it = mMemberValues.entrySet().iterator(); 276 while (it.hasNext()) { 277 Map.Entry entry = (Map.Entry )it.next(); 278 String name = (String )entry.getKey(); 279 MemberValue value = (MemberValue)entry.getValue(); 280 dout.writeShort(mCp.addConstantUTF(name).getIndex()); 281 value.writeTo(dout); 282 } 283 } 284 285 public static class MemberValue { 286 private final char mTag; 287 private final Object mValue; 288 289 public MemberValue(char tag, Object value) { 290 switch (mTag = tag) { 291 default: 292 throw new IllegalArgumentException  293 ("Illegal annotation member value tag: " + mTag); 294 295 case MEMBER_TAG_BOOLEAN: 296 case MEMBER_TAG_BYTE: 297 case MEMBER_TAG_SHORT: 298 case MEMBER_TAG_CHAR: 299 case MEMBER_TAG_INT: 300 if (value instanceof ConstantIntegerInfo) { 301 mValue = value; 302 } else { 303 throw new IllegalArgumentException ("Value must be ConstantIntegerInfo"); 304 } 305 break; 306 307 case MEMBER_TAG_LONG: 308 if (value instanceof ConstantLongInfo) { 309 mValue = value; 310 } else { 311 throw new IllegalArgumentException ("Value must be ConstantLongInfo"); 312 } 313 break; 314 315 case MEMBER_TAG_FLOAT: 316 if (value instanceof ConstantFloatInfo) { 317 mValue = value; 318 } else { 319 throw new IllegalArgumentException ("Value must be ConstantFloatInfo"); 320 } 321 break; 322 323 case MEMBER_TAG_DOUBLE: 324 if (value instanceof ConstantDoubleInfo) { 325 mValue = value; 326 } else { 327 throw new IllegalArgumentException ("Value must be ConstantDoubleInfo"); 328 } 329 break; 330 331 case MEMBER_TAG_CLASS: 332 if (value instanceof ConstantUTFInfo) { 333 mValue = value; 334 } else { 335 throw new IllegalArgumentException ("Value must be ConstantUTFInfo"); 336 } 337 break; 338 339 case MEMBER_TAG_STRING: 340 if (value instanceof ConstantUTFInfo) { 341 mValue = value; 342 } else { 343 throw new IllegalArgumentException ("Value must be ConstantUTFInfo"); 344 } 345 break; 346 347 case MEMBER_TAG_ENUM: 348 if (value instanceof EnumConstValue) { 349 mValue = value; 350 } else { 351 throw new IllegalArgumentException ("Value must be EnumConstValue"); 352 } 353 break; 354 355 case MEMBER_TAG_ARRAY: 356 if (value instanceof MemberValue[]) { 357 mValue = value; 358 } else { 359 throw new IllegalArgumentException ("Value must be MemberValue[]"); 360 } 361 break; 362 363 case MEMBER_TAG_ANNOTATION: 364 if (value instanceof Annotation) { 365 mValue = value; 366 } else { 367 throw new IllegalArgumentException ("Value must be Annotation"); 368 } 369 break; 370 } 371 } 372 373 public MemberValue(ConstantPool cp, DataInput din) throws IOException { 374 switch (mTag = (char)din.readUnsignedByte()) { 375 default: 376 throw new IllegalStateException  377 ("Illegal annotation member value tag: " + mTag); 378 379 case MEMBER_TAG_BOOLEAN: 380 case MEMBER_TAG_BYTE: 381 case MEMBER_TAG_SHORT: 382 case MEMBER_TAG_CHAR: 383 case MEMBER_TAG_INT: 384 case MEMBER_TAG_LONG: 385 case MEMBER_TAG_FLOAT: 386 case MEMBER_TAG_DOUBLE: 387 case MEMBER_TAG_CLASS: 388 case MEMBER_TAG_STRING: 389 mValue = cp.getConstant(din.readUnsignedShort()); 390 break; 391 392 case MEMBER_TAG_ENUM: 393 mValue = new EnumConstValue(cp, din); 394 break; 395 396 case MEMBER_TAG_ARRAY: 397 int length = din.readUnsignedShort(); 398 MemberValue[] values = new MemberValue[length]; 399 for (int i=0; i<length; i++) { 400 values[i] = new MemberValue(cp, din); 401 } 402 mValue = values; 403 break; 404 405 case MEMBER_TAG_ANNOTATION: 406 mValue = new Annotation(cp, din); 407 break; 408 } 409 } 410 411 public char getTag() { 412 return mTag; 413 } 414 415 public Object getValue() { 416 return mValue; 417 } 418 419 public int getLength() { 420 switch (mTag) { 421 default: 422 return 1; 423 424 case MEMBER_TAG_BOOLEAN: 425 case MEMBER_TAG_BYTE: 426 case MEMBER_TAG_SHORT: 427 case MEMBER_TAG_CHAR: 428 case MEMBER_TAG_INT: 429 case MEMBER_TAG_LONG: 430 case MEMBER_TAG_FLOAT: 431 case MEMBER_TAG_DOUBLE: 432 case MEMBER_TAG_CLASS: 433 case MEMBER_TAG_STRING: 434 return 3; 435 436 case MEMBER_TAG_ENUM: 437 return 1 + ((EnumConstValue)mValue).getLength(); 438 439 case MEMBER_TAG_ARRAY: { 440 MemberValue[] values = (MemberValue[])mValue; 441 int length = 3; 442 for (int i=0; i<values.length; i++) { 443 length += values[i].getLength(); 444 } 445 return length; 446 } 447 448 case MEMBER_TAG_ANNOTATION: 449 return 1 + ((Annotation)mValue).getLength(); 450 } 451 } 452 453 public void writeTo(DataOutput dout) throws IOException { 454 dout.writeByte(mTag); 455 456 switch (mTag) { 457 case MEMBER_TAG_BOOLEAN: 458 case MEMBER_TAG_BYTE: 459 case MEMBER_TAG_SHORT: 460 case MEMBER_TAG_CHAR: 461 case MEMBER_TAG_INT: 462 case MEMBER_TAG_LONG: 463 case MEMBER_TAG_FLOAT: 464 case MEMBER_TAG_DOUBLE: 465 case MEMBER_TAG_CLASS: 466 case MEMBER_TAG_STRING: 467 dout.writeShort(((ConstantInfo)mValue).getIndex()); 468 break; 469 470 case MEMBER_TAG_ENUM: 471 ((EnumConstValue)mValue).writeTo(dout); 472 break; 473 474 case MEMBER_TAG_ARRAY: 475 MemberValue[] values = (MemberValue[])mValue; 476 dout.writeShort(values.length); 477 for (int i=0; i<values.length; i++) { 478 values[i].writeTo(dout); 479 } 480 break; 481 482 case MEMBER_TAG_ANNOTATION: 483 ((Annotation)mValue).writeTo(dout); 484 break; 485 } 486 } 487 } 488 489 public static class EnumConstValue { 490 private final ConstantUTFInfo mTypeName; 491 private final ConstantUTFInfo mConstName; 492 493 public EnumConstValue(ConstantUTFInfo typeName, ConstantUTFInfo constName) { 494 mTypeName = typeName; 495 mConstName = constName; 496 } 497 498 public EnumConstValue(ConstantPool cp, DataInput din) throws IOException { 499 mTypeName = (ConstantUTFInfo)cp.getConstant(din.readUnsignedShort()); 500 mConstName = (ConstantUTFInfo)cp.getConstant(din.readUnsignedShort()); 501 } 502 503 public ConstantUTFInfo getTypeName() { 504 return mTypeName; 505 } 506 507 public ConstantUTFInfo getConstName() { 508 return mConstName; 509 } 510 511 public int getLength() { 512 return 4; 513 } 514 515 public void writeTo(DataOutput dout) throws IOException { 516 dout.writeShort(mTypeName.getIndex()); 517 dout.writeShort(mConstName.getIndex()); 518 } 519 } 520 } 521 | Popular Tags |