/*
 * Copyright 2002-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.axis.utils.bytecode;

import org.apache.axis.utils.Messages;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 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. <p>
 *
 * 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. <p>
 *
 * don't get tricky, it's the bare minimum.  Instances of this class
 * are not threadsafe -- don't share them. <p>
 *
 * @author Edwin Smith, Macromedia
 */
public class ClassReader extends ByteArrayInputStream {
    // constants values that appear in java class files,
    // from jvm spec 2nd ed, section 4.4, pp 103
    private static final int CONSTANT_Class = 7;
    private static final int CONSTANT_Fieldref = 9;
    private static final int CONSTANT_Methodref = 10;
    private static final int CONSTANT_InterfaceMethodref = 11;
    private static final int CONSTANT_String = 8;
    private static final int CONSTANT_Integer = 3;
    private static final int CONSTANT_Float = 4;
    private static final int CONSTANT_Long = 5;
    private static final int CONSTANT_Double = 6;
    private static final int CONSTANT_NameAndType = 12;
    private static final int CONSTANT_Utf8 = 1;
    /**
     * 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 int[] cpoolIndex;
    private Object[] cpool;

    private Map attrMethods;

    /**
     * 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
     */
    protected static byte[] getBytes(Class c) 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();
        }
    }

    static String classDescriptorToName(String desc) {
        return desc.replace('/', '.');
    }

    protected static Map findAttributeReaders(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 String getSignature(Member method, 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();
    }

    private static void addDescriptor(StringBuffer b, 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(';');
        }
    }


    /**
     * @return the next unsigned 16 bit value
     */
    protected final int readShort() {
        return (read() << 8) | read();
    }

    /**
     * @return the next signed 32 bit value
     */
    protected final int readInt() {
        return (read() << 24) | (read() << 16) | (read() << 8) | read();
    }

    /**
     * skip n bytes in the input stream.
     */
    protected void skipFully(int n) throws IOException {
        while (n > 0) {
            int c = (int) skip(n);
            if (c <= 0)
                throw new EOFException(Messages.getMessage("unexpectedEOF00"));
            n -= c;
        }
    }

    protected final Member resolveMethod(int index) throws IOException, ClassNotFoundException, NoSuchMethodException {
        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 Field resolveField(int i) throws IOException, ClassNotFoundException, NoSuchFieldException {
        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;
        }
    }

    private static class NameAndType {
        String name;
        String type;

        public NameAndType(String name, String type) {
            this.name = name;
            this.type = type;
        }
    }

    protected final NameAndType resolveNameAndType(int i) throws IOException {
        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 Class resolveClass(int i) throws IOException, ClassNotFoundException {
        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 String resolveUtf8(int i) throws IOException {
        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 void readCpool() throws IOException {
        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 void skipAttributes() throws IOException {
        int count = readShort();
        for (int i = 0; i < count; i++) {
            readShort(); // name index
            skipFully(readInt());
        }
    }

    /**
     * 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.
     */
    protected final void readAttributes() throws IOException {
        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);
            }
        }
    }

    /**
     * read a code attribute
     * @throws IOException
     */
    public void readCode() 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 ClassReader(byte buf[], Map attrMethods) {
        super(buf);

        this.attrMethods = attrMethods;
    }
}

