View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  
24  import org.apache.bcel.classfile.ConstantDouble;
25  import org.apache.bcel.classfile.ConstantFloat;
26  import org.apache.bcel.classfile.ConstantInteger;
27  import org.apache.bcel.classfile.ConstantLong;
28  import org.apache.bcel.classfile.ConstantUtf8;
29  import org.apache.bcel.classfile.ElementValue;
30  import org.apache.bcel.classfile.SimpleElementValue;
31  
32  /**
33   * Generates simple element values in annotations.
34   *
35   * @since 6.0
36   */
37  public class SimpleElementValueGen extends ElementValueGen {
38      // For primitive types and string type, this points to the value entry in
39      // the cpGen
40      // For 'class' this points to the class entry in the cpGen
41      private final int idx;
42  
43      /**
44       * Constructs a SimpleElementValueGen for a boolean value.
45       *
46       * @param type The element value type.
47       * @param cpGen The constant pool generator.
48       * @param value The boolean value.
49       */
50      public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value) {
51          super(type, cpGen);
52          if (value) {
53              idx = getConstantPool().addInteger(1);
54          } else {
55              idx = getConstantPool().addInteger(0);
56          }
57      }
58  
59      /**
60       * Constructs a SimpleElementValueGen for a byte value.
61       *
62       * @param type The element value type.
63       * @param cpGen The constant pool generator.
64       * @param value The byte value.
65       */
66      public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value) {
67          super(type, cpGen);
68          idx = getConstantPool().addInteger(value);
69      }
70  
71      /**
72       * Constructs a SimpleElementValueGen for a char value.
73       *
74       * @param type The element value type.
75       * @param cpGen The constant pool generator.
76       * @param value The char value.
77       */
78      public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value) {
79          super(type, cpGen);
80          idx = getConstantPool().addInteger(value);
81      }
82  
83      /**
84       * Constructs a SimpleElementValueGen for a double value.
85       *
86       * @param type The element value type.
87       * @param cpGen The constant pool generator.
88       * @param value The double value.
89       */
90      public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value) {
91          super(type, cpGen);
92          idx = getConstantPool().addDouble(value);
93      }
94  
95      /**
96       * Constructs a SimpleElementValueGen for a float value.
97       *
98       * @param type The element value type.
99       * @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 }