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.DataInput;
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 
24 import org.apache.bcel.classfile.AnnotationElementValue;
25 import org.apache.bcel.classfile.AnnotationEntry;
26 import org.apache.bcel.classfile.ArrayElementValue;
27 import org.apache.bcel.classfile.ClassElementValue;
28 import org.apache.bcel.classfile.ElementValue;
29 import org.apache.bcel.classfile.EnumElementValue;
30 import org.apache.bcel.classfile.SimpleElementValue;
31 
32 /**
33  * @since 6.0
34  */
35 public abstract class ElementValueGen
36 {
37     /**
38      * @deprecated (since 6.0) will be made private and final; do not access directly, use getter
39      */
40     @Deprecated
41     protected int type;
42 
43     /**
44      * @deprecated (since 6.0) will be made private and final; do not access directly, use getter
45      */
46     @Deprecated
47     protected ConstantPoolGen cpGen;
48 
ElementValueGen(final int type, final ConstantPoolGen cpGen)49     protected ElementValueGen(final int type, final ConstantPoolGen cpGen)
50     {
51         this.type = type;
52         this.cpGen = cpGen;
53     }
54 
55     /**
56      * Subtypes return an immutable variant of the ElementValueGen
57      */
getElementValue()58     public abstract ElementValue getElementValue();
59 
getElementValueType()60     public int getElementValueType()
61     {
62         return type;
63     }
64 
stringifyValue()65     public abstract String stringifyValue();
66 
dump(DataOutputStream dos)67     public abstract void dump(DataOutputStream dos) throws IOException;
68 
69     public static final int STRING = 's';
70 
71     public static final int ENUM_CONSTANT = 'e';
72 
73     public static final int CLASS = 'c';
74 
75     public static final int ANNOTATION = '@';
76 
77     public static final int ARRAY = '[';
78 
79     public static final int PRIMITIVE_INT = 'I';
80 
81     public static final int PRIMITIVE_BYTE = 'B';
82 
83     public static final int PRIMITIVE_CHAR = 'C';
84 
85     public static final int PRIMITIVE_DOUBLE = 'D';
86 
87     public static final int PRIMITIVE_FLOAT = 'F';
88 
89     public static final int PRIMITIVE_LONG = 'J';
90 
91     public static final int PRIMITIVE_SHORT = 'S';
92 
93     public static final int PRIMITIVE_BOOLEAN = 'Z';
94 
readElementValue(final DataInput dis, final ConstantPoolGen cpGen)95     public static ElementValueGen readElementValue(final DataInput dis,
96             final ConstantPoolGen cpGen) throws IOException
97     {
98         final int type = dis.readUnsignedByte();
99         switch (type)
100         {
101         case 'B': // byte
102             return new SimpleElementValueGen(PRIMITIVE_BYTE, dis
103                     .readUnsignedShort(), cpGen);
104         case 'C': // char
105             return new SimpleElementValueGen(PRIMITIVE_CHAR, dis
106                     .readUnsignedShort(), cpGen);
107         case 'D': // double
108             return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis
109                     .readUnsignedShort(), cpGen);
110         case 'F': // float
111             return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis
112                     .readUnsignedShort(), cpGen);
113         case 'I': // int
114             return new SimpleElementValueGen(PRIMITIVE_INT, dis
115                     .readUnsignedShort(), cpGen);
116         case 'J': // long
117             return new SimpleElementValueGen(PRIMITIVE_LONG, dis
118                     .readUnsignedShort(), cpGen);
119         case 'S': // short
120             return new SimpleElementValueGen(PRIMITIVE_SHORT, dis
121                     .readUnsignedShort(), cpGen);
122         case 'Z': // boolean
123             return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis
124                     .readUnsignedShort(), cpGen);
125         case 's': // String
126             return new SimpleElementValueGen(STRING, dis.readUnsignedShort(),
127                     cpGen);
128         case 'e': // Enum constant
129             return new EnumElementValueGen(dis.readUnsignedShort(), dis
130                     .readUnsignedShort(), cpGen);
131         case 'c': // Class
132             return new ClassElementValueGen(dis.readUnsignedShort(), cpGen);
133         case '@': // Annotation
134             // TODO: isRuntimeVisible ??????????
135             // FIXME
136             return new AnnotationElementValueGen(ANNOTATION,
137                     new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen
138                             .getConstantPool(), true), cpGen, false), cpGen);
139         case '[': // Array
140             final int numArrayVals = dis.readUnsignedShort();
141             final ElementValue[] evalues = new ElementValue[numArrayVals];
142             for (int j = 0; j < numArrayVals; j++)
143             {
144                 evalues[j] = ElementValue.readElementValue(dis, cpGen
145                         .getConstantPool());
146             }
147             return new ArrayElementValueGen(ARRAY, evalues, cpGen);
148         default:
149             throw new RuntimeException("Unexpected element value kind in annotation: " + type);
150         }
151     }
152 
getConstantPool()153     protected ConstantPoolGen getConstantPool()
154     {
155         return cpGen;
156     }
157 
158     /**
159      * Creates an (modifiable) ElementValueGen copy of an (immutable)
160      * ElementValue - constant pool is assumed correct.
161      */
copy(final ElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries)162     public static ElementValueGen copy(final ElementValue value,
163             final ConstantPoolGen cpool, final boolean copyPoolEntries)
164     {
165         switch (value.getElementValueType())
166         {
167         case 'B': // byte
168         case 'C': // char
169         case 'D': // double
170         case 'F': // float
171         case 'I': // int
172         case 'J': // long
173         case 'S': // short
174         case 'Z': // boolean
175         case 's': // String
176             return new SimpleElementValueGen((SimpleElementValue) value, cpool,
177                     copyPoolEntries);
178         case 'e': // Enum constant
179             return new EnumElementValueGen((EnumElementValue) value, cpool,
180                     copyPoolEntries);
181         case '@': // Annotation
182             return new AnnotationElementValueGen(
183                     (AnnotationElementValue) value, cpool, copyPoolEntries);
184         case '[': // Array
185             return new ArrayElementValueGen((ArrayElementValue) value, cpool,
186                     copyPoolEntries);
187         case 'c': // Class
188             return new ClassElementValueGen((ClassElementValue) value, cpool,
189                     copyPoolEntries);
190         default:
191             throw new RuntimeException("Not implemented yet! (" + value.getElementValueType() + ")");
192         }
193     }
194 }
195