FileDocCategorySizeDatePackage
ClassReader.javaAPI DocApache Axis 1.414127Sat Apr 22 18:57:26 BST 2006org.apache.axis.utils.bytecode

ClassReader

public class ClassReader extends ByteArrayInputStream
This is the class file reader for obtaining the parameter names for declared methods in a class. The class must have debugging attributes for us to obtain this information.

This does not work for inherited methods. To obtain parameter names for inherited methods, you must use a paramReader for the class that originally declared the method.

don't get tricky, it's the bare minimum. Instances of this class are not threadsafe -- don't share them.

author
Edwin Smith, Macromedia

Fields Summary
private static final int
CONSTANT_Class
private static final int
CONSTANT_Fieldref
private static final int
CONSTANT_Methodref
private static final int
CONSTANT_InterfaceMethodref
private static final int
CONSTANT_String
private static final int
CONSTANT_Integer
private static final int
CONSTANT_Float
private static final int
CONSTANT_Long
private static final int
CONSTANT_Double
private static final int
CONSTANT_NameAndType
private static final int
CONSTANT_Utf8
private int[]
cpoolIndex
the constant pool. constant pool indices in the class file directly index into this array. The value stored in this array is the position in the class file where that constant begins.
private Object[]
cpool
private Map
attrMethods
Constructors Summary
protected ClassReader(byte[] buf, Map attrMethods)

        super(buf);

        this.attrMethods = attrMethods;
    
