/* * @(#)ConstantPool.java 1.9 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package com.sun.xlet.ixc; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import java.io.DataOutputStream; import java.io.IOException; class ConstantPool { // We write the CP out in this order: classes, methods, fields, // nameAndType, strings. private Hashtable classes = new Hashtable(11); // Hashtable<String, String>, becomes Hashtable<String, Integer> // on write private Vector fields = new Vector(); // Vector<String[3]> private Vector methods = new Vector(); // Vector<String[3]> private Vector ifMethods = new Vector(); // Interface methods private Vector nameAndType = new Vector(); // Vector<String[2]>A private Hashtable stringConstants = new Hashtable(11); // This is the list of CONSTANT_String_info things // Hashtable<String, String>, becomes Hashtable<String, Integer> // on write private Hashtable strings = new Hashtable(51); // Hashtable<String, String>, becomes Hashtable<String, Integer> // on write void addStringConstant(String s) { addString(s); stringConstants.put(s, s); } void addString(String s) { strings.put(s, s); } void addClass(String s) { addString(s); classes.put(s, s); } boolean hasClass(String s) { return classes.get(s) != null; } private void addNameAndType(String name, String type) { addString(name); addString(type); nameAndType.addElement(new String[] { name, type } ); } int lookupString(Object s) { Integer i = (Integer) strings.get(s); if (i == null) { throw new RuntimeException("" + s + " not found in constant pool"); } return i.intValue(); } int lookupStringConstant(Object s) { Integer i = (Integer) stringConstants.get(s); if (i == null) { throw new RuntimeException("string constant " + s + " not found in constant pool"); } return i.intValue(); } int lookupClass(Object s) { Integer i = (Integer) classes.get(s); if (i == null) { throw new RuntimeException("class " + s + " not found in constant pool"); } return i.intValue(); } int lookupMethod(String className, String name, String type) { for (int i = 0; i < methods.size(); i++) { String[] el = (String[]) methods.elementAt(i); if (className.equals(el[0]) && name.equals(el[1]) && type.equals(el[2])) { return 1 + classes.size() + fields.size() + i; } } throw new RuntimeException("Method <" + className + ". " + name + " : " + type + "> not found in constant pool"); } int lookupField(String className, String name, String type) { for (int i = 0; i < fields.size(); i++) { String[] el = (String[]) fields.elementAt(i); if (className.equals(el[0]) && name.equals(el[1]) && type.equals(el[2])) { return 1 + classes.size() + i; } } throw new RuntimeException("Field <" + className + ". " + name + " : " + type + "> not found in constant pool"); } int lookupNameAndType(String name, String type) { for (int i = 0; i < nameAndType.size(); i++) { String[] el = (String[]) nameAndType.elementAt(i); if (name.equals(el[0]) && type.equals(el[1])) { return 1 + classes.size() + fields.size() + methods.size() + ifMethods.size() + i; } } throw new RuntimeException("Name and type <" + name + ", " + type + "> not found in constant pool"); } void addField(String className, String name, String type) { addString(className); addNameAndType(name, type); fields.addElement(new String[] { className, name, type } ); } void addMethodReference(String className, String name, String type) { addString(className); addNameAndType(name, type); methods.addElement(new String[] { className, name, type } ); } // // Add an interface method reference // void addIfMethodReference(String className, String name, String type) { addString(className); addNameAndType(name, type); ifMethods.addElement(new String[] { className, name, type } ); } void write(DataOutputStream dos) throws IOException { // Assign an entry number to each class, stringConstant and string // CP entry. Remmeber, counting starts at 1! int num = 1; String[] classesArr = new String[classes.size()]; { int i = 0; for (Enumeration e = classes.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); classesArr[i++] = key; classes.put(key, new Integer(num++)); } } num += fields.size() + methods.size() + ifMethods.size() + nameAndType.size(); String[] stringConstantArr = new String[stringConstants.size()]; { int i = 0; for (Enumeration e = stringConstants.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); stringConstantArr[i++] = key; stringConstants.put(key, new Integer(num++)); } } String[] stringArr = new String[strings.size()]; { int i = 0; for (Enumeration e = strings.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); stringArr[i++] = key; strings.put(key, new Integer(num++)); } } // Now num is the correct constant_pool_count, one greater than // the number of entries. Yes, entires really are numbered // 1..(constant_pool_count-1)! dos.writeShort(num); for (int i = 0; i < classesArr.length; i++) { dos.writeByte(7); // CONSTANT_Class dos.writeShort(lookupString(classesArr[i])); } for (int i = 0; i < fields.size(); i++) { String[] sa = (String[]) fields.elementAt(i); dos.writeByte(9); // CONSTANT_Fieldref dos.writeShort(lookupClass(sa[0])); dos.writeShort(lookupNameAndType(sa[1], sa[2])); } for (int i = 0; i < methods.size(); i++) { String[] sa = (String[]) methods.elementAt(i); dos.writeByte(10); // CONSTANT_Methodref dos.writeShort(lookupClass(sa[0])); dos.writeShort(lookupNameAndType(sa[1], sa[2])); } for (int i = 0; i < ifMethods.size(); i++) { String[] sa = (String[]) ifMethods.elementAt(i); dos.writeByte(11); // CONSTANT_InterfaceMethodref dos.writeShort(lookupClass(sa[0])); dos.writeShort(lookupNameAndType(sa[1], sa[2])); } for (int i = 0; i < nameAndType.size(); i++) { String[] sa = (String[]) nameAndType.elementAt(i); dos.writeByte(12); // CONSTANT_NameAndtype dos.writeShort(lookupString(sa[0])); dos.writeShort(lookupString(sa[1])); } for (int i = 0; i < stringConstantArr.length; i++) { dos.writeByte(0x8); // CONSTANT_String_info dos.writeShort(lookupString(stringConstantArr[i])); } for (int i = 0; i < stringArr.length; i++) { dos.writeByte(1); // CONSTANT_Utf8 dos.writeUTF(stringArr[i]); } } }