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