001: /*
002: * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.java;
027:
028: import java.io.IOException;
029: import java.io.DataInputStream;
030: import java.io.DataOutputStream;
031: import java.util.Vector;
032: import java.util.Hashtable;
033:
034: /**
035: * This class is used to represent a constant table once
036: * it is read from a class file.
037: *
038: * WARNING: The contents of this source file are not part of any
039: * supported API. Code that depends on them does so at its own risk:
040: * they are subject to change or removal without notice.
041: */
042: public final class BinaryConstantPool implements Constants {
043: private byte types[];
044: private Object cpool[];
045:
046: /**
047: * Constructor
048: */
049: BinaryConstantPool(DataInputStream in) throws IOException {
050: // JVM 4.1 ClassFile.constant_pool_count
051: types = new byte[in.readUnsignedShort()];
052: cpool = new Object[types.length];
053: for (int i = 1; i < cpool.length; i++) {
054: int j = i;
055: // JVM 4.4 cp_info.tag
056: switch (types[i] = in.readByte()) {
057: case CONSTANT_UTF8:
058: cpool[i] = in.readUTF();
059: break;
060:
061: case CONSTANT_INTEGER:
062: cpool[i] = new Integer(in.readInt());
063: break;
064: case CONSTANT_FLOAT:
065: cpool[i] = new Float(in.readFloat());
066: break;
067: case CONSTANT_LONG:
068: cpool[i++] = new Long(in.readLong());
069: break;
070: case CONSTANT_DOUBLE:
071: cpool[i++] = new Double(in.readDouble());
072: break;
073:
074: case CONSTANT_CLASS:
075: case CONSTANT_STRING:
076: // JVM 4.4.3 CONSTANT_String_info.string_index
077: // or JVM 4.4.1 CONSTANT_Class_info.name_index
078: cpool[i] = new Integer(in.readUnsignedShort());
079: break;
080:
081: case CONSTANT_FIELD:
082: case CONSTANT_METHOD:
083: case CONSTANT_INTERFACEMETHOD:
084: case CONSTANT_NAMEANDTYPE:
085: // JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index
086: cpool[i] = new Integer((in.readUnsignedShort() << 16)
087: | in.readUnsignedShort());
088: break;
089:
090: case 0:
091: default:
092: throw new ClassFormatError("invalid constant type: "
093: + (int) types[i]);
094: }
095: }
096: }
097:
098: /**
099: * get a integer
100: */
101: public int getInteger(int n) {
102: return (n == 0) ? 0 : ((Number) cpool[n]).intValue();
103: }
104:
105: /**
106: * get a value
107: */
108: public Object getValue(int n) {
109: return (n == 0) ? null : cpool[n];
110: }
111:
112: /**
113: * get a string
114: */
115: public String getString(int n) {
116: return (n == 0) ? null : (String) cpool[n];
117: }
118:
119: /**
120: * get an identifier
121: */
122: public Identifier getIdentifier(int n) {
123: return (n == 0) ? null : Identifier.lookup(getString(n));
124: }
125:
126: /**
127: * get class declaration
128: */
129: public ClassDeclaration getDeclarationFromName(Environment env,
130: int n) {
131: return (n == 0) ? null : env.getClassDeclaration(Identifier
132: .lookup(getString(n).replace('/', '.')));
133: }
134:
135: /**
136: * get class declaration
137: */
138: public ClassDeclaration getDeclaration(Environment env, int n) {
139: return (n == 0) ? null : getDeclarationFromName(env,
140: getInteger(n));
141: }
142:
143: /**
144: * get a type from a type signature
145: */
146: public Type getType(int n) {
147: return Type.tType(getString(n));
148: }
149:
150: /**
151: * get the type of constant given an index
152: */
153: public int getConstantType(int n) {
154: return types[n];
155: }
156:
157: /**
158: * get the n-th constant from the constant pool
159: */
160: public Object getConstant(int n, Environment env) {
161: int constant_type = getConstantType(n);
162: switch (constant_type) {
163: case CONSTANT_INTEGER:
164: case CONSTANT_FLOAT:
165: case CONSTANT_LONG:
166: case CONSTANT_DOUBLE:
167: return getValue(n);
168:
169: case CONSTANT_CLASS:
170: return getDeclaration(env, n);
171:
172: case CONSTANT_STRING:
173: return getString(getInteger(n));
174:
175: case CONSTANT_FIELD:
176: case CONSTANT_METHOD:
177: case CONSTANT_INTERFACEMETHOD:
178: try {
179: int key = getInteger(n);
180: ClassDefinition clazz = getDeclaration(env, key >> 16)
181: .getClassDefinition(env);
182: int name_and_type = getInteger(key & 0xFFFF);
183: Identifier id = getIdentifier(name_and_type >> 16);
184: Type type = getType(name_and_type & 0xFFFF);
185:
186: for (MemberDefinition field = clazz.getFirstMatch(id); field != null; field = field
187: .getNextMatch()) {
188: Type field_type = field.getType();
189: if ((constant_type == CONSTANT_FIELD) ? (field_type == type)
190: : (field_type.equalArguments(type)))
191: return field;
192: }
193: } catch (ClassNotFound e) {
194: }
195: return null;
196:
197: default:
198: throw new ClassFormatError("invalid constant type: "
199: + constant_type);
200: }
201: }
202:
203: /**
204: * Get a list of dependencies, ie: all the classes referenced in this
205: * constant pool.
206: */
207: public Vector getDependencies(Environment env) {
208: Vector v = new Vector();
209: for (int i = 1; i < cpool.length; i++) {
210: switch (types[i]) {
211: case CONSTANT_CLASS:
212: v
213: .addElement(getDeclarationFromName(env,
214: getInteger(i)));
215: break;
216: }
217: }
218: return v;
219: }
220:
221: Hashtable indexHashObject, indexHashAscii;
222: Vector MoreStuff;
223:
224: /**
225: * Find the index of an Object in the constant pool
226: */
227: public int indexObject(Object obj, Environment env) {
228: if (indexHashObject == null)
229: createIndexHash(env);
230: Integer result = (Integer) indexHashObject.get(obj);
231: if (result == null)
232: throw new IndexOutOfBoundsException("Cannot find object "
233: + obj + " of type " + obj.getClass()
234: + " in constant pool");
235: return result.intValue();
236: }
237:
238: /**
239: * Find the index of an ascii string in the constant pool. If it's not in
240: * the constant pool, then add it at the end.
241: */
242: public int indexString(String string, Environment env) {
243: if (indexHashObject == null)
244: createIndexHash(env);
245: Integer result = (Integer) indexHashAscii.get(string);
246: if (result == null) {
247: if (MoreStuff == null)
248: MoreStuff = new Vector();
249: result = new Integer(cpool.length + MoreStuff.size());
250: MoreStuff.addElement(string);
251: indexHashAscii.put(string, result);
252: }
253: return result.intValue();
254: }
255:
256: /**
257: * Create a hash table of all the items in the constant pool that could
258: * possibly be referenced from the outside.
259: */
260:
261: public void createIndexHash(Environment env) {
262: indexHashObject = new Hashtable();
263: indexHashAscii = new Hashtable();
264: for (int i = 1; i < cpool.length; i++) {
265: if (types[i] == CONSTANT_UTF8) {
266: indexHashAscii.put(cpool[i], new Integer(i));
267: } else {
268: try {
269: indexHashObject.put(getConstant(i, env),
270: new Integer(i));
271: } catch (ClassFormatError e) {
272: }
273: }
274: }
275: }
276:
277: /**
278: * Write out the contents of the constant pool, including any additions
279: * that have been added.
280: */
281: public void write(DataOutputStream out, Environment env)
282: throws IOException {
283: int length = cpool.length;
284: if (MoreStuff != null)
285: length += MoreStuff.size();
286: out.writeShort(length);
287: for (int i = 1; i < cpool.length; i++) {
288: int type = types[i];
289: Object x = cpool[i];
290: out.writeByte(type);
291: switch (type) {
292: case CONSTANT_UTF8:
293: out.writeUTF((String) x);
294: break;
295: case CONSTANT_INTEGER:
296: out.writeInt(((Number) x).intValue());
297: break;
298: case CONSTANT_FLOAT:
299: out.writeFloat(((Number) x).floatValue());
300: break;
301: case CONSTANT_LONG:
302: out.writeLong(((Number) x).longValue());
303: i++;
304: break;
305: case CONSTANT_DOUBLE:
306: out.writeDouble(((Number) x).doubleValue());
307: i++;
308: break;
309: case CONSTANT_CLASS:
310: case CONSTANT_STRING:
311: out.writeShort(((Number) x).intValue());
312: break;
313: case CONSTANT_FIELD:
314: case CONSTANT_METHOD:
315: case CONSTANT_INTERFACEMETHOD:
316: case CONSTANT_NAMEANDTYPE: {
317: int value = ((Number) x).intValue();
318: out.writeShort(value >> 16);
319: out.writeShort(value & 0xFFFF);
320: break;
321: }
322: default:
323: throw new ClassFormatError("invalid constant type: "
324: + (int) types[i]);
325: }
326: }
327: for (int i = cpool.length; i < length; i++) {
328: String string = (String) (MoreStuff.elementAt(i
329: - cpool.length));
330: out.writeByte(CONSTANT_UTF8);
331: out.writeUTF(string);
332: }
333: }
334:
335: }
|