1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 package org.apache.bcel.generic;
19 
20 import java.io.DataOutputStream;
21 import java.io.IOException;
22 
23 import org.apache.bcel.classfile.ConstantDouble;
24 import org.apache.bcel.classfile.ConstantFloat;
25 import org.apache.bcel.classfile.ConstantInteger;
26 import org.apache.bcel.classfile.ConstantLong;
27 import org.apache.bcel.classfile.ConstantUtf8;
28 import org.apache.bcel.classfile.ElementValue;
29 import org.apache.bcel.classfile.SimpleElementValue;
30 
31 /**
32  * @since 6.0
33  */
34 public class SimpleElementValueGen extends ElementValueGen
35 {
36     // For primitive types and string type, this points to the value entry in
37     // the cpGen
38     // For 'class' this points to the class entry in the cpGen
39     private int idx;
40 
41     // ctors for each supported type... type could be inferred but for now lets
42     // force it to be passed
43     /**
44      * Protected ctor used for deserialization, doesn't *put* an entry in the
45      * constant pool, assumes the one at the supplied index is correct.
46      */
SimpleElementValueGen(final int type, final int idx, final ConstantPoolGen cpGen)47     protected SimpleElementValueGen(final int type, final int idx, final ConstantPoolGen cpGen)
48     {
49         super(type, cpGen);
50         this.idx = idx;
51     }
52 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final int value)53     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final int value)
54     {
55         super(type, cpGen);
56         idx = getConstantPool().addInteger(value);
57     }
58 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final long value)59     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final long value)
60     {
61         super(type, cpGen);
62         idx = getConstantPool().addLong(value);
63     }
64 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value)65     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value)
66     {
67         super(type, cpGen);
68         idx = getConstantPool().addDouble(value);
69     }
70 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final float value)71     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final float value)
72     {
73         super(type, cpGen);
74         idx = getConstantPool().addFloat(value);
75     }
76 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final short value)77     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final short value)
78     {
79         super(type, cpGen);
80         idx = getConstantPool().addInteger(value);
81     }
82 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value)83     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value)
84     {
85         super(type, cpGen);
86         idx = getConstantPool().addInteger(value);
87     }
88 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value)89     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value)
90     {
91         super(type, cpGen);
92         idx = getConstantPool().addInteger(value);
93     }
94 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value)95     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value)
96     {
97         super(type, cpGen);
98         if (value) {
99             idx = getConstantPool().addInteger(1);
100         } else {
101             idx = getConstantPool().addInteger(0);
102         }
103     }
104 
SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final String value)105     public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final String value)
106     {
107         super(type, cpGen);
108         idx = getConstantPool().addUtf8(value);
109     }
110 
111     /**
112      * The boolean controls whether we copy info from the 'old' constant pool to
113      * the 'new'. You need to use this ctor if the annotation is being copied
114      * from one file to another.
115      */
SimpleElementValueGen(final SimpleElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries)116     public SimpleElementValueGen(final SimpleElementValue value,
117             final ConstantPoolGen cpool, final boolean copyPoolEntries)
118     {
119         super(value.getElementValueType(), cpool);
120         if (!copyPoolEntries)
121         {
122             // J5ASSERT: Could assert value.stringifyValue() is the same as
123             // cpool.getConstant(SimpleElementValuevalue.getIndex())
124             idx = value.getIndex();
125         }
126         else
127         {
128             switch (value.getElementValueType())
129             {
130             case STRING:
131                 idx = cpool.addUtf8(value.getValueString());
132                 break;
133             case PRIMITIVE_INT:
134                 idx = cpool.addInteger(value.getValueInt());
135                 break;
136             case PRIMITIVE_BYTE:
137                 idx = cpool.addInteger(value.getValueByte());
138                 break;
139             case PRIMITIVE_CHAR:
140                 idx = cpool.addInteger(value.getValueChar());
141                 break;
142             case PRIMITIVE_LONG:
143                 idx = cpool.addLong(value.getValueLong());
144                 break;
145             case PRIMITIVE_FLOAT:
146                 idx = cpool.addFloat(value.getValueFloat());
147                 break;
148             case PRIMITIVE_DOUBLE:
149                 idx = cpool.addDouble(value.getValueDouble());
150                 break;
151             case PRIMITIVE_BOOLEAN:
152                 if (value.getValueBoolean())
153                 {
154                     idx = cpool.addInteger(1);
155                 }
156                 else
157                 {
158                     idx = cpool.addInteger(0);
159                 }
160                 break;
161             case PRIMITIVE_SHORT:
162                 idx = cpool.addInteger(value.getValueShort());
163                 break;
164             default:
165                 throw new RuntimeException(
166                     "SimpleElementValueGen class does not know how to copy this type " + super.getElementValueType());
167             }
168         }
169     }
170 
171     /**
172      * Return immutable variant
173      */
174     @Override
getElementValue()175     public ElementValue getElementValue()
176     {
177         return new SimpleElementValue(super.getElementValueType(), idx, getConstantPool().getConstantPool());
178     }
179 
getIndex()180     public int getIndex()
181     {
182         return idx;
183     }
184 
getValueString()185     public String getValueString()
186     {
187         if (super.getElementValueType() != STRING) {
188             throw new RuntimeException(
189                     "Dont call getValueString() on a non STRING ElementValue");
190         }
191         final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx);
192         return c.getBytes();
193     }
194 
getValueInt()195     public int getValueInt()
196     {
197         if (super.getElementValueType() != PRIMITIVE_INT) {
198             throw new RuntimeException(
199                     "Dont call getValueString() on a non STRING ElementValue");
200         }
201         final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx);
202         return c.getBytes();
203     }
204 
205     // Whatever kind of value it is, return it as a string
206     @Override
stringifyValue()207     public String stringifyValue()
208     {
209         switch (super.getElementValueType())
210         {
211         case PRIMITIVE_INT:
212             final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx);
213             return Integer.toString(c.getBytes());
214         case PRIMITIVE_LONG:
215             final ConstantLong j = (ConstantLong) getConstantPool().getConstant(idx);
216             return Long.toString(j.getBytes());
217         case PRIMITIVE_DOUBLE:
218             final ConstantDouble d = (ConstantDouble) getConstantPool().getConstant(idx);
219             return Double.toString(d.getBytes());
220         case PRIMITIVE_FLOAT:
221             final ConstantFloat f = (ConstantFloat) getConstantPool().getConstant(idx);
222             return Float.toString(f.getBytes());
223         case PRIMITIVE_SHORT:
224             final ConstantInteger s = (ConstantInteger) getConstantPool().getConstant(idx);
225             return Integer.toString(s.getBytes());
226         case PRIMITIVE_BYTE:
227             final ConstantInteger b = (ConstantInteger) getConstantPool().getConstant(idx);
228             return Integer.toString(b.getBytes());
229         case PRIMITIVE_CHAR:
230             final ConstantInteger ch = (ConstantInteger) getConstantPool().getConstant(idx);
231             return Integer.toString(ch.getBytes());
232         case PRIMITIVE_BOOLEAN:
233             final ConstantInteger bo = (ConstantInteger) getConstantPool().getConstant(idx);
234             if (bo.getBytes() == 0) {
235                 return "false";
236             }
237             return "true";
238         case STRING:
239             final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx);
240             return cu8.getBytes();
241         default:
242             throw new RuntimeException(
243                 "SimpleElementValueGen class does not know how to stringify type " + super.getElementValueType());
244         }
245     }
246 
247     @Override
dump(final DataOutputStream dos)248     public void dump(final DataOutputStream dos) throws IOException
249     {
250         dos.writeByte(super.getElementValueType()); // u1 kind of value
251         switch (super.getElementValueType())
252         {
253         case PRIMITIVE_INT:
254         case PRIMITIVE_BYTE:
255         case PRIMITIVE_CHAR:
256         case PRIMITIVE_FLOAT:
257         case PRIMITIVE_LONG:
258         case PRIMITIVE_BOOLEAN:
259         case PRIMITIVE_SHORT:
260         case PRIMITIVE_DOUBLE:
261         case STRING:
262             dos.writeShort(idx);
263             break;
264         default:
265             throw new RuntimeException(
266                 "SimpleElementValueGen doesnt know how to write out type " + super.getElementValueType());
267         }
268     }
269 }
270