diff --git a/src/de/inetsoftware/classparser/Annotations.java b/src/de/inetsoftware/classparser/Annotations.java index c17a6d2..6773b23 100644 --- a/src/de/inetsoftware/classparser/Annotations.java +++ b/src/de/inetsoftware/classparser/Annotations.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2019 Volker Berlin (i-net software) + * Copyright 2017 - 2021 Volker Berlin (i-net software) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,39 +36,59 @@ public class Annotations { * if an I/O error occurs * @return the map of the annotation names to its attributes */ - static Map> read( DataInputStream input, ConstantPool constantPool ) throws IOException { - Map> annotations = new HashMap<>(); + static Map> read( DataInputStream input, ConstantPool constantPool ) throws IOException { + Map> annotations = new HashMap<>(); int count = input.readUnsignedShort(); for( int i = 0; i < count; i++ ) { String className = (String)constantPool.get( input.readUnsignedShort() ); className = className.substring( 1, className.length() - 1 ).replace( '/', '.' ); // has the form: "Lcom/package/ClassName;" - Map valuePairs = new HashMap<>(); + Map valuePairs = new HashMap<>(); annotations.put( className, valuePairs ); int valuePairCount = input.readUnsignedShort(); for( int p = 0; p < valuePairCount; p++ ) { String key = (String)constantPool.get( input.readUnsignedShort() ); - int type = input.readUnsignedByte(); - Object value; - switch( type ) { - case 'B': - case 'C': - case 'D': - case 'F': - case 'I': - case 'J': - case 'S': - case 'Z': - case 's': - value = constantPool.get( input.readUnsignedShort() ); - break; - default: - // TODO other possible values for type: e c @ [ - throw new IOException( "Unknown annotation value type pool type: " + type ); - } + Object value = readElementValue( input, constantPool ); valuePairs.put( key, value ); } } return annotations; } + + /** + * Read a single element value + * + * @param input + * the stream of the RuntimeInvisibleAnnotations attribute + * @param constantPool + * the ConstantPool of the class + * @return the value + * @throws IOException + * if an I/O error occurs + */ + private static Object readElementValue( DataInputStream input, ConstantPool constantPool ) throws IOException { + int type = input.readUnsignedByte(); + switch( type ) { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + case 's': + return constantPool.get( input.readUnsignedShort() ); + case '[': + int count = input.readUnsignedShort(); + Object[] values = new Object[count]; + for( int i = 0; i < count; i++ ) { + values[i] = readElementValue( input, constantPool ); + } + return values; + default: + // TODO other possible values for type: e c @ + throw new IOException( "Unknown annotation value type pool type: " + type ); + } + } }