| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.tools.java;  | 
 | 
 | 
 | 
import java.io.IOException;  | 
 | 
import java.io.DataInputStream;  | 
 | 
import java.io.DataOutputStream;  | 
 | 
import java.util.Vector;  | 
 | 
import java.util.Hashtable;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public final  | 
 | 
class BinaryConstantPool implements Constants { | 
 | 
    private byte types[];  | 
 | 
    private Object cpool[];  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    BinaryConstantPool(DataInputStream in) throws IOException { | 
 | 
          | 
 | 
        types = new byte[in.readUnsignedShort()];  | 
 | 
        cpool = new Object[types.length];  | 
 | 
        for (int i = 1 ; i < cpool.length ; i++) { | 
 | 
            int j = i;  | 
 | 
              | 
 | 
            switch(types[i] = in.readByte()) { | 
 | 
              case CONSTANT_UTF8:  | 
 | 
                cpool[i] = in.readUTF();  | 
 | 
                break;  | 
 | 
 | 
 | 
              case CONSTANT_INTEGER:  | 
 | 
                cpool[i] = new Integer(in.readInt());  | 
 | 
                break;  | 
 | 
              case CONSTANT_FLOAT:  | 
 | 
                cpool[i] = new Float(in.readFloat());  | 
 | 
                break;  | 
 | 
              case CONSTANT_LONG:  | 
 | 
                cpool[i++] = new Long(in.readLong());  | 
 | 
                break;  | 
 | 
              case CONSTANT_DOUBLE:  | 
 | 
                cpool[i++] = new Double(in.readDouble());  | 
 | 
                break;  | 
 | 
 | 
 | 
              case CONSTANT_CLASS:  | 
 | 
              case CONSTANT_STRING:  | 
 | 
                // JVM 4.4.3 CONSTANT_String_info.string_index  | 
 | 
                  | 
 | 
                cpool[i] = new Integer(in.readUnsignedShort());  | 
 | 
                break;  | 
 | 
 | 
 | 
              case CONSTANT_FIELD:  | 
 | 
              case CONSTANT_METHOD:  | 
 | 
              case CONSTANT_INTERFACEMETHOD:  | 
 | 
              case CONSTANT_NAMEANDTYPE:  | 
 | 
                  | 
 | 
                cpool[i] = new Integer((in.readUnsignedShort() << 16) | in.readUnsignedShort());  | 
 | 
                break;  | 
 | 
 | 
 | 
              case CONSTANT_METHODHANDLE:  | 
 | 
                cpool[i] = readBytes(in, 3);  | 
 | 
                break;  | 
 | 
              case CONSTANT_METHODTYPE:  | 
 | 
                cpool[i] = readBytes(in, 2);  | 
 | 
                break;  | 
 | 
              case CONSTANT_INVOKEDYNAMIC:  | 
 | 
                cpool[i] = readBytes(in, 4);  | 
 | 
                break;  | 
 | 
 | 
 | 
              case 0:  | 
 | 
              default:  | 
 | 
                throw new ClassFormatError("invalid constant type: " + (int)types[i]); | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private byte[] readBytes(DataInputStream in, int cnt) throws IOException { | 
 | 
        byte[] b = new byte[cnt];  | 
 | 
        in.readFully(b);  | 
 | 
        return b;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public int getInteger(int n) { | 
 | 
        return (n == 0) ? 0 : ((Number)cpool[n]).intValue();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public Object getValue(int n) { | 
 | 
        return (n == 0) ? null : cpool[n];  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public String getString(int n) { | 
 | 
        return (n == 0) ? null : (String)cpool[n];  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public Identifier getIdentifier(int n) { | 
 | 
        return (n == 0) ? null : Identifier.lookup(getString(n));  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public ClassDeclaration getDeclarationFromName(Environment env, int n) { | 
 | 
        return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.'))); | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public ClassDeclaration getDeclaration(Environment env, int n) { | 
 | 
        return (n == 0) ? null : getDeclarationFromName(env, getInteger(n));  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public Type getType(int n) { | 
 | 
        return Type.tType(getString(n));  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public int getConstantType(int n) { | 
 | 
        return types[n];  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public Object getConstant(int n, Environment env) { | 
 | 
        int constant_type = getConstantType(n);  | 
 | 
        switch (constant_type) { | 
 | 
            case CONSTANT_INTEGER:  | 
 | 
            case CONSTANT_FLOAT:  | 
 | 
            case CONSTANT_LONG:  | 
 | 
            case CONSTANT_DOUBLE:  | 
 | 
            case CONSTANT_METHODHANDLE:  | 
 | 
            case CONSTANT_METHODTYPE:  | 
 | 
            case CONSTANT_INVOKEDYNAMIC:  | 
 | 
                return getValue(n);  | 
 | 
 | 
 | 
            case CONSTANT_CLASS:  | 
 | 
                return getDeclaration(env, n);  | 
 | 
 | 
 | 
            case CONSTANT_STRING:  | 
 | 
                return getString(getInteger(n));  | 
 | 
 | 
 | 
            case CONSTANT_FIELD:  | 
 | 
            case CONSTANT_METHOD:  | 
 | 
            case CONSTANT_INTERFACEMETHOD:  | 
 | 
                try { | 
 | 
                    int key = getInteger(n);  | 
 | 
                    ClassDefinition clazz =  | 
 | 
                        getDeclaration(env, key >> 16).getClassDefinition(env);  | 
 | 
                    int name_and_type = getInteger(key & 0xFFFF);  | 
 | 
                    Identifier id = getIdentifier(name_and_type >> 16);  | 
 | 
                    Type type = getType(name_and_type & 0xFFFF);  | 
 | 
 | 
 | 
                    for (MemberDefinition field = clazz.getFirstMatch(id);  | 
 | 
                         field != null;  | 
 | 
                         field = field.getNextMatch()) { | 
 | 
                        Type field_type = field.getType();  | 
 | 
                        if ((constant_type == CONSTANT_FIELD)  | 
 | 
                            ? (field_type == type)  | 
 | 
                            : (field_type.equalArguments(type)))  | 
 | 
                            return field;  | 
 | 
                    }  | 
 | 
                } catch (ClassNotFound e) { | 
 | 
                }  | 
 | 
                return null;  | 
 | 
 | 
 | 
            default:  | 
 | 
                throw new ClassFormatError("invalid constant type: " + | 
 | 
                                              constant_type);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Vector getDependencies(Environment env) { | 
 | 
        Vector v = new Vector();  | 
 | 
        for (int i = 1 ; i < cpool.length ; i++) { | 
 | 
            switch(types[i]) { | 
 | 
              case CONSTANT_CLASS:  | 
 | 
                v.addElement(getDeclarationFromName(env, getInteger(i)));  | 
 | 
                break;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return v;  | 
 | 
    }  | 
 | 
 | 
 | 
    Hashtable indexHashObject, indexHashAscii;  | 
 | 
    Vector MoreStuff;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public int indexObject(Object obj, Environment env) { | 
 | 
        if (indexHashObject == null)  | 
 | 
            createIndexHash(env);  | 
 | 
        Integer result = (Integer)indexHashObject.get(obj);  | 
 | 
        if (result == null)  | 
 | 
            throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " + | 
 | 
                                obj.getClass() + " in constant pool");  | 
 | 
        return result.intValue();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public int indexString(String string, Environment env) { | 
 | 
        if (indexHashObject == null)  | 
 | 
            createIndexHash(env);  | 
 | 
        Integer result = (Integer)indexHashAscii.get(string);  | 
 | 
        if (result == null) { | 
 | 
            if (MoreStuff == null) MoreStuff = new Vector();  | 
 | 
            result = new Integer(cpool.length + MoreStuff.size());  | 
 | 
            MoreStuff.addElement(string);  | 
 | 
            indexHashAscii.put(string, result);  | 
 | 
        }  | 
 | 
        return result.intValue();  | 
 | 
    }  | 
 | 
 | 
 | 
    /**  | 
 | 
     * Create a hash table of all the items in the constant pool that could  | 
 | 
     * possibly be referenced from the outside.  | 
 | 
     */  | 
 | 
 | 
 | 
    public void createIndexHash(Environment env) { | 
 | 
        indexHashObject = new Hashtable();  | 
 | 
        indexHashAscii = new Hashtable();  | 
 | 
        for (int i = 1; i < cpool.length; i++) { | 
 | 
            if (types[i] == CONSTANT_UTF8) { | 
 | 
                indexHashAscii.put(cpool[i], new Integer(i));  | 
 | 
            } else { | 
 | 
                try { | 
 | 
                    indexHashObject.put(getConstant(i, env), new Integer(i));  | 
 | 
                } catch (ClassFormatError e) { } | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void write(DataOutputStream out, Environment env) throws IOException { | 
 | 
        int length = cpool.length;  | 
 | 
        if (MoreStuff != null)  | 
 | 
            length += MoreStuff.size();  | 
 | 
        out.writeShort(length);  | 
 | 
        for (int i = 1 ; i < cpool.length; i++) { | 
 | 
            int type = types[i];  | 
 | 
            Object x = cpool[i];  | 
 | 
            out.writeByte(type);  | 
 | 
            switch (type) { | 
 | 
                case CONSTANT_UTF8:  | 
 | 
                    out.writeUTF((String) x);  | 
 | 
                    break;  | 
 | 
                case CONSTANT_INTEGER:  | 
 | 
                    out.writeInt(((Number)x).intValue());  | 
 | 
                    break;  | 
 | 
                case CONSTANT_FLOAT:  | 
 | 
                    out.writeFloat(((Number)x).floatValue());  | 
 | 
                    break;  | 
 | 
                case CONSTANT_LONG:  | 
 | 
                    out.writeLong(((Number)x).longValue());  | 
 | 
                    i++;  | 
 | 
                    break;  | 
 | 
                case CONSTANT_DOUBLE:  | 
 | 
                    out.writeDouble(((Number)x).doubleValue());  | 
 | 
                    i++;  | 
 | 
                    break;  | 
 | 
                case CONSTANT_CLASS:  | 
 | 
                case CONSTANT_STRING:  | 
 | 
                    out.writeShort(((Number)x).intValue());  | 
 | 
                    break;  | 
 | 
                case CONSTANT_FIELD:  | 
 | 
                case CONSTANT_METHOD:  | 
 | 
                case CONSTANT_INTERFACEMETHOD:  | 
 | 
                case CONSTANT_NAMEANDTYPE: { | 
 | 
                    int value = ((Number)x).intValue();  | 
 | 
                    out.writeShort(value >> 16);  | 
 | 
                    out.writeShort(value & 0xFFFF);  | 
 | 
                    break;  | 
 | 
                }  | 
 | 
                case CONSTANT_METHODHANDLE:  | 
 | 
                case CONSTANT_METHODTYPE:  | 
 | 
                case CONSTANT_INVOKEDYNAMIC:  | 
 | 
                    out.write((byte[])x, 0, ((byte[])x).length);  | 
 | 
                    break;  | 
 | 
                default:  | 
 | 
                     throw new ClassFormatError("invalid constant type: " | 
 | 
                                                   + (int)types[i]);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        for (int i = cpool.length; i < length; i++) { | 
 | 
            String string = (String)(MoreStuff.elementAt(i - cpool.length));  | 
 | 
            out.writeByte(CONSTANT_UTF8);  | 
 | 
            out.writeUTF(string);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
}  |