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 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value) { 044 super(type, cpGen); 045 if (value) { 046 idx = getConstantPool().addInteger(1); 047 } else { 048 idx = getConstantPool().addInteger(0); 049 } 050 } 051 052 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value) { 053 super(type, cpGen); 054 idx = getConstantPool().addInteger(value); 055 } 056 057 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value) { 058 super(type, cpGen); 059 idx = getConstantPool().addInteger(value); 060 } 061 062 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value) { 063 super(type, cpGen); 064 idx = getConstantPool().addDouble(value); 065 } 066 067 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final float value) { 068 super(type, cpGen); 069 idx = getConstantPool().addFloat(value); 070 } 071 072 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final int value) { 073 super(type, cpGen); 074 idx = getConstantPool().addInteger(value); 075 } 076 077 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final long value) { 078 super(type, cpGen); 079 idx = getConstantPool().addLong(value); 080 } 081 082 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final short value) { 083 super(type, cpGen); 084 idx = getConstantPool().addInteger(value); 085 } 086 087 public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final String value) { 088 super(type, cpGen); 089 idx = getConstantPool().addUtf8(value); 090 } 091 092 // ctors for each supported type... type could be inferred but for now lets 093 // force it to be passed 094 095 /** 096 * Protected ctor used for deserialization, doesn't *put* an entry in the constant pool, assumes the one at the supplied 097 * index is correct. 098 */ 099 protected SimpleElementValueGen(final int type, final int idx, final ConstantPoolGen cpGen) { 100 super(type, cpGen); 101 this.idx = idx; 102 } 103 104 /** 105 * The boolean controls whether we copy info from the 'old' constant pool to the 'new'. You need to use this ctor if the 106 * annotation is being copied from one file to another. 107 */ 108 public SimpleElementValueGen(final SimpleElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { 109 super(value.getElementValueType(), cpool); 110 if (!copyPoolEntries) { 111 // J5ASSERT: Could assert value.stringifyValue() is the same as 112 // cpool.getConstant(SimpleElementValuevalue.getIndex()) 113 idx = value.getIndex(); 114 } else { 115 switch (value.getElementValueType()) { 116 case STRING: 117 idx = cpool.addUtf8(value.getValueString()); 118 break; 119 case PRIMITIVE_INT: 120 idx = cpool.addInteger(value.getValueInt()); 121 break; 122 case PRIMITIVE_BYTE: 123 idx = cpool.addInteger(value.getValueByte()); 124 break; 125 case PRIMITIVE_CHAR: 126 idx = cpool.addInteger(value.getValueChar()); 127 break; 128 case PRIMITIVE_LONG: 129 idx = cpool.addLong(value.getValueLong()); 130 break; 131 case PRIMITIVE_FLOAT: 132 idx = cpool.addFloat(value.getValueFloat()); 133 break; 134 case PRIMITIVE_DOUBLE: 135 idx = cpool.addDouble(value.getValueDouble()); 136 break; 137 case PRIMITIVE_BOOLEAN: 138 if (value.getValueBoolean()) { 139 idx = cpool.addInteger(1); 140 } else { 141 idx = cpool.addInteger(0); 142 } 143 break; 144 case PRIMITIVE_SHORT: 145 idx = cpool.addInteger(value.getValueShort()); 146 break; 147 default: 148 throw new IllegalArgumentException("SimpleElementValueGen class does not know how to copy this type " + super.getElementValueType()); 149 } 150 } 151 } 152 153 @Override 154 public void dump(final DataOutputStream dos) throws IOException { 155 dos.writeByte(super.getElementValueType()); // u1 kind of value 156 switch (super.getElementValueType()) { 157 case PRIMITIVE_INT: 158 case PRIMITIVE_BYTE: 159 case PRIMITIVE_CHAR: 160 case PRIMITIVE_FLOAT: 161 case PRIMITIVE_LONG: 162 case PRIMITIVE_BOOLEAN: 163 case PRIMITIVE_SHORT: 164 case PRIMITIVE_DOUBLE: 165 case STRING: 166 dos.writeShort(idx); 167 break; 168 default: 169 throw new IllegalStateException("SimpleElementValueGen doesn't know how to write out type " + super.getElementValueType()); 170 } 171 } 172 173 /** 174 * Return immutable variant 175 */ 176 @Override 177 public ElementValue getElementValue() { 178 return new SimpleElementValue(super.getElementValueType(), idx, getConstantPool().getConstantPool()); 179 } 180 181 public int getIndex() { 182 return idx; 183 } 184 185 public int getValueInt() { 186 if (super.getElementValueType() != PRIMITIVE_INT) { 187 throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); 188 } 189 final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); 190 return c.getBytes(); 191 } 192 193 public String getValueString() { 194 if (super.getElementValueType() != STRING) { 195 throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); 196 } 197 final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx); 198 return c.getBytes(); 199 } 200 201 // Whatever kind of value it is, return it as a string 202 @Override 203 public String stringifyValue() { 204 switch (super.getElementValueType()) { 205 case PRIMITIVE_INT: 206 final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); 207 return Integer.toString(c.getBytes()); 208 case PRIMITIVE_LONG: 209 final ConstantLong j = (ConstantLong) getConstantPool().getConstant(idx); 210 return Long.toString(j.getBytes()); 211 case PRIMITIVE_DOUBLE: 212 final ConstantDouble d = (ConstantDouble) getConstantPool().getConstant(idx); 213 return Double.toString(d.getBytes()); 214 case PRIMITIVE_FLOAT: 215 final ConstantFloat f = (ConstantFloat) getConstantPool().getConstant(idx); 216 return Float.toString(f.getBytes()); 217 case PRIMITIVE_SHORT: 218 final ConstantInteger s = (ConstantInteger) getConstantPool().getConstant(idx); 219 return Integer.toString(s.getBytes()); 220 case PRIMITIVE_BYTE: 221 final ConstantInteger b = (ConstantInteger) getConstantPool().getConstant(idx); 222 return Integer.toString(b.getBytes()); 223 case PRIMITIVE_CHAR: 224 final ConstantInteger ch = (ConstantInteger) getConstantPool().getConstant(idx); 225 return Integer.toString(ch.getBytes()); 226 case PRIMITIVE_BOOLEAN: 227 final ConstantInteger bo = (ConstantInteger) getConstantPool().getConstant(idx); 228 if (bo.getBytes() == 0) { 229 return "false"; 230 } 231 return "true"; 232 case STRING: 233 final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx); 234 return cu8.getBytes(); 235 default: 236 throw new IllegalStateException("SimpleElementValueGen class does not know how to stringify type " + super.getElementValueType()); 237 } 238 } 239}