1/* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import com.sun.tools.classfile.Annotation; 25import com.sun.tools.classfile.AnnotationDefault_attribute; 26import com.sun.tools.classfile.ClassFile; 27import com.sun.tools.classfile.ConstantPool; 28 29import java.util.Arrays; 30import java.util.HashMap; 31import java.util.Map; 32 33public class AnnotationDefaultVerifier { 34 35 private final Map<Integer, TestElementValue> verifiers; 36 37 public AnnotationDefaultVerifier() { 38 this.verifiers = new HashMap<>(); 39 verifiers.put((int) 'B', new TestIntegerElementValue()); 40 verifiers.put((int) 'C', new TestIntegerElementValue()); 41 verifiers.put((int) 'D', new TestDoubleElementValue()); 42 verifiers.put((int) 'F', new TestFloatElementValue()); 43 verifiers.put((int) 'I', new TestIntegerElementValue()); 44 verifiers.put((int) 'J', new TestLongElementValue()); 45 verifiers.put((int) 'S', new TestIntegerElementValue()); 46 verifiers.put((int) 'Z', new TestIntegerElementValue()); 47 verifiers.put((int) 's', new TestStringElementValue()); 48 verifiers.put((int) 'e', new TestEnumElementValue()); 49 verifiers.put((int) 'c', new TestClassElementValue()); 50 verifiers.put((int) '[', new TestArrayElementValue()); 51 verifiers.put((int) '@', new TestAnnotationElementValue()); 52 } 53 54 public void testLength(int tag, TestResult testResult, AnnotationDefault_attribute attr) { 55 verifiers.get(tag).testLength(testResult, attr); 56 } 57 58 public void testElementValue(int tag, TestResult testResult, ClassFile classFile, 59 Annotation.element_value element_value, String[] values) 60 throws ConstantPool.UnexpectedEntry, ConstantPool.InvalidIndex { 61 get(tag).testElementValue(testResult, classFile, element_value, values); 62 } 63 64 private TestElementValue get(int tag) { 65 TestElementValue ev = verifiers.get(tag); 66 if (ev == null) { 67 throw new IllegalArgumentException("Unknown tag : " + (char) tag); 68 } 69 return ev; 70 } 71 72 private abstract class TestElementValue { 73 public void testLength(TestResult testCase, AnnotationDefault_attribute attr) { 74 testCase.checkEquals(attr.attribute_length, 1 + attr.default_value.length(), 75 "attribute_length"); 76 } 77 78 public String[] getValues(String[] values, int index, int length) { 79 return Arrays.copyOfRange(values, index, index + length); 80 } 81 82 public int getLength() { 83 return 1; 84 } 85 86 public abstract void testElementValue( 87 TestResult testCase, 88 ClassFile classFile, 89 Annotation.element_value element_value, 90 String[] values) 91 throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry; 92 } 93 94 private class TestIntegerElementValue extends TestElementValue { 95 96 @Override 97 public void testElementValue( 98 TestResult testCase, 99 ClassFile classFile, 100 Annotation.element_value element_value, 101 String[] values) throws ConstantPool.InvalidIndex { 102 Annotation.Primitive_element_value ev = 103 (Annotation.Primitive_element_value) element_value; 104 ConstantPool.CONSTANT_Integer_info info = 105 (ConstantPool.CONSTANT_Integer_info) 106 classFile.constant_pool.get(ev.const_value_index); 107 testCase.checkEquals(info.value, Integer.parseInt(values[0]), "const_value_index"); 108 } 109 } 110 111 private class TestLongElementValue extends TestElementValue { 112 @Override 113 public void testElementValue( 114 TestResult testCase, 115 ClassFile classFile, 116 Annotation.element_value element_value, 117 String[] values) throws ConstantPool.InvalidIndex { 118 Annotation.Primitive_element_value ev = 119 (Annotation.Primitive_element_value) element_value; 120 ConstantPool.CONSTANT_Long_info info = 121 (ConstantPool.CONSTANT_Long_info) 122 classFile.constant_pool.get(ev.const_value_index); 123 testCase.checkEquals(info.value, Long.parseLong(values[0]), "const_value_index"); 124 } 125 } 126 127 private class TestFloatElementValue extends TestElementValue { 128 @Override 129 public void testElementValue( 130 TestResult testCase, 131 ClassFile classFile, 132 Annotation.element_value element_value, 133 String[] values) throws ConstantPool.InvalidIndex { 134 Annotation.Primitive_element_value ev = 135 (Annotation.Primitive_element_value) element_value; 136 ConstantPool.CONSTANT_Float_info info = 137 (ConstantPool.CONSTANT_Float_info) 138 classFile.constant_pool.get(ev.const_value_index); 139 testCase.checkEquals(info.value, Float.parseFloat(values[0]), "const_value_index"); 140 } 141 } 142 143 private class TestDoubleElementValue extends TestElementValue { 144 @Override 145 public void testElementValue( 146 TestResult testCase, 147 ClassFile classFile, 148 Annotation.element_value element_value, 149 String[] values) throws ConstantPool.InvalidIndex { 150 Annotation.Primitive_element_value ev = 151 (Annotation.Primitive_element_value) element_value; 152 ConstantPool.CONSTANT_Double_info info = 153 (ConstantPool.CONSTANT_Double_info) 154 classFile.constant_pool.get(ev.const_value_index); 155 testCase.checkEquals(info.value, Double.parseDouble(values[0]), "const_value_index"); 156 } 157 } 158 159 private class TestStringElementValue extends TestElementValue { 160 @Override 161 public void testElementValue( 162 TestResult testCase, 163 ClassFile classFile, 164 Annotation.element_value element_value, 165 String[] values) throws ConstantPool.InvalidIndex { 166 Annotation.Primitive_element_value ev = 167 (Annotation.Primitive_element_value) element_value; 168 ConstantPool.CONSTANT_Utf8_info info = 169 (ConstantPool.CONSTANT_Utf8_info) 170 classFile.constant_pool.get(ev.const_value_index); 171 testCase.checkEquals(info.value, values[0], "const_value_index"); 172 } 173 } 174 175 private class TestEnumElementValue extends TestElementValue { 176 177 @Override 178 public int getLength() { 179 return 2; 180 } 181 182 @Override 183 public void testElementValue( 184 TestResult testCase, 185 ClassFile classFile, 186 Annotation.element_value element_value, 187 String[] values) 188 throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry { 189 Annotation.Enum_element_value ev = (Annotation.Enum_element_value) element_value; 190 testCase.checkEquals(classFile.constant_pool.getUTF8Info(ev.type_name_index).value, 191 values[0], "type_name_index"); 192 testCase.checkEquals(classFile.constant_pool.getUTF8Info(ev.const_name_index).value, 193 values[1], "const_name_index"); 194 } 195 } 196 197 private class TestClassElementValue extends TestElementValue { 198 @Override 199 public void testElementValue( 200 TestResult testCase, 201 ClassFile classFile, 202 Annotation.element_value element_value, 203 String[] values) 204 throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry { 205 Annotation.Class_element_value ev = (Annotation.Class_element_value) element_value; 206 testCase.checkEquals( 207 classFile.constant_pool.getUTF8Info(ev.class_info_index).value, 208 values[0], "class_info_index"); 209 } 210 } 211 212 private class TestAnnotationElementValue extends TestElementValue { 213 @Override 214 public void testLength(TestResult testCase, AnnotationDefault_attribute attr) { 215 // Suppress, since it is hard to test the length of this kind of element values. 216 } 217 218 @Override 219 public int getLength() { 220 // Expected that the test uses DefaultAnnotation 221 // tag (1 byte) + annotation_value (2 bytes) which contains const_value 222 return 3; 223 } 224 225 @Override 226 public void testElementValue( 227 TestResult testCase, 228 ClassFile classFile, 229 Annotation.element_value element_value, 230 String[] values) 231 throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry { 232 Annotation ev = ((Annotation.Annotation_element_value) element_value) 233 .annotation_value; 234 testCase.checkEquals( 235 classFile.constant_pool.getUTF8Info(ev.type_index).value, 236 values[0], 237 "type_index"); 238 for (int i = 0; i < ev.num_element_value_pairs; ++i) { 239 Annotation.element_value_pair pair = ev.element_value_pairs[i]; 240 testCase.checkEquals( 241 classFile.constant_pool.getUTF8Info(pair.element_name_index).value, 242 values[2 * i + 1], 243 "element_name_index"); 244 TestElementValue testElementValue = verifiers.get(pair.value.tag); 245 testElementValue.testElementValue( 246 testCase, 247 classFile, 248 pair.value, 249 new String[]{values[2 * i + 2]}); 250 } 251 } 252 } 253 254 private class TestArrayElementValue extends TestElementValue { 255 @Override 256 public void testLength(TestResult testCase, AnnotationDefault_attribute attr) { 257 Annotation.Array_element_value ev = 258 (Annotation.Array_element_value) attr.default_value; 259 int sizeOfTag = ev.values[0].tag == 'e' ? 0 : 1; 260 // tag (1 byte) + array header (2 byte) + length of entries 261 testCase.checkEquals(attr.attribute_length, 1 + 2 + 262 (sizeOfTag + ev.length() / ev.num_values) * ev.num_values, "attribute_length"); 263 } 264 265 @Override 266 public void testElementValue( 267 TestResult testCase, 268 ClassFile classFile, 269 Annotation.element_value element_value, 270 String[] values) 271 throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry { 272 Annotation.Array_element_value ev = 273 (Annotation.Array_element_value) element_value; 274 int index = 0; 275 for (int i = 0; i < ev.num_values; ++i) { 276 TestElementValue testElementValue = verifiers.get(ev.values[i].tag); 277 int length = testElementValue.getLength(); 278 testElementValue.testElementValue( 279 testCase, 280 classFile, 281 ev.values[i], 282 testElementValue.getValues(values, index, length)); 283 index += length; 284 } 285 } 286 } 287} 288