001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.bcel.classfile; 021 022import java.io.DataInput; 023import java.io.DataOutputStream; 024import java.io.IOException; 025 026import org.apache.bcel.Const; 027 028/** 029 * The element_value structure is documented at https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7.16.1 030 * 031 * <pre> 032 * element_value { 033 * u1 tag; 034 * union { 035 * u2 const_value_index; 036 * 037 * { u2 type_name_index; 038 * u2 const_name_index; 039 * } enum_const_value; 040 * 041 * u2 class_info_index; 042 * 043 * annotation annotation_value; 044 * 045 * { u2 num_values; 046 * element_value values[num_values]; 047 * } array_value; 048 * } value; 049 *} 050 *</pre> 051 * 052 * @since 6.0 053 */ 054public abstract class ElementValue { 055 056 /** Element value type: string. */ 057 public static final byte STRING = 's'; 058 059 /** Element value type: enum constant. */ 060 public static final byte ENUM_CONSTANT = 'e'; 061 062 /** Element value type: class. */ 063 public static final byte CLASS = 'c'; 064 065 /** Element value type: annotation. */ 066 public static final byte ANNOTATION = '@'; 067 068 /** Element value type: array. */ 069 public static final byte ARRAY = '['; 070 071 /** Element value type: primitive int. */ 072 public static final byte PRIMITIVE_INT = 'I'; 073 074 /** Element value type: primitive byte. */ 075 public static final byte PRIMITIVE_BYTE = 'B'; 076 077 /** Element value type: primitive char. */ 078 public static final byte PRIMITIVE_CHAR = 'C'; 079 080 /** Element value type: primitive double. */ 081 public static final byte PRIMITIVE_DOUBLE = 'D'; 082 083 /** Element value type: primitive float. */ 084 public static final byte PRIMITIVE_FLOAT = 'F'; 085 086 /** Element value type: primitive long. */ 087 public static final byte PRIMITIVE_LONG = 'J'; 088 089 /** Element value type: primitive short. */ 090 public static final byte PRIMITIVE_SHORT = 'S'; 091 092 /** Element value type: primitive boolean. */ 093 public static final byte PRIMITIVE_BOOLEAN = 'Z'; 094 095 /** Empty array constant. */ 096 static final ElementValue[] EMPTY_ARRAY = {}; 097 098 /** 099 * Reads an {@code element_value} as an {@code ElementValue}. 100 * 101 * @param input Raw data input. 102 * @param cpool Constant pool. 103 * @return a new ElementValue. 104 * @throws IOException if an I/O error occurs. 105 */ 106 public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool) throws IOException { 107 return readElementValue(input, cpool, 0); 108 } 109 110 /** 111 * Reads an {@code element_value} as an {@code ElementValue}. 112 * 113 * @param input Raw data input. 114 * @param cpool Constant pool. 115 * @param arrayNesting level of current array nesting. 116 * @return a new ElementValue. 117 * @throws IOException if an I/O error occurs. 118 * @since 6.7.0 119 */ 120 public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool, int arrayNesting) 121 throws IOException { 122 final byte tag = input.readByte(); 123 switch (tag) { 124 case PRIMITIVE_BYTE: 125 case PRIMITIVE_CHAR: 126 case PRIMITIVE_DOUBLE: 127 case PRIMITIVE_FLOAT: 128 case PRIMITIVE_INT: 129 case PRIMITIVE_LONG: 130 case PRIMITIVE_SHORT: 131 case PRIMITIVE_BOOLEAN: 132 case STRING: 133 return new SimpleElementValue(tag, input.readUnsignedShort(), cpool); 134 135 case ENUM_CONSTANT: 136 return new EnumElementValue(ENUM_CONSTANT, input.readUnsignedShort(), input.readUnsignedShort(), cpool); 137 138 case CLASS: 139 return new ClassElementValue(CLASS, input.readUnsignedShort(), cpool); 140 141 case ANNOTATION: 142 // TODO isRuntimeVisible 143 return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(input, cpool, false), cpool); 144 145 case ARRAY: 146 arrayNesting++; 147 if (arrayNesting > Const.MAX_ARRAY_DIMENSIONS) { 148 // JVM spec 4.4.1 149 throw new ClassFormatException(String.format("Arrays are only valid if they represent %,d or fewer dimensions.", Const.MAX_ARRAY_DIMENSIONS)); 150 } 151 final int numArrayVals = input.readUnsignedShort(); 152 final ElementValue[] evalues = new ElementValue[numArrayVals]; 153 for (int j = 0; j < numArrayVals; j++) { 154 evalues[j] = readElementValue(input, cpool, arrayNesting); 155 } 156 return new ArrayElementValue(ARRAY, evalues, cpool); 157 158 default: 159 throw new ClassFormatException("Unexpected element value tag in annotation: " + tag); 160 } 161 } 162 163 /** 164 * @deprecated (since 6.0) will be made private and final; do not access directly, use getter. 165 */ 166 @java.lang.Deprecated 167 protected int type; // TODO should be final 168 169 /** 170 * @deprecated (since 6.0) will be made private and final; do not access directly, use getter. 171 */ 172 @java.lang.Deprecated 173 protected ConstantPool cpool; // TODO should be final 174 175 /** 176 * Constructs an ElementValue. 177 * 178 * @param type the element value type. 179 * @param cpool the constant pool. 180 */ 181 protected ElementValue(final int type, final ConstantPool cpool) { 182 this.type = type; 183 this.cpool = cpool; 184 } 185 186 /** 187 * Dumps this element value to a DataOutputStream. 188 * 189 * @param dos the output stream. 190 * @throws IOException if an I/O error occurs. 191 */ 192 public abstract void dump(DataOutputStream dos) throws IOException; 193 194 /** 195 * Gets the constant pool. 196 * 197 * @return the constant pool. 198 * @since 6.0 199 */ 200 final ConstantPool getConstantPool() { 201 return cpool; 202 } 203 204 /** 205 * Gets the element value type. 206 * 207 * @return the element value type. 208 */ 209 public int getElementValueType() { 210 return type; 211 } 212 213 /** 214 * Gets the type. 215 * 216 * @return the type. 217 * @since 6.0 218 */ 219 final int getType() { 220 return type; 221 } 222 223 /** 224 * Returns a string representation of the element value. 225 * 226 * @return a string representation of the element value. 227 */ 228 public abstract String stringifyValue(); 229 230 /** 231 * Returns a short string representation of the element value. 232 * 233 * @return a short string representation of the element value. 234 */ 235 public String toShortString() { 236 return stringifyValue(); 237 } 238 239 /** 240 * Returns a string representation of the element value. 241 * 242 * @return a string representation of the element value. 243 */ 244 @Override 245 public String toString() { 246 return stringifyValue(); 247 } 248}