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 */ 019package org.apache.bcel.generic; 020 021import java.io.DataOutputStream; 022import java.io.IOException; 023 024import org.apache.bcel.classfile.ConstantDouble; 025import org.apache.bcel.classfile.ConstantFloat; 026import org.apache.bcel.classfile.ConstantInteger; 027import org.apache.bcel.classfile.ConstantLong; 028import org.apache.bcel.classfile.ConstantUtf8; 029import org.apache.bcel.classfile.ElementValue; 030import org.apache.bcel.classfile.SimpleElementValue; 031 032/** 033 * Generates simple element values in annotations. 034 * 035 * @since 6.0 036 */ 037public class SimpleElementValueGen extends ElementValueGen { 038 // For primitive types and string type, this points to the value entry in 039 // the cpGen 040 // For 'class' this points to the class entry in the cpGen 041 private final int idx; 042 043 /** 044 * Constructs a SimpleElementValueGen for a boolean value. 045 * 046 * @param type The element value type. 047 * @param cpGen The constant pool generator. 048 * @param value The boolean value. 049 */ 050 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value) { 051 super(type, cpGen); 052 if (value) { 053 idx = getConstantPool().addInteger(1); 054 } else { 055 idx = getConstantPool().addInteger(0); 056 } 057 } 058 059 /** 060 * Constructs a SimpleElementValueGen for a byte value. 061 * 062 * @param type The element value type. 063 * @param cpGen The constant pool generator. 064 * @param value The byte value. 065 */ 066 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value) { 067 super(type, cpGen); 068 idx = getConstantPool().addInteger(value); 069 } 070 071 /** 072 * Constructs a SimpleElementValueGen for a char value. 073 * 074 * @param type The element value type. 075 * @param cpGen The constant pool generator. 076 * @param value The char value. 077 */ 078 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value) { 079 super(type, cpGen); 080 idx = getConstantPool().addInteger(value); 081 } 082 083 /** 084 * Constructs a SimpleElementValueGen for a double value. 085 * 086 * @param type The element value type. 087 * @param cpGen The constant pool generator. 088 * @param value The double value. 089 */ 090 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value) { 091 super(type, cpGen); 092 idx = getConstantPool().addDouble(value); 093 } 094 095 /** 096 * Constructs a SimpleElementValueGen for a float value. 097 * 098 * @param type The element value type. 099 * @param cpGen The constant pool generator. 100 * @param value The float value. 101 */ 102 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final float value) { 103 super(type, cpGen); 104 idx = getConstantPool().addFloat(value); 105 } 106 107 /** 108 * Constructs a SimpleElementValueGen for an int value. 109 * 110 * @param type The element value type. 111 * @param cpGen The constant pool generator. 112 * @param value The int value. 113 */ 114 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final int value) { 115 super(type, cpGen); 116 idx = getConstantPool().addInteger(value); 117 } 118 119 /** 120 * Constructs a SimpleElementValueGen for a long value. 121 * 122 * @param type The element value type. 123 * @param cpGen The constant pool generator. 124 * @param value The long value. 125 */ 126 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final long value) { 127 super(type, cpGen); 128 idx = getConstantPool().addLong(value); 129 } 130 131 /** 132 * Constructs a SimpleElementValueGen for a short value. 133 * 134 * @param type The element value type. 135 * @param cpGen The constant pool generator. 136 * @param value The short value. 137 */ 138 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final short value) { 139 super(type, cpGen); 140 idx = getConstantPool().addInteger(value); 141 } 142 143 /** 144 * Constructs a SimpleElementValueGen for a String value. 145 * 146 * @param type The element value type. 147 * @param cpGen The constant pool generator. 148 * @param value The string value. 149 */ 150 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final String value) { 151 super(type, cpGen); 152 idx = getConstantPool().addUtf8(value); 153 } 154 155 // ctors for each supported type... type could be inferred but for now lets 156 // force it to be passed 157 158 /** 159 * Protected ctor used for deserialization, doesn't *put* an entry in the constant pool, assumes the one at the supplied 160 * index is correct. 161 * 162 * @param type The element value type. 163 * @param idx The constant pool index. 164 * @param cpGen The constant pool generator. 165 */ 166 protected SimpleElementValueGen(final int type, final int idx, final ConstantPoolGen cpGen) { 167 super(type, cpGen); 168 this.idx = idx; 169 } 170 171 /** 172 * The boolean controls whether we copy info from the 'old' constant pool to the 'new'. You need to use this ctor if the 173 * annotation is being copied from one file to another. 174 * 175 * @param value The simple element value to copy. 176 * @param cpool The constant pool generator. 177 * @param copyPoolEntries whether to copy pool entries. 178 */ 179 public SimpleElementValueGen(final SimpleElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { 180 super(value.getElementValueType(), cpool); 181 if (!copyPoolEntries) { 182 // J5ASSERT: Could assert value.stringifyValue() is the same as 183 // cpool.getConstant(SimpleElementValuevalue.getIndex()) 184 idx = value.getIndex(); 185 } else { 186 switch (value.getElementValueType()) { 187 case STRING: 188 idx = cpool.addUtf8(value.getValueString()); 189 break; 190 case PRIMITIVE_INT: 191 idx = cpool.addInteger(value.getValueInt()); 192 break; 193 case PRIMITIVE_BYTE: 194 idx = cpool.addInteger(value.getValueByte()); 195 break; 196 case PRIMITIVE_CHAR: 197 idx = cpool.addInteger(value.getValueChar()); 198 break; 199 case PRIMITIVE_LONG: 200 idx = cpool.addLong(value.getValueLong()); 201 break; 202 case PRIMITIVE_FLOAT: 203 idx = cpool.addFloat(value.getValueFloat()); 204 break; 205 case PRIMITIVE_DOUBLE: 206 idx = cpool.addDouble(value.getValueDouble()); 207 break; 208 case PRIMITIVE_BOOLEAN: 209 if (value.getValueBoolean()) { 210 idx = cpool.addInteger(1); 211 } else { 212 idx = cpool.addInteger(0); 213 } 214 break; 215 case PRIMITIVE_SHORT: 216 idx = cpool.addInteger(value.getValueShort()); 217 break; 218 default: 219 throw new IllegalArgumentException("SimpleElementValueGen class does not know how to copy this type " + super.getElementValueType()); 220 } 221 } 222 } 223 224 @Override 225 public void dump(final DataOutputStream dos) throws IOException { 226 dos.writeByte(super.getElementValueType()); // u1 kind of value 227 switch (super.getElementValueType()) { 228 case PRIMITIVE_INT: 229 case PRIMITIVE_BYTE: 230 case PRIMITIVE_CHAR: 231 case PRIMITIVE_FLOAT: 232 case PRIMITIVE_LONG: 233 case PRIMITIVE_BOOLEAN: 234 case PRIMITIVE_SHORT: 235 case PRIMITIVE_DOUBLE: 236 case STRING: 237 dos.writeShort(idx); 238 break; 239 default: 240 throw new IllegalStateException("SimpleElementValueGen doesn't know how to write out type " + super.getElementValueType()); 241 } 242 } 243 244 /** 245 * Gets the immutable variant. 246 * 247 * @return The immutable variant. 248 */ 249 @Override 250 public ElementValue getElementValue() { 251 return new SimpleElementValue(super.getElementValueType(), idx, getConstantPool().getConstantPool()); 252 } 253 254 /** 255 * Gets the constant pool index. 256 * 257 * @return The index. 258 */ 259 public int getIndex() { 260 return idx; 261 } 262 263 /** 264 * Gets the int value. 265 * 266 * @return The int value. 267 */ 268 public int getValueInt() { 269 if (super.getElementValueType() != PRIMITIVE_INT) { 270 throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); 271 } 272 final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); 273 return c.getBytes(); 274 } 275 276 /** 277 * Gets the string value. 278 * 279 * @return The string value. 280 */ 281 public String getValueString() { 282 if (super.getElementValueType() != STRING) { 283 throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); 284 } 285 final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx); 286 return c.getBytes(); 287 } 288 289 // Whatever kind of value it is, return it as a string 290 @Override 291 public String stringifyValue() { 292 switch (super.getElementValueType()) { 293 case PRIMITIVE_INT: 294 final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); 295 return Integer.toString(c.getBytes()); 296 case PRIMITIVE_LONG: 297 final ConstantLong j = (ConstantLong) getConstantPool().getConstant(idx); 298 return Long.toString(j.getBytes()); 299 case PRIMITIVE_DOUBLE: 300 final ConstantDouble d = (ConstantDouble) getConstantPool().getConstant(idx); 301 return Double.toString(d.getBytes()); 302 case PRIMITIVE_FLOAT: 303 final ConstantFloat f = (ConstantFloat) getConstantPool().getConstant(idx); 304 return Float.toString(f.getBytes()); 305 case PRIMITIVE_SHORT: 306 final ConstantInteger s = (ConstantInteger) getConstantPool().getConstant(idx); 307 return Integer.toString(s.getBytes()); 308 case PRIMITIVE_BYTE: 309 final ConstantInteger b = (ConstantInteger) getConstantPool().getConstant(idx); 310 return Integer.toString(b.getBytes()); 311 case PRIMITIVE_CHAR: 312 final ConstantInteger ch = (ConstantInteger) getConstantPool().getConstant(idx); 313 return Integer.toString(ch.getBytes()); 314 case PRIMITIVE_BOOLEAN: 315 final ConstantInteger bo = (ConstantInteger) getConstantPool().getConstant(idx); 316 if (bo.getBytes() == 0) { 317 return "false"; 318 } 319 return "true"; 320 case STRING: 321 final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx); 322 return cu8.getBytes(); 323 default: 324 throw new IllegalStateException("SimpleElementValueGen class does not know how to stringify type " + super.getElementValueType()); 325 } 326 } 327}