--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/BinaryConstantPool.java Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 in the LICENSE file that
+ * accompanied this code).
+ *
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.java;
+
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.util.Vector;
+import java.util.Hashtable;
+
+/**
+ * This class is used to represent a constant table once
+ * it is read from a class file.
+ *
+ * WARNING: The contents of this source file are not part of any
+ * supported API. Code that depends on them does so at its own risk:
+ * they are subject to change or removal without notice.
+ */
+public final
+class BinaryConstantPool implements Constants {
+ private byte types[];
+ private Object cpool[];
+
+ /**
+ * Constructor
+ */
+ BinaryConstantPool(DataInputStream in) throws IOException {
+ // JVM 4.1 ClassFile.constant_pool_count
+ types = new byte[in.readUnsignedShort()];
+ cpool = new Object[types.length];
+ for (int i = 1 ; i < cpool.length ; i++) {
+ int j = i;
+ // JVM 4.4 cp_info.tag
+ switch(types[i] = in.readByte()) {
+ case CONSTANT_UTF8:
+ cpool[i] = in.readUTF();
+ break;
+
+ case CONSTANT_INTEGER:
+ cpool[i] = in.readInt();
+ break;
+ case CONSTANT_FLOAT:
+ cpool[i] = new Float(in.readFloat());
+ break;
+ case CONSTANT_LONG:
+ cpool[i++] = 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
+ // or JVM 4.4.1 CONSTANT_Class_info.name_index
+ cpool[i] =in.readUnsignedShort();
+ break;
+
+ case CONSTANT_FIELD:
+ case CONSTANT_METHOD:
+ case CONSTANT_INTERFACEMETHOD:
+ case CONSTANT_NAMEANDTYPE:
+ // JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index
+ cpool[i] = (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;
+ }
+
+ /**
+ * get a integer
+ */
+ public int getInteger(int n) {
+ return (n == 0) ? 0 : ((Number)cpool[n]).intValue();
+ }
+
+ /**
+ * get a value
+ */
+ public Object getValue(int n) {
+ return (n == 0) ? null : cpool[n];
+ }
+
+ /**
+ * get a string
+ */
+ public String getString(int n) {
+ return (n == 0) ? null : (String)cpool[n];
+ }
+
+ /**
+ * get an identifier
+ */
+ public Identifier getIdentifier(int n) {
+ return (n == 0) ? null : Identifier.lookup(getString(n));
+ }
+
+ /**
+ * get class declaration
+ */
+ public ClassDeclaration getDeclarationFromName(Environment env, int n) {
+ return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.')));
+ }
+
+ /**
+ * get class declaration
+ */
+ public ClassDeclaration getDeclaration(Environment env, int n) {
+ return (n == 0) ? null : getDeclarationFromName(env, getInteger(n));
+ }
+
+ /**
+ * get a type from a type signature
+ */
+ public Type getType(int n) {
+ return Type.tType(getString(n));
+ }
+
+ /**
+ * get the type of constant given an index
+ */
+ public int getConstantType(int n) {
+ return types[n];
+ }
+
+ /**
+ * get the n-th constant from the constant pool
+ */
+ 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);
+ }
+ }
+
+
+ /**
+ * Get a list of dependencies, ie: all the classes referenced in this
+ * constant pool.
+ */
+ public Vector<ClassDeclaration> getDependencies(Environment env) {
+ Vector<ClassDeclaration> 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<Object, Integer> indexHashObject;
+ Hashtable<Object, Integer> indexHashAscii;
+ Vector<String> MoreStuff;
+
+ /**
+ * Find the index of an Object in the constant pool
+ */
+ public int indexObject(Object obj, Environment env) {
+ if (indexHashObject == null)
+ createIndexHash(env);
+ Integer result = indexHashObject.get(obj);
+ if (result == null)
+ throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " +
+ obj.getClass() + " in constant pool");
+ return result.intValue();
+ }
+
+ /**
+ * Find the index of an ascii string in the constant pool. If it's not in
+ * the constant pool, then add it at the end.
+ */
+ public int indexString(String string, Environment env) {
+ if (indexHashObject == null)
+ createIndexHash(env);
+ Integer result = indexHashAscii.get(string);
+ if (result == null) {
+ if (MoreStuff == null) MoreStuff = new Vector<>();
+ result = 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], i);
+ } else {
+ try {
+ indexHashObject.put(getConstant(i, env), i);
+ } catch (ClassFormatError e) { }
+ }
+ }
+ }
+
+
+ /**
+ * Write out the contents of the constant pool, including any additions
+ * that have been added.
+ */
+ 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 = MoreStuff.elementAt(i - cpool.length);
+ out.writeByte(CONSTANT_UTF8);
+ out.writeUTF(string);
+ }
+ }
+
+}