View Javadoc
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  
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       */
58      public abstract ElementValue getElementValue();
59  
60      public int getElementValueType()
61      {
62          return type;
63      }
64  
65      public abstract String stringifyValue();
66  
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  
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 
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      */
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 }