jdk/test/java/lang/instrument/ilib/ClassReaderWriter.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/ilib/ClassReaderWriter.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  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.
+ *
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package ilib;
+
+class ClassReaderWriter implements RuntimeConstants {
+
+    int codeAttributeIndex;
+    int lineNumberAttributeIndex;
+    int localVarAttributeIndex;
+
+    private final byte[] orig;
+    private final byte[] gen;
+    private final int sectionLength;
+
+    private static final int GROWTH_FACTOR = 2;
+    private static final int SECTIONS = 2;
+    private static final String codeAttributeName = "Code";
+    private static final String lineNumberAttributeName = "LineNumberTable";
+    private static final String localVarAttributeName = "LocalVariableTable";
+
+    private int[] genSectionPos = new int[SECTIONS];
+
+    private int inputPos = 0;
+    private int genPos = 0;
+    private int markPos = 0;
+    private int currentSection = 0;
+
+    private String[] constantPool;
+
+    ClassReaderWriter(byte[] orig) {
+        this.orig = orig;
+        sectionLength = orig.length * GROWTH_FACTOR;
+        gen = new byte[sectionLength * SECTIONS];
+        for (int section = 0; section < SECTIONS; ++section) {
+            genSectionPos[section] = section * sectionLength;
+        }
+    }
+
+    int setSection(int section) {
+        int prevSection = currentSection;
+        genSectionPos[prevSection] = genPos;
+        genPos = genSectionPos[section];
+        currentSection = section;
+        return prevSection;
+    }
+
+    byte[] result() {
+        int section;
+        int totalLength = 0;
+
+        setSection(0); // save current section
+
+        for (section = 0; section < SECTIONS; ++section) {
+            int sectionStart = section * sectionLength;
+            int sectionGenLength = genSectionPos[section] - sectionStart;
+            totalLength += sectionGenLength;
+        }
+
+        byte[] newcf = new byte[totalLength];
+        int written = 0;
+        for (section = 0; section < SECTIONS; ++section) {
+            int sectionStart = section * sectionLength;
+            int sectionGenLength = genSectionPos[section] - sectionStart;
+            System.arraycopy(gen, sectionStart, newcf, written, sectionGenLength);
+            written += sectionGenLength;
+        }
+
+        return newcf;
+    }
+
+    int readU1() {
+        return ((int)orig[inputPos++]) & 0xFF;
+    }
+
+    int readU2() {
+        int res = readU1();
+        return (res << 8) + readU1();
+    }
+
+    short readS2() {
+        int res = readU1();
+        return (short)((res << 8) + readU1());
+    }
+
+    int readU4() {
+        int res = readU2();
+        return (res << 16) + readU2();
+    }
+
+    void writeU1(int val) {
+        gen[genPos++] = (byte)val;
+    }
+
+    void writeU2(int val) {
+        writeU1(val >> 8);
+        writeU1(val & 0xFF);
+    }
+
+    void writeU4(int val) {
+        writeU2(val >> 16);
+        writeU2(val & 0xFFFF);
+    }
+
+    int copyU1() {
+        int value = readU1();
+        writeU1(value);
+        return value;
+    }
+
+    int copyU2() {
+        int value = readU2();
+        writeU2(value);
+        return value;
+    }
+
+    int copyU4() {
+        int value = readU4();
+        writeU4(value);
+        return value;
+    }
+
+    void copy(int count) {
+        for (int i = 0; i < count; ++i) {
+            gen[genPos++] = orig[inputPos++];
+        }
+    }
+
+    void skip(int count) {
+        inputPos += count;
+    }
+
+    byte[] readBytes(int count) {
+        byte[] bytes = new byte[count];
+        for (int i = 0; i < count; ++i) {
+            bytes[i] = orig[inputPos++];
+        }
+        return bytes;
+    }
+
+    void writeBytes(byte[] bytes) {
+        for (int i = 0; i < bytes.length; ++i) {
+            gen[genPos++] = bytes[i];
+        }
+    }
+
+    byte[] inputBytes() {
+        return orig;
+    }
+
+    int inputPosition() {
+        return inputPos;
+    }
+
+    void setInputPosition(int pos) {
+        inputPos = pos;
+    }
+
+    void markLocalPositionStart() {
+        markPos = inputPos;
+    }
+
+    int localPosition() {
+        return inputPos - markPos;
+    }
+
+    void rewind() {
+        setInputPosition(markPos);
+    }
+
+    int generatedPosition() {
+        return genPos;
+    }
+
+    void randomAccessWriteU2(int pos, int val) {
+        int savePos = genPos;
+        genPos = pos;
+        writeU2(val);
+        genPos = savePos;
+    }
+
+    void randomAccessWriteU4(int pos, int val) {
+        int savePos = genPos;
+        genPos = pos;
+        writeU4(val);
+        genPos = savePos;
+    }
+
+    String constantPoolString(int index) {
+        return constantPool[index];
+    }
+
+    void copyConstantPool(int constantPoolCount){
+        // copy const pool
+        constantPool = new String[constantPoolCount];
+        // index zero not in class file
+        for (int i = 1; i < constantPoolCount; ++i) {
+            int tag = readU1();
+            writeU1(tag);
+            switch (tag) {
+                case CONSTANT_CLASS:
+                case CONSTANT_STRING:
+                    copy(2);
+                    break;
+                case CONSTANT_FIELD:
+                case CONSTANT_METHOD:
+                case CONSTANT_INTERFACEMETHOD:
+                case CONSTANT_INTEGER:
+                case CONSTANT_FLOAT:
+                case CONSTANT_NAMEANDTYPE:
+                    copy(4);
+                    break;
+                case CONSTANT_LONG:
+                case CONSTANT_DOUBLE:
+                    copy(8);
+                    ++i;  // these take two CP entries - duh!
+                    break;
+                case CONSTANT_UTF8:
+                    int len = copyU2();
+                    byte[] utf8 = readBytes(len);
+                    String str = null; // null to shut the compiler up
+                    try {
+                        str = new String(utf8, "UTF-8");
+                    } catch (Exception exc) {
+                        throw new Error("CP exception: " + exc);
+                    }
+                    constantPool[i] = str;
+                    if (str.equals(codeAttributeName)) {
+                        codeAttributeIndex = i;
+                    } else if (str.equals(lineNumberAttributeName)) {
+                        lineNumberAttributeIndex = i;
+                    } else if (str.equals(localVarAttributeName)) {
+                        localVarAttributeIndex = i;
+                    }
+                    writeBytes(utf8);
+                    break;
+                default:
+                    throw new Error(i + " unexpected CP tag: " + tag);
+            }
+        }
+    }
+
+}