com.j2biz.pencil.ClassNameReader.java Source code

Java tutorial

Introduction

Here is the source code for com.j2biz.pencil.ClassNameReader.java

Source

/* 
 * "Pencil - Log message compiler" is (c) 2004 Andreas Siebert (j2biz community)
 *
 * Author: Andreas Siebert.
 *  
 * This file is part of "Pencil - Log message compiler".
 *
 * "Pencil - Log message compiler" is free software; 
 * you can redistribute it and/or modify it under the terms of the GNU 
 * General Public License as published by the Free Software Foundation; 
 * either version 2 of the License, or (at your option) any later version.
 *
 * "Pencil - Log message compiler" 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with "Pencil - Logger message compiler"; if not, 
 * write to the Free Software Foundation, Inc., 59 Temple Place, 
 * Suite 330, Boston, MA  02111-1307  USA
 * 
 */
package com.j2biz.pencil;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;

/**
 * 
 * This class is haevy based on the code from the ClassReader of the ASM-Project
 * 
 * @author Andreas Siebert
 * 
 * (c) 2004 by Andreas Siebert / j2biz.com
 */
public class ClassNameReader {

    /**
     * The type of CONSTANT_Class constant pool items.
     */

    final static int CLASS = 7;

    /**
     * The type of CONSTANT_Fieldref constant pool items.
     */

    final static int FIELD = 9;

    /**
     * The type of CONSTANT_Methodref constant pool items.
     */

    final static int METH = 10;

    /**
     * The type of CONSTANT_InterfaceMethodref constant pool items.
     */

    final static int IMETH = 11;

    /**
     * The type of CONSTANT_String constant pool items.
     */

    final static int STR = 8;

    /**
     * The type of CONSTANT_Integer constant pool items.
     */

    final static int INT = 3;

    /**
     * The type of CONSTANT_Float constant pool items.
     */

    final static int FLOAT = 4;

    /**
     * The type of CONSTANT_Long constant pool items.
     */

    final static int LONG = 5;

    /**
     * The type of CONSTANT_Double constant pool items.
     */

    final static int DOUBLE = 6;

    /**
     * The type of CONSTANT_NameAndType constant pool items.
     */

    final static int NAME_TYPE = 12;

    /**
     * The type of CONSTANT_Utf8 constant pool items.
     */

    final static int UTF8 = 1;

    /**
     * @param b
     */
    public ClassNameReader() {
        ;
    }

    public String readClassName(final InputStream in) throws IOException {
        byte[] buffer = IOUtils.toByteArray(in);
        return readClassName(buffer);
    }

    public int readClassVersion(final byte[] byteBuffer) {
        return readInt(byteBuffer, 4);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor,
     *      org.objectweb.asm.Attribute[], boolean)
     */
    public String readClassName(final byte[] byteBuffer) {
        int sizeOfConstantPool = readUnsignedShort(byteBuffer, 8);

        int index = 10;
        int max = 0;
        int[] itemIdxs = new int[sizeOfConstantPool];

        for (int i = 1; i < sizeOfConstantPool; ++i) {
            itemIdxs[i] = index + 1;

            int tag = byteBuffer[index];
            int size;
            switch (tag) {
            case FIELD:
            case METH:
            case IMETH:
            case INT:
            case FLOAT:
            case NAME_TYPE:
                size = 5;
                break;
            case LONG:
            case DOUBLE:
                size = 9;
                ++i;
                break;
            case UTF8:
                size = 3 + readUnsignedShort(byteBuffer, index + 1);
                max = (size > max ? size : max);
                break;
            case CLASS:
                size = 3;
                break;
            default:
                size = 3;
                break;
            }

            index += size;
        }

        final char[] stringChars = new char[max];
        final int classInfoIdx = index + 2;

        final String className = readClassName(byteBuffer, itemIdxs, classInfoIdx, stringChars);

        return className;
    }

    public String readClassName(byte[] byteCode, int[] items, int classInfoIdx, final char[] buf) {
        int classNameIdx = items[readUnsignedShort(byteCode, classInfoIdx)];
        int utfIdx = items[readUnsignedShort(byteCode, classNameIdx)];

        // reads the length of the string (in bytes, not characters)
        int utfLen = readUnsignedShort(byteCode, utfIdx);
        utfIdx += 2;

        // parses the string bytes
        int endIndex = utfIdx + utfLen;

        int strLen = 0;
        int c, d, e;
        while (utfIdx < endIndex) {
            c = byteCode[utfIdx++] & 0xFF;
            switch (c >> 4) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                // 0xxxxxxx
                buf[strLen++] = (char) c;
                break;
            case 12:
            case 13:
                // 110x xxxx 10xx xxxx
                d = byteCode[utfIdx++];
                buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
                break;
            default:
                // 1110 xxxx 10xx xxxx 10xx xxxx
                d = byteCode[utfIdx++];
                e = byteCode[utfIdx++];
                buf[strLen++] = (char) (((c & 0x0F) << 12) | ((d & 0x3F) << 6) | (e & 0x3F));
                break;
            }
        }

        final String className = new String(buf, 0, strLen);
        return className;
    }

    private int readUnsignedShort(final byte[] byteCode, final int index) {
        return ((byteCode[index] & 0xFF) << 8) | (byteCode[index + 1] & 0xFF);
    }

    public int readInt(final byte[] byteCode, final int index) {
        return ((byteCode[index] & 0xFF) << 24) | ((byteCode[index + 1] & 0xFF) << 16)
                | ((byteCode[index + 2] & 0xFF) << 8) | (byteCode[index + 3] & 0xFF);
    }
}