blob: c85f19f9b9ecef72ce9d58e6771d8a83ad116b66 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.tools.java;
27
28import java.io.IOException;
29import java.io.DataInputStream;
30import java.io.DataOutputStream;
31import java.util.Vector;
32import java.util.Hashtable;
33
34/**
35 * This class is used to represent a constant table once
36 * it is read from a class file.
37 *
38 * WARNING: The contents of this source file are not part of any
39 * supported API. Code that depends on them does so at its own risk:
40 * they are subject to change or removal without notice.
41 */
42public final
43class BinaryConstantPool implements Constants {
44 private byte types[];
45 private Object cpool[];
46
47 /**
48 * Constructor
49 */
50 BinaryConstantPool(DataInputStream in) throws IOException {
51 // JVM 4.1 ClassFile.constant_pool_count
52 types = new byte[in.readUnsignedShort()];
53 cpool = new Object[types.length];
54 for (int i = 1 ; i < cpool.length ; i++) {
55 int j = i;
56 // JVM 4.4 cp_info.tag
57 switch(types[i] = in.readByte()) {
58 case CONSTANT_UTF8:
59 cpool[i] = in.readUTF();
60 break;
61
62 case CONSTANT_INTEGER:
63 cpool[i] = new Integer(in.readInt());
64 break;
65 case CONSTANT_FLOAT:
66 cpool[i] = new Float(in.readFloat());
67 break;
68 case CONSTANT_LONG:
69 cpool[i++] = new Long(in.readLong());
70 break;
71 case CONSTANT_DOUBLE:
72 cpool[i++] = new Double(in.readDouble());
73 break;
74
75 case CONSTANT_CLASS:
76 case CONSTANT_STRING:
77 // JVM 4.4.3 CONSTANT_String_info.string_index
78 // or JVM 4.4.1 CONSTANT_Class_info.name_index
79 cpool[i] = new Integer(in.readUnsignedShort());
80 break;
81
82 case CONSTANT_FIELD:
83 case CONSTANT_METHOD:
84 case CONSTANT_INTERFACEMETHOD:
85 case CONSTANT_NAMEANDTYPE:
86 // JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index
87 cpool[i] = new Integer((in.readUnsignedShort() << 16) | in.readUnsignedShort());
88 break;
89
90 case 0:
91 default:
92 throw new ClassFormatError("invalid constant type: " + (int)types[i]);
93 }
94 }
95 }
96
97 /**
98 * get a integer
99 */
100 public int getInteger(int n) {
101 return (n == 0) ? 0 : ((Number)cpool[n]).intValue();
102 }
103
104 /**
105 * get a value
106 */
107 public Object getValue(int n) {
108 return (n == 0) ? null : cpool[n];
109 }
110
111 /**
112 * get a string
113 */
114 public String getString(int n) {
115 return (n == 0) ? null : (String)cpool[n];
116 }
117
118 /**
119 * get an identifier
120 */
121 public Identifier getIdentifier(int n) {
122 return (n == 0) ? null : Identifier.lookup(getString(n));
123 }
124
125 /**
126 * get class declaration
127 */
128 public ClassDeclaration getDeclarationFromName(Environment env, int n) {
129 return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.')));
130 }
131
132 /**
133 * get class declaration
134 */
135 public ClassDeclaration getDeclaration(Environment env, int n) {
136 return (n == 0) ? null : getDeclarationFromName(env, getInteger(n));
137 }
138
139 /**
140 * get a type from a type signature
141 */
142 public Type getType(int n) {
143 return Type.tType(getString(n));
144 }
145
146 /**
147 * get the type of constant given an index
148 */
149 public int getConstantType(int n) {
150 return types[n];
151 }
152
153 /**
154 * get the n-th constant from the constant pool
155 */
156 public Object getConstant(int n, Environment env) {
157 int constant_type = getConstantType(n);
158 switch (constant_type) {
159 case CONSTANT_INTEGER:
160 case CONSTANT_FLOAT:
161 case CONSTANT_LONG:
162 case CONSTANT_DOUBLE:
163 return getValue(n);
164
165 case CONSTANT_CLASS:
166 return getDeclaration(env, n);
167
168 case CONSTANT_STRING:
169 return getString(getInteger(n));
170
171 case CONSTANT_FIELD:
172 case CONSTANT_METHOD:
173 case CONSTANT_INTERFACEMETHOD:
174 try {
175 int key = getInteger(n);
176 ClassDefinition clazz =
177 getDeclaration(env, key >> 16).getClassDefinition(env);
178 int name_and_type = getInteger(key & 0xFFFF);
179 Identifier id = getIdentifier(name_and_type >> 16);
180 Type type = getType(name_and_type & 0xFFFF);
181
182 for (MemberDefinition field = clazz.getFirstMatch(id);
183 field != null;
184 field = field.getNextMatch()) {
185 Type field_type = field.getType();
186 if ((constant_type == CONSTANT_FIELD)
187 ? (field_type == type)
188 : (field_type.equalArguments(type)))
189 return field;
190 }
191 } catch (ClassNotFound e) {
192 }
193 return null;
194
195 default:
196 throw new ClassFormatError("invalid constant type: " +
197 constant_type);
198 }
199 }
200
201
202 /**
203 * Get a list of dependencies, ie: all the classes referenced in this
204 * constant pool.
205 */
206 public Vector getDependencies(Environment env) {
207 Vector v = new Vector();
208 for (int i = 1 ; i < cpool.length ; i++) {
209 switch(types[i]) {
210 case CONSTANT_CLASS:
211 v.addElement(getDeclarationFromName(env, getInteger(i)));
212 break;
213 }
214 }
215 return v;
216 }
217
218 Hashtable indexHashObject, indexHashAscii;
219 Vector MoreStuff;
220
221 /**
222 * Find the index of an Object in the constant pool
223 */
224 public int indexObject(Object obj, Environment env) {
225 if (indexHashObject == null)
226 createIndexHash(env);
227 Integer result = (Integer)indexHashObject.get(obj);
228 if (result == null)
229 throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " +
230 obj.getClass() + " in constant pool");
231 return result.intValue();
232 }
233
234 /**
235 * Find the index of an ascii string in the constant pool. If it's not in
236 * the constant pool, then add it at the end.
237 */
238 public int indexString(String string, Environment env) {
239 if (indexHashObject == null)
240 createIndexHash(env);
241 Integer result = (Integer)indexHashAscii.get(string);
242 if (result == null) {
243 if (MoreStuff == null) MoreStuff = new Vector();
244 result = new Integer(cpool.length + MoreStuff.size());
245 MoreStuff.addElement(string);
246 indexHashAscii.put(string, result);
247 }
248 return result.intValue();
249 }
250
251 /**
252 * Create a hash table of all the items in the constant pool that could
253 * possibly be referenced from the outside.
254 */
255
256 public void createIndexHash(Environment env) {
257 indexHashObject = new Hashtable();
258 indexHashAscii = new Hashtable();
259 for (int i = 1; i < cpool.length; i++) {
260 if (types[i] == CONSTANT_UTF8) {
261 indexHashAscii.put(cpool[i], new Integer(i));
262 } else {
263 try {
264 indexHashObject.put(getConstant(i, env), new Integer(i));
265 } catch (ClassFormatError e) { }
266 }
267 }
268 }
269
270
271 /**
272 * Write out the contents of the constant pool, including any additions
273 * that have been added.
274 */
275 public void write(DataOutputStream out, Environment env) throws IOException {
276 int length = cpool.length;
277 if (MoreStuff != null)
278 length += MoreStuff.size();
279 out.writeShort(length);
280 for (int i = 1 ; i < cpool.length; i++) {
281 int type = types[i];
282 Object x = cpool[i];
283 out.writeByte(type);
284 switch (type) {
285 case CONSTANT_UTF8:
286 out.writeUTF((String) x);
287 break;
288 case CONSTANT_INTEGER:
289 out.writeInt(((Number)x).intValue());
290 break;
291 case CONSTANT_FLOAT:
292 out.writeFloat(((Number)x).floatValue());
293 break;
294 case CONSTANT_LONG:
295 out.writeLong(((Number)x).longValue());
296 i++;
297 break;
298 case CONSTANT_DOUBLE:
299 out.writeDouble(((Number)x).doubleValue());
300 i++;
301 break;
302 case CONSTANT_CLASS:
303 case CONSTANT_STRING:
304 out.writeShort(((Number)x).intValue());
305 break;
306 case CONSTANT_FIELD:
307 case CONSTANT_METHOD:
308 case CONSTANT_INTERFACEMETHOD:
309 case CONSTANT_NAMEANDTYPE: {
310 int value = ((Number)x).intValue();
311 out.writeShort(value >> 16);
312 out.writeShort(value & 0xFFFF);
313 break;
314 }
315 default:
316 throw new ClassFormatError("invalid constant type: "
317 + (int)types[i]);
318 }
319 }
320 for (int i = cpool.length; i < length; i++) {
321 String string = (String)(MoreStuff.elementAt(i - cpool.length));
322 out.writeByte(CONSTANT_UTF8);
323 out.writeUTF(string);
324 }
325 }
326
327}