Methods Summary
private static voidaddDescriptor(java.lang.StringBuffer b, java.lang.Class c)

        if (c.isPrimitive()) {
            if (c == void.class)
                b.append('V");
            else if (c == int.class)
                b.append('I");
            else if (c == boolean.class)
                b.append('Z");
            else if (c == byte.class)
                b.append('B");
            else if (c == short.class)
                b.append('S");
            else if (c == long.class)
                b.append('J");
            else if (c == char.class)
                b.append('C");
            else if (c == float.class)
                b.append('F");
            else if (c == double.class) b.append('D");
        } else if (c.isArray()) {
            b.append('[");
            addDescriptor(b, c.getComponentType());
        } else {
            b.append('L").append(c.getName().replace('.", '/")).append(';");
        }
    
static java.lang.StringclassDescriptorToName(java.lang.String desc)

        return desc.replace('/", '.");
    
protected static java.util.MapfindAttributeReaders(java.lang.Class c)

        HashMap map = new HashMap();
        Method[] methods = c.getMethods();

        for (int i = 0; i < methods.length; i++) {
            String name = methods[i].getName();
            if (name.startsWith("read") && methods[i].getReturnType() == void.class) {
                map.put(name.substring(4), methods[i]);
            }
        }

        return map;
    
protected static byte[]getBytes(java.lang.Class c)
load the bytecode for a given class, by using the class's defining classloader and assuming that for a class named P.C, the bytecodes are in a resource named /P/C.class.

param
c the class of interest
return
a byte array containing the bytecode
throws
IOException


                                                     
           
        InputStream fin = c.getResourceAsStream('/" + c.getName().replace('.", '/") + ".class");
        if (fin == null) {
            throw new IOException(
                    Messages.getMessage("cantLoadByecode", c.getName()));
        }
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int actual;
            do {
                actual = fin.read(buf);
                if (actual > 0) {
                    out.write(buf, 0, actual);
                }
            } while (actual > 0);
            return out.toByteArray();
        } finally {
            fin.close();
        }
    
protected static java.lang.StringgetSignature(java.lang.reflect.Member method, java.lang.Class[] paramTypes)

        // compute the method descriptor

        StringBuffer b = new StringBuffer((method instanceof Method) ? method.getName() : "<init>");
        b.append('(");

        for (int i = 0; i < paramTypes.length; i++) {
            addDescriptor(b, paramTypes[i]);
        }

        b.append(')");
        if (method instanceof Method) {
            addDescriptor(b, ((Method) method).getReturnType());
        } else if (method instanceof Constructor) {
            addDescriptor(b, void.class);
        }

        return b.toString();
    
protected final voidreadAttributes()
read an attributes array. the elements of a class file that can contain attributes are: fields, methods, the class itself, and some other types of attributes.

        int count = readShort();
        for (int i = 0; i < count; i++) {
            int nameIndex = readShort(); // name index
            int attrLen = readInt();
            int curPos = pos;

            String attrName = resolveUtf8(nameIndex);

            Method m = (Method) attrMethods.get(attrName);

            if (m != null) {
                try {
                    m.invoke(this, new Object[]{});
                } catch (IllegalAccessException e) {
                    pos = curPos;
                    skipFully(attrLen);
                } catch (InvocationTargetException e) {
                    try {
                        throw e.getTargetException();
                    } catch (Error ex) {
                        throw ex;
                    } catch (RuntimeException ex) {
                        throw ex;
                    } catch (IOException ex) {
                        throw ex;
                    } catch (Throwable ex) {
                        pos = curPos;
                        skipFully(attrLen);
                    }
                }
            } else {
                // don't care what attribute this is
                skipFully(attrLen);
            }
        }
    
public voidreadCode()
read a code attribute

throws
IOException

        readShort(); // max stack
        readShort(); // max locals
        skipFully(readInt()); // code
        skipFully(8 * readShort()); // exception table

        // read the code attributes (recursive).  This is where
        // we will find the LocalVariableTable attribute.
        readAttributes();
    
protected final voidreadCpool()

        int count = readShort(); // cpool count
        cpoolIndex = new int[count];
        cpool = new Object[count];
        for (int i = 1; i < count; i++) {
            int c = read();
            cpoolIndex[i] = super.pos;
            switch (c) // constant pool tag
            {
                case CONSTANT_Fieldref:
                case CONSTANT_Methodref:
                case CONSTANT_InterfaceMethodref:
                case CONSTANT_NameAndType:

                    readShort(); // class index or (12) name index
                    // fall through

                case CONSTANT_Class:
                case CONSTANT_String:

                    readShort(); // string index or class index
                    break;

                case CONSTANT_Long:
                case CONSTANT_Double:

                    readInt(); // hi-value

                    // see jvm spec section 4.4.5 - double and long cpool
                    // entries occupy two "slots" in the cpool table.
                    i++;
                    // fall through

                case CONSTANT_Integer:
                case CONSTANT_Float:

                    readInt(); // value
                    break;

                case CONSTANT_Utf8:

                    int len = readShort();
                    skipFully(len);
                    break;

                default:
                    // corrupt class file
                    throw new IllegalStateException(
                            Messages.getMessage("unexpectedBytes00"));
            }
        }
    
protected final intreadInt()

return
the next signed 32 bit value

        return (read() << 24) | (read() << 16) | (read() << 8) | read();
    
protected final intreadShort()

return
the next unsigned 16 bit value

        return (read() << 8) | read();
    
protected final java.lang.ClassresolveClass(int i)

        int oldPos = pos;
        try {
            Class c = (Class) cpool[i];
            if (c == null) {
                pos = cpoolIndex[i];
                String name = resolveUtf8(readShort());
                cpool[i] = c = Class.forName(classDescriptorToName(name));
            }
            return c;
        } finally {
            pos = oldPos;
        }
    
protected final java.lang.reflect.FieldresolveField(int i)

        int oldPos = pos;
        try {
            Field f = (Field) cpool[i];
            if (f == null) {
                pos = cpoolIndex[i];
                Class owner = resolveClass(readShort());
                NameAndType nt = resolveNameAndType(readShort());
                cpool[i] = f = owner.getDeclaredField(nt.name);
            }
            return f;
        } finally {
            pos = oldPos;
        }
    
protected final java.lang.reflect.MemberresolveMethod(int index)

        int oldPos = pos;
        try {
            Member m = (Member) cpool[index];
            if (m == null) {
                pos = cpoolIndex[index];
                Class owner = resolveClass(readShort());
                NameAndType nt = resolveNameAndType(readShort());
                String signature = nt.name + nt.type;
                if (nt.name.equals("<init>")) {
                    Constructor[] ctors = owner.getConstructors();
                    for (int i = 0; i < ctors.length; i++) {
                        String sig = getSignature(ctors[i], ctors[i].getParameterTypes());
                        if (sig.equals(signature)) {
                            cpool[index] = m = ctors[i];
                            return m;
                        }
                    }
                } else {
                    Method[] methods = owner.getDeclaredMethods();
                    for (int i = 0; i < methods.length; i++) {
                        String sig = getSignature(methods[i], methods[i].getParameterTypes());
                        if (sig.equals(signature)) {
                            cpool[index] = m = methods[i];
                            return m;
                        }
                    }
                }
                throw new NoSuchMethodException(signature);
            }
            return m;
        } finally {
            pos = oldPos;
        }

    
protected final org.apache.axis.utils.bytecode.ClassReader$NameAndTyperesolveNameAndType(int i)

        int oldPos = pos;
        try {
            NameAndType nt = (NameAndType) cpool[i];
            if (nt == null) {
                pos = cpoolIndex[i];
                String name = resolveUtf8(readShort());
                String type = resolveUtf8(readShort());
                cpool[i] = nt = new NameAndType(name, type);
            }
            return nt;
        } finally {
            pos = oldPos;
        }
    
protected final java.lang.StringresolveUtf8(int i)

        int oldPos = pos;
        try {
            String s = (String) cpool[i];
            if (s == null) {
                pos = cpoolIndex[i];
                int len = readShort();
                skipFully(len);
                cpool[i] = s = new String(buf, pos - len, len, "utf-8");
            }
            return s;
        } finally {
            pos = oldPos;
        }
    
protected final voidskipAttributes()

        int count = readShort();
        for (int i = 0; i < count; i++) {
            readShort(); // name index
            skipFully(readInt());
        }
    
protected voidskipFully(int n)
skip n bytes in the input stream.

        while (n > 0) {
            int c = (int) skip(n);
            if (c <= 0)
                throw new EOFException(Messages.getMessage("unexpectedEOF00"));
            n -= c;
        